r24153: Convert call_trans2setfsinfo to the new API.
[samba.git] / source / smbd / trans2.c
1 /* 
2    Unix SMB/CIFS implementation.
3    SMB transaction2 handling
4    Copyright (C) Jeremy Allison                 1994-2007
5    Copyright (C) Stefan (metze) Metzmacher      2003
6    Copyright (C) Volker Lendecke                2005-2007
7    Copyright (C) Steve French                   2005
8    Copyright (C) James Peach                    2007
9
10    Extensively modified by Andrew Tridgell, 1995
11
12    This program is free software; you can redistribute it and/or modify
13    it under the terms of the GNU General Public License as published by
14    the Free Software Foundation; either version 3 of the License, or
15    (at your option) any later version.
16    
17    This program is distributed in the hope that it will be useful,
18    but WITHOUT ANY WARRANTY; without even the implied warranty of
19    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20    GNU General Public License for more details.
21    
22    You should have received a copy of the GNU General Public License
23    along with this program.  If not, see <http://www.gnu.org/licenses/>.
24 */
25
26 #include "includes.h"
27
28 extern int max_send;
29 extern enum protocol_types Protocol;
30 extern int smb_read_error;
31 extern uint32 global_client_caps;
32 extern struct current_user current_user;
33
34 #define get_file_size(sbuf) ((sbuf).st_size)
35 #define DIR_ENTRY_SAFETY_MARGIN 4096
36
37 static char *store_file_unix_basic(connection_struct *conn,
38                                 char *pdata,
39                                 files_struct *fsp,
40                                 const SMB_STRUCT_STAT *psbuf);
41
42 static char *store_file_unix_basic_info2(connection_struct *conn,
43                                 char *pdata,
44                                 files_struct *fsp,
45                                 const SMB_STRUCT_STAT *psbuf);
46
47 /********************************************************************
48  Roundup a value to the nearest allocation roundup size boundary.
49  Only do this for Windows clients.
50 ********************************************************************/
51
52 SMB_BIG_UINT smb_roundup(connection_struct *conn, SMB_BIG_UINT val)
53 {
54         SMB_BIG_UINT rval = lp_allocation_roundup_size(SNUM(conn));
55
56         /* Only roundup for Windows clients. */
57         enum remote_arch_types ra_type = get_remote_arch();
58         if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
59                 val = SMB_ROUNDUP(val,rval);
60         }
61         return val;
62 }
63
64 /********************************************************************
65  Given a stat buffer return the allocated size on disk, taking into
66  account sparse files.
67 ********************************************************************/
68
69 SMB_BIG_UINT get_allocation_size(connection_struct *conn, files_struct *fsp, const SMB_STRUCT_STAT *sbuf)
70 {
71         SMB_BIG_UINT ret;
72
73         if(S_ISDIR(sbuf->st_mode)) {
74                 return 0;
75         }
76
77 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
78         ret = (SMB_BIG_UINT)STAT_ST_BLOCKSIZE * (SMB_BIG_UINT)sbuf->st_blocks;
79 #else
80         ret = (SMB_BIG_UINT)get_file_size(*sbuf);
81 #endif
82
83         if (fsp && fsp->initial_allocation_size)
84                 ret = MAX(ret,fsp->initial_allocation_size);
85
86         return smb_roundup(conn, ret);
87 }
88
89 /****************************************************************************
90  Utility functions for dealing with extended attributes.
91 ****************************************************************************/
92
93 /****************************************************************************
94  Refuse to allow clients to overwrite our private xattrs.
95 ****************************************************************************/
96
97 static BOOL samba_private_attr_name(const char *unix_ea_name)
98 {
99         static const char *prohibited_ea_names[] = {
100                 SAMBA_POSIX_INHERITANCE_EA_NAME,
101                 SAMBA_XATTR_DOS_ATTRIB,
102                 NULL
103         };
104
105         int i;
106
107         for (i = 0; prohibited_ea_names[i]; i++) {
108                 if (strequal( prohibited_ea_names[i], unix_ea_name))
109                         return True;
110         }
111         return False;
112 }
113
114 /****************************************************************************
115  Get one EA value. Fill in a struct ea_struct.
116 ****************************************************************************/
117
118 static BOOL get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
119                                 const char *fname, char *ea_name, struct ea_struct *pea)
120 {
121         /* Get the value of this xattr. Max size is 64k. */
122         size_t attr_size = 256;
123         char *val = NULL;
124         ssize_t sizeret;
125
126  again:
127
128         val = TALLOC_REALLOC_ARRAY(mem_ctx, val, char, attr_size);
129         if (!val) {
130                 return False;
131         }
132
133         if (fsp && fsp->fh->fd != -1) {
134                 sizeret = SMB_VFS_FGETXATTR(fsp, fsp->fh->fd, ea_name, val, attr_size);
135         } else {
136                 sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
137         }
138
139         if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
140                 attr_size = 65536;
141                 goto again;
142         }
143
144         if (sizeret == -1) {
145                 return False;
146         }
147
148         DEBUG(10,("get_ea_value: EA %s is of length %u: ", ea_name, (unsigned int)sizeret));
149         dump_data(10, (uint8 *)val, sizeret);
150
151         pea->flags = 0;
152         if (strnequal(ea_name, "user.", 5)) {
153                 pea->name = &ea_name[5];
154         } else {
155                 pea->name = ea_name;
156         }
157         pea->value.data = (unsigned char *)val;
158         pea->value.length = (size_t)sizeret;
159         return True;
160 }
161
162 /****************************************************************************
163  Return a linked list of the total EA's. Plus the total size
164 ****************************************************************************/
165
166 static struct ea_list *get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
167                                         const char *fname, size_t *pea_total_len)
168 {
169         /* Get a list of all xattrs. Max namesize is 64k. */
170         size_t ea_namelist_size = 1024;
171         char *ea_namelist;
172         char *p;
173         ssize_t sizeret;
174         int i;
175         struct ea_list *ea_list_head = NULL;
176
177         *pea_total_len = 0;
178
179         if (!lp_ea_support(SNUM(conn))) {
180                 return NULL;
181         }
182
183         for (i = 0, ea_namelist = TALLOC_ARRAY(mem_ctx, char, ea_namelist_size); i < 6;
184              ea_namelist = TALLOC_REALLOC_ARRAY(mem_ctx, ea_namelist, char, ea_namelist_size), i++) {
185
186                 if (!ea_namelist) {
187                         return NULL;
188                 }
189
190                 if (fsp && fsp->fh->fd != -1) {
191                         sizeret = SMB_VFS_FLISTXATTR(fsp, fsp->fh->fd, ea_namelist, ea_namelist_size);
192                 } else {
193                         sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist, ea_namelist_size);
194                 }
195
196                 if (sizeret == -1 && errno == ERANGE) {
197                         ea_namelist_size *= 2;
198                 } else {
199                         break;
200                 }
201         }
202
203         if (sizeret == -1)
204                 return NULL;
205
206         DEBUG(10,("get_ea_list_from_file: ea_namelist size = %u\n", (unsigned int)sizeret ));
207
208         if (sizeret) {
209                 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p) + 1) {
210                         struct ea_list *listp;
211
212                         if (strnequal(p, "system.", 7) || samba_private_attr_name(p))
213                                 continue;
214                 
215                         listp = TALLOC_P(mem_ctx, struct ea_list);
216                         if (!listp)
217                                 return NULL;
218
219                         if (!get_ea_value(mem_ctx, conn, fsp, fname, p, &listp->ea)) {
220                                 return NULL;
221                         }
222
223                         {
224                                 fstring dos_ea_name;
225                                 push_ascii_fstring(dos_ea_name, listp->ea.name);
226                                 *pea_total_len += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
227                                 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len = %u\n",
228                                         (unsigned int)*pea_total_len, dos_ea_name,
229                                         (unsigned int)listp->ea.value.length ));
230                         }
231                         DLIST_ADD_END(ea_list_head, listp, struct ea_list *);
232                 }
233                 /* Add on 4 for total length. */
234                 if (*pea_total_len) {
235                         *pea_total_len += 4;
236                 }
237         }
238
239         DEBUG(10,("get_ea_list_from_file: total_len = %u\n", (unsigned int)*pea_total_len));
240         return ea_list_head;
241 }
242
243 /****************************************************************************
244  Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
245  that was filled.
246 ****************************************************************************/
247
248 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
249         connection_struct *conn, struct ea_list *ea_list)
250 {
251         unsigned int ret_data_size = 4;
252         char *p = pdata;
253
254         SMB_ASSERT(total_data_size >= 4);
255
256         if (!lp_ea_support(SNUM(conn))) {
257                 SIVAL(pdata,4,0);
258                 return 4;
259         }
260
261         for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
262                 size_t dos_namelen;
263                 fstring dos_ea_name;
264                 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
265                 dos_namelen = strlen(dos_ea_name);
266                 if (dos_namelen > 255 || dos_namelen == 0) {
267                         break;
268                 }
269                 if (ea_list->ea.value.length > 65535) {
270                         break;
271                 }
272                 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
273                         break;
274                 }
275
276                 /* We know we have room. */
277                 SCVAL(p,0,ea_list->ea.flags);
278                 SCVAL(p,1,dos_namelen);
279                 SSVAL(p,2,ea_list->ea.value.length);
280                 fstrcpy(p+4, dos_ea_name);
281                 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
282
283                 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
284                 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
285         }
286
287         ret_data_size = PTR_DIFF(p, pdata);
288         DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
289         SIVAL(pdata,0,ret_data_size);
290         return ret_data_size;
291 }
292
293 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const char *fname)
294 {
295         size_t total_ea_len = 0;
296         TALLOC_CTX *mem_ctx = NULL;
297
298         if (!lp_ea_support(SNUM(conn))) {
299                 return 0;
300         }
301         mem_ctx = talloc_init("estimate_ea_size");
302         (void)get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
303         talloc_destroy(mem_ctx);
304         return total_ea_len;
305 }
306
307 /****************************************************************************
308  Ensure the EA name is case insensitive by matching any existing EA name.
309 ****************************************************************************/
310
311 static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
312 {
313         size_t total_ea_len;
314         TALLOC_CTX *mem_ctx = talloc_init("canonicalize_ea_name");
315         struct ea_list *ea_list = get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
316
317         for (; ea_list; ea_list = ea_list->next) {
318                 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
319                         DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
320                                 &unix_ea_name[5], ea_list->ea.name));
321                         safe_strcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-6);
322                         break;
323                 }
324         }
325         talloc_destroy(mem_ctx);
326 }
327
328 /****************************************************************************
329  Set or delete an extended attribute.
330 ****************************************************************************/
331
332 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp, const char *fname, struct ea_list *ea_list)
333 {
334         if (!lp_ea_support(SNUM(conn))) {
335                 return NT_STATUS_EAS_NOT_SUPPORTED;
336         }
337
338         for (;ea_list; ea_list = ea_list->next) {
339                 int ret;
340                 fstring unix_ea_name;
341
342                 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
343                 fstrcat(unix_ea_name, ea_list->ea.name);
344
345                 canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
346
347                 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
348
349                 if (samba_private_attr_name(unix_ea_name)) {
350                         DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
351                         return NT_STATUS_ACCESS_DENIED;
352                 }
353
354                 if (ea_list->ea.value.length == 0) {
355                         /* Remove the attribute. */
356                         if (fsp && (fsp->fh->fd != -1)) {
357                                 DEBUG(10,("set_ea: deleting ea name %s on file %s by file descriptor.\n",
358                                         unix_ea_name, fsp->fsp_name));
359                                 ret = SMB_VFS_FREMOVEXATTR(fsp, fsp->fh->fd, unix_ea_name);
360                         } else {
361                                 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
362                                         unix_ea_name, fname));
363                                 ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
364                         }
365 #ifdef ENOATTR
366                         /* Removing a non existent attribute always succeeds. */
367                         if (ret == -1 && errno == ENOATTR) {
368                                 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
369                                                 unix_ea_name));
370                                 ret = 0;
371                         }
372 #endif
373                 } else {
374                         if (fsp && (fsp->fh->fd != -1)) {
375                                 DEBUG(10,("set_ea: setting ea name %s on file %s by file descriptor.\n",
376                                         unix_ea_name, fsp->fsp_name));
377                                 ret = SMB_VFS_FSETXATTR(fsp, fsp->fh->fd, unix_ea_name,
378                                                         ea_list->ea.value.data, ea_list->ea.value.length, 0);
379                         } else {
380                                 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
381                                         unix_ea_name, fname));
382                                 ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name,
383                                                         ea_list->ea.value.data, ea_list->ea.value.length, 0);
384                         }
385                 }
386
387                 if (ret == -1) {
388 #ifdef ENOTSUP
389                         if (errno == ENOTSUP) {
390                                 return NT_STATUS_EAS_NOT_SUPPORTED;
391                         }
392 #endif
393                         return map_nt_error_from_unix(errno);
394                 }
395
396         }
397         return NT_STATUS_OK;
398 }
399 /****************************************************************************
400  Read a list of EA names from an incoming data buffer. Create an ea_list with them.
401 ****************************************************************************/
402
403 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
404 {
405         struct ea_list *ea_list_head = NULL;
406         size_t offset = 0;
407
408         while (offset + 2 < data_size) {
409                 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
410                 unsigned int namelen = CVAL(pdata,offset);
411
412                 offset++; /* Go past the namelen byte. */
413
414                 /* integer wrap paranioa. */
415                 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
416                                 (offset > data_size) || (namelen > data_size) ||
417                                 (offset + namelen >= data_size)) {
418                         break;
419                 }
420                 /* Ensure the name is null terminated. */
421                 if (pdata[offset + namelen] != '\0') {
422                         return NULL;
423                 }
424                 pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset]);
425                 if (!eal->ea.name) {
426                         return NULL;
427                 }
428
429                 offset += (namelen + 1); /* Go past the name + terminating zero. */
430                 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
431                 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
432         }
433
434         return ea_list_head;
435 }
436
437 /****************************************************************************
438  Read one EA list entry from the buffer.
439 ****************************************************************************/
440
441 struct ea_list *read_ea_list_entry(TALLOC_CTX *ctx, const char *pdata, size_t data_size, size_t *pbytes_used)
442 {
443         struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
444         uint16 val_len;
445         unsigned int namelen;
446
447         if (!eal) {
448                 return NULL;
449         }
450
451         if (data_size < 6) {
452                 return NULL;
453         }
454
455         eal->ea.flags = CVAL(pdata,0);
456         namelen = CVAL(pdata,1);
457         val_len = SVAL(pdata,2);
458
459         if (4 + namelen + 1 + val_len > data_size) {
460                 return NULL;
461         }
462
463         /* Ensure the name is null terminated. */
464         if (pdata[namelen + 4] != '\0') {
465                 return NULL;
466         }
467         pull_ascii_talloc(ctx, &eal->ea.name, pdata + 4);
468         if (!eal->ea.name) {
469                 return NULL;
470         }
471
472         eal->ea.value = data_blob_talloc(eal, NULL, (size_t)val_len + 1);
473         if (!eal->ea.value.data) {
474                 return NULL;
475         }
476
477         memcpy(eal->ea.value.data, pdata + 4 + namelen + 1, val_len);
478
479         /* Ensure we're null terminated just in case we print the value. */
480         eal->ea.value.data[val_len] = '\0';
481         /* But don't count the null. */
482         eal->ea.value.length--;
483
484         if (pbytes_used) {
485                 *pbytes_used = 4 + namelen + 1 + val_len;
486         }
487
488         DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal->ea.name));
489         dump_data(10, eal->ea.value.data, eal->ea.value.length);
490
491         return eal;
492 }
493
494 /****************************************************************************
495  Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
496 ****************************************************************************/
497
498 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
499 {
500         struct ea_list *ea_list_head = NULL;
501         size_t offset = 0;
502         size_t bytes_used = 0;
503
504         while (offset < data_size) {
505                 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
506
507                 if (!eal) {
508                         return NULL;
509                 }
510
511                 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
512                 offset += bytes_used;
513         }
514
515         return ea_list_head;
516 }
517
518 /****************************************************************************
519  Count the total EA size needed.
520 ****************************************************************************/
521
522 static size_t ea_list_size(struct ea_list *ealist)
523 {
524         fstring dos_ea_name;
525         struct ea_list *listp;
526         size_t ret = 0;
527
528         for (listp = ealist; listp; listp = listp->next) {
529                 push_ascii_fstring(dos_ea_name, listp->ea.name);
530                 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
531         }
532         /* Add on 4 for total length. */
533         if (ret) {
534                 ret += 4;
535         }
536
537         return ret;
538 }
539
540 /****************************************************************************
541  Return a union of EA's from a file list and a list of names.
542  The TALLOC context for the two lists *MUST* be identical as we steal
543  memory from one list to add to another. JRA.
544 ****************************************************************************/
545
546 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
547 {
548         struct ea_list *nlistp, *flistp;
549
550         for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
551                 for (flistp = file_list; flistp; flistp = flistp->next) {
552                         if (strequal(nlistp->ea.name, flistp->ea.name)) {
553                                 break;
554                         }
555                 }
556
557                 if (flistp) {
558                         /* Copy the data from this entry. */
559                         nlistp->ea.flags = flistp->ea.flags;
560                         nlistp->ea.value = flistp->ea.value;
561                 } else {
562                         /* Null entry. */
563                         nlistp->ea.flags = 0;
564                         ZERO_STRUCT(nlistp->ea.value);
565                 }
566         }
567
568         *total_ea_len = ea_list_size(name_list);
569         return name_list;
570 }
571
572 /****************************************************************************
573   Send the required number of replies back.
574   We assume all fields other than the data fields are
575   set correctly for the type of call.
576   HACK ! Always assumes smb_setup field is zero.
577 ****************************************************************************/
578
579 int send_trans2_replies(const char *inbuf,
580                         char *outbuf,
581                         int bufsize,
582                         const char *params, 
583                         int paramsize,
584                         const char *pdata,
585                         int datasize,
586                         int max_data_bytes)
587 {
588         /* As we are using a protocol > LANMAN1 then the max_send
589          variable must have been set in the sessetupX call.
590          This takes precedence over the max_xmit field in the
591          global struct. These different max_xmit variables should
592          be merged as this is now too confusing */
593
594         int data_to_send = datasize;
595         int params_to_send = paramsize;
596         int useable_space;
597         const char *pp = params;
598         const char *pd = pdata;
599         int params_sent_thistime, data_sent_thistime, total_sent_thistime;
600         int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
601         int data_alignment_offset = 0;
602
603         /* Initially set the wcnt area to be 10 - this is true for all trans2 replies */
604         
605         set_message(inbuf,outbuf,10,0,True);
606
607         /* Modify the data_to_send and datasize and set the error if
608            we're trying to send more than max_data_bytes. We still send
609            the part of the packet(s) that fit. Strange, but needed
610            for OS/2. */
611
612         if (max_data_bytes > 0 && datasize > max_data_bytes) {
613                 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
614                         max_data_bytes, datasize ));
615                 datasize = data_to_send = max_data_bytes;
616                 error_packet_set(outbuf,ERRDOS,ERRbufferoverflow,STATUS_BUFFER_OVERFLOW,__LINE__,__FILE__);
617         }
618
619         /* If there genuinely are no parameters or data to send just send the empty packet */
620
621         if(params_to_send == 0 && data_to_send == 0) {
622                 show_msg(outbuf);
623                 if (!send_smb(smbd_server_fd(),outbuf))
624                         exit_server_cleanly("send_trans2_replies: send_smb failed.");
625                 return 0;
626         }
627
628         /* When sending params and data ensure that both are nicely aligned */
629         /* Only do this alignment when there is also data to send - else
630                 can cause NT redirector problems. */
631
632         if (((params_to_send % 4) != 0) && (data_to_send != 0))
633                 data_alignment_offset = 4 - (params_to_send % 4);
634
635         /* Space is bufsize minus Netbios over TCP header minus SMB header */
636         /* The alignment_offset is to align the param bytes on an even byte
637                 boundary. NT 4.0 Beta needs this to work correctly. */
638
639         useable_space = bufsize - ((smb_buf(outbuf)+ alignment_offset+data_alignment_offset) - outbuf);
640
641         /* useable_space can never be more than max_send minus the alignment offset. */
642
643         useable_space = MIN(useable_space, max_send - (alignment_offset+data_alignment_offset));
644
645         while (params_to_send || data_to_send) {
646                 /* Calculate whether we will totally or partially fill this packet */
647
648                 total_sent_thistime = params_to_send + data_to_send + alignment_offset + data_alignment_offset;
649
650                 /* We can never send more than useable_space */
651                 /*
652                  * Note that 'useable_space' does not include the alignment offsets,
653                  * but we must include the alignment offsets in the calculation of
654                  * the length of the data we send over the wire, as the alignment offsets
655                  * are sent here. Fix from Marc_Jacobsen@hp.com.
656                  */
657
658                 total_sent_thistime = MIN(total_sent_thistime, useable_space+ alignment_offset + data_alignment_offset);
659
660                 set_message(inbuf, outbuf, 10, total_sent_thistime, True);
661
662                 /* Set total params and data to be sent */
663                 SSVAL(outbuf,smb_tprcnt,paramsize);
664                 SSVAL(outbuf,smb_tdrcnt,datasize);
665
666                 /* Calculate how many parameters and data we can fit into
667                  * this packet. Parameters get precedence
668                  */
669
670                 params_sent_thistime = MIN(params_to_send,useable_space);
671                 data_sent_thistime = useable_space - params_sent_thistime;
672                 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
673
674                 SSVAL(outbuf,smb_prcnt, params_sent_thistime);
675
676                 /* smb_proff is the offset from the start of the SMB header to the
677                         parameter bytes, however the first 4 bytes of outbuf are
678                         the Netbios over TCP header. Thus use smb_base() to subtract
679                         them from the calculation */
680
681                 SSVAL(outbuf,smb_proff,((smb_buf(outbuf)+alignment_offset) - smb_base(outbuf)));
682
683                 if(params_sent_thistime == 0)
684                         SSVAL(outbuf,smb_prdisp,0);
685                 else
686                         /* Absolute displacement of param bytes sent in this packet */
687                         SSVAL(outbuf,smb_prdisp,pp - params);
688
689                 SSVAL(outbuf,smb_drcnt, data_sent_thistime);
690                 if(data_sent_thistime == 0) {
691                         SSVAL(outbuf,smb_droff,0);
692                         SSVAL(outbuf,smb_drdisp, 0);
693                 } else {
694                         /* The offset of the data bytes is the offset of the
695                                 parameter bytes plus the number of parameters being sent this time */
696                         SSVAL(outbuf,smb_droff,((smb_buf(outbuf)+alignment_offset) - 
697                                 smb_base(outbuf)) + params_sent_thistime + data_alignment_offset);
698                         SSVAL(outbuf,smb_drdisp, pd - pdata);
699                 }
700
701                 /* Copy the param bytes into the packet */
702
703                 if(params_sent_thistime)
704                         memcpy((smb_buf(outbuf)+alignment_offset),pp,params_sent_thistime);
705
706                 /* Copy in the data bytes */
707                 if(data_sent_thistime)
708                         memcpy(smb_buf(outbuf)+alignment_offset+params_sent_thistime+
709                                 data_alignment_offset,pd,data_sent_thistime);
710
711                 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
712                         params_sent_thistime, data_sent_thistime, useable_space));
713                 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
714                         params_to_send, data_to_send, paramsize, datasize));
715
716                 /* Send the packet */
717                 show_msg(outbuf);
718                 if (!send_smb(smbd_server_fd(),outbuf))
719                         exit_server_cleanly("send_trans2_replies: send_smb failed.");
720
721                 pp += params_sent_thistime;
722                 pd += data_sent_thistime;
723
724                 params_to_send -= params_sent_thistime;
725                 data_to_send -= data_sent_thistime;
726
727                 /* Sanity check */
728                 if(params_to_send < 0 || data_to_send < 0) {
729                         DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
730                                 params_to_send, data_to_send));
731                         return -1;
732                 }
733         }
734
735         return 0;
736 }
737
738 static void send_trans2_replies_new(struct smb_request *req,
739                                     const char *params,
740                                     int paramsize,
741                                     const char *pdata,
742                                     int datasize,
743                                     int max_data_bytes)
744 {
745         char *inbuf, *outbuf;
746         int length, bufsize;
747
748         if (!reply_prep_legacy(req, &inbuf, &outbuf, &length, &bufsize)) {
749                 reply_nterror(req, NT_STATUS_NO_MEMORY);
750                 return;
751         }
752
753         reply_post_legacy(req, send_trans2_replies(
754                                   inbuf, outbuf, bufsize,
755                                   params, paramsize,
756                                   pdata, datasize,
757                                   max_data_bytes));
758 }
759
760 /****************************************************************************
761  Reply to a TRANSACT2_OPEN.
762 ****************************************************************************/
763
764 static void call_trans2open(connection_struct *conn,
765                             struct smb_request *req,
766                             char **pparams, int total_params,
767                             char **ppdata, int total_data,
768                             unsigned int max_data_bytes)
769 {
770         char *params = *pparams;
771         char *pdata = *ppdata;
772         int deny_mode;
773         int32 open_attr;
774         BOOL oplock_request;
775 #if 0
776         BOOL return_additional_info;
777         int16 open_sattr;
778         time_t open_time;
779 #endif
780         int open_ofun;
781         uint32 open_size;
782         char *pname;
783         pstring fname;
784         SMB_OFF_T size=0;
785         int fattr=0,mtime=0;
786         SMB_INO_T inode = 0;
787         SMB_STRUCT_STAT sbuf;
788         int smb_action = 0;
789         files_struct *fsp;
790         struct ea_list *ea_list = NULL;
791         uint16 flags = 0;
792         NTSTATUS status;
793         uint32 access_mask;
794         uint32 share_mode;
795         uint32 create_disposition;
796         uint32 create_options = 0;
797
798         /*
799          * Ensure we have enough parameters to perform the operation.
800          */
801
802         if (total_params < 29) {
803                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
804                 return;
805         }
806
807         flags = SVAL(params, 0);
808         deny_mode = SVAL(params, 2);
809         open_attr = SVAL(params,6);
810         oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
811         if (oplock_request) {
812                 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
813         }
814
815 #if 0
816         return_additional_info = BITSETW(params,0);
817         open_sattr = SVAL(params, 4);
818         open_time = make_unix_date3(params+8);
819 #endif
820         open_ofun = SVAL(params,12);
821         open_size = IVAL(params,14);
822         pname = &params[28];
823
824         if (IS_IPC(conn)) {
825                 reply_doserror(req, ERRSRV, ERRaccess);
826                 return;
827         }
828
829         srvstr_get_path(params, req->flags2, fname, pname,
830                         sizeof(fname), total_params - 28, STR_TERMINATE,
831                         &status);
832         if (!NT_STATUS_IS_OK(status)) {
833                 reply_nterror(req, status);
834                 return;
835         }
836
837         DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
838                 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
839                 (unsigned int)open_ofun, open_size));
840
841         /* XXXX we need to handle passed times, sattr and flags */
842
843         status = unix_convert(conn, fname, False, NULL, &sbuf);
844         if (!NT_STATUS_IS_OK(status)) {
845                 reply_nterror(req, status);
846                 return;
847         }
848     
849         status = check_name(conn, fname);
850         if (!NT_STATUS_IS_OK(status)) {
851                 reply_nterror(req, status);
852                 return;
853         }
854
855         if (open_ofun == 0) {
856                 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
857                 return;
858         }
859
860         if (!map_open_params_to_ntcreate(fname, deny_mode, open_ofun,
861                                 &access_mask,
862                                 &share_mode,
863                                 &create_disposition,
864                                 &create_options)) {
865                 reply_doserror(req, ERRDOS, ERRbadaccess);
866                 return;
867         }
868
869         /* Any data in this call is an EA list. */
870         if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
871                 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
872                 return;
873         }
874
875         if (total_data != 4) {
876                 if (total_data < 10) {
877                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
878                         return;
879                 }
880
881                 if (IVAL(pdata,0) > total_data) {
882                         DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
883                                 IVAL(pdata,0), (unsigned int)total_data));
884                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
885                         return;
886                 }
887
888                 ea_list = read_ea_list(tmp_talloc_ctx(), pdata + 4,
889                                        total_data - 4);
890                 if (!ea_list) {
891                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
892                         return;
893                 }
894         } else if (IVAL(pdata,0) != 4) {
895                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
896                 return;
897         }
898
899         status = open_file_ntcreate(conn, req, fname, &sbuf,
900                 access_mask,
901                 share_mode,
902                 create_disposition,
903                 create_options,
904                 open_attr,
905                 oplock_request,
906                 &smb_action, &fsp);
907       
908         if (!NT_STATUS_IS_OK(status)) {
909                 if (open_was_deferred(req->mid)) {
910                         /* We have re-scheduled this call. */
911                         return;
912                 }
913                 reply_nterror(req, status);
914                 return;
915         }
916
917         size = get_file_size(sbuf);
918         fattr = dos_mode(conn,fname,&sbuf);
919         mtime = sbuf.st_mtime;
920         inode = sbuf.st_ino;
921         if (fattr & aDIR) {
922                 close_file(fsp,ERROR_CLOSE);
923                 reply_doserror(req, ERRDOS,ERRnoaccess);
924                 return;
925         }
926
927         /* Save the requested allocation size. */
928         /* Allocate space for the file if a size hint is supplied */
929         if ((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) {
930                 SMB_BIG_UINT allocation_size = (SMB_BIG_UINT)open_size;
931                 if (allocation_size && (allocation_size > (SMB_BIG_UINT)size)) {
932                         fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
933                         if (fsp->is_directory) {
934                                 close_file(fsp,ERROR_CLOSE);
935                                 /* Can't set allocation size on a directory. */
936                                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
937                                 return;
938                         }
939                         if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
940                                 close_file(fsp,ERROR_CLOSE);
941                                 reply_nterror(req, NT_STATUS_DISK_FULL);
942                                 return;
943                         }
944
945                         /* Adjust size here to return the right size in the reply.
946                            Windows does it this way. */
947                         size = fsp->initial_allocation_size;
948                 } else {
949                         fsp->initial_allocation_size = smb_roundup(fsp->conn,(SMB_BIG_UINT)size);
950                 }
951         }
952
953         if (ea_list && smb_action == FILE_WAS_CREATED) {
954                 status = set_ea(conn, fsp, fname, ea_list);
955                 if (!NT_STATUS_IS_OK(status)) {
956                         close_file(fsp,ERROR_CLOSE);
957                         reply_nterror(req, status);
958                         return;
959                 }
960         }
961
962         /* Realloc the size of parameters and data we will return */
963         *pparams = (char *)SMB_REALLOC(*pparams, 30);
964         if(*pparams == NULL ) {
965                 reply_nterror(req, NT_STATUS_NO_MEMORY);
966                 return;
967         }
968         params = *pparams;
969
970         SSVAL(params,0,fsp->fnum);
971         SSVAL(params,2,fattr);
972         srv_put_dos_date2(params,4, mtime);
973         SIVAL(params,8, (uint32)size);
974         SSVAL(params,12,deny_mode);
975         SSVAL(params,14,0); /* open_type - file or directory. */
976         SSVAL(params,16,0); /* open_state - only valid for IPC device. */
977
978         if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
979                 smb_action |= EXTENDED_OPLOCK_GRANTED;
980         }
981
982         SSVAL(params,18,smb_action);
983
984         /*
985          * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
986          */
987         SIVAL(params,20,inode);
988         SSVAL(params,24,0); /* Padding. */
989         if (flags & 8) {
990                 uint32 ea_size = estimate_ea_size(conn, fsp, fname);
991                 SIVAL(params, 26, ea_size);
992         } else {
993                 SIVAL(params, 26, 0);
994         }
995
996         /* Send the required number of replies */
997         send_trans2_replies_new(req, params, 30, *ppdata, 0, max_data_bytes);
998 }
999
1000 /*********************************************************
1001  Routine to check if a given string matches exactly.
1002  as a special case a mask of "." does NOT match. That
1003  is required for correct wildcard semantics
1004  Case can be significant or not.
1005 **********************************************************/
1006
1007 static BOOL exact_match(connection_struct *conn, char *str, char *mask)
1008 {
1009         if (mask[0] == '.' && mask[1] == 0)
1010                 return False;
1011         if (conn->case_sensitive)
1012                 return strcmp(str,mask)==0;
1013         if (StrCaseCmp(str,mask) != 0) {
1014                 return False;
1015         }
1016         if (dptr_has_wild(conn->dirptr)) {
1017                 return False;
1018         }
1019         return True;
1020 }
1021
1022 /****************************************************************************
1023  Return the filetype for UNIX extensions.
1024 ****************************************************************************/
1025
1026 static uint32 unix_filetype(mode_t mode)
1027 {
1028         if(S_ISREG(mode))
1029                 return UNIX_TYPE_FILE;
1030         else if(S_ISDIR(mode))
1031                 return UNIX_TYPE_DIR;
1032 #ifdef S_ISLNK
1033         else if(S_ISLNK(mode))
1034                 return UNIX_TYPE_SYMLINK;
1035 #endif
1036 #ifdef S_ISCHR
1037         else if(S_ISCHR(mode))
1038                 return UNIX_TYPE_CHARDEV;
1039 #endif
1040 #ifdef S_ISBLK
1041         else if(S_ISBLK(mode))
1042                 return UNIX_TYPE_BLKDEV;
1043 #endif
1044 #ifdef S_ISFIFO
1045         else if(S_ISFIFO(mode))
1046                 return UNIX_TYPE_FIFO;
1047 #endif
1048 #ifdef S_ISSOCK
1049         else if(S_ISSOCK(mode))
1050                 return UNIX_TYPE_SOCKET;
1051 #endif
1052
1053         DEBUG(0,("unix_filetype: unknown filetype %u", (unsigned)mode));
1054         return UNIX_TYPE_UNKNOWN;
1055 }
1056
1057 /****************************************************************************
1058  Map wire perms onto standard UNIX permissions. Obey share restrictions.
1059 ****************************************************************************/
1060
1061 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1062
1063 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1064                                 SMB_STRUCT_STAT *psbuf,
1065                                 uint32 perms,
1066                                 enum perm_type ptype,
1067                                 mode_t *ret_perms)
1068 {
1069         mode_t ret = 0;
1070
1071         if (perms == SMB_MODE_NO_CHANGE) {
1072                 if (!VALID_STAT(*psbuf)) {
1073                         return NT_STATUS_INVALID_PARAMETER;
1074                 } else {
1075                         *ret_perms = psbuf->st_mode;
1076                         return NT_STATUS_OK;
1077                 }
1078         }
1079
1080         ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1081         ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1082         ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1083         ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1084         ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1085         ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1086         ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1087         ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1088         ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1089 #ifdef S_ISVTX
1090         ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1091 #endif
1092 #ifdef S_ISGID
1093         ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1094 #endif
1095 #ifdef S_ISUID
1096         ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1097 #endif
1098
1099         switch (ptype) {
1100         case PERM_NEW_FILE:
1101                 /* Apply mode mask */
1102                 ret &= lp_create_mask(SNUM(conn));
1103                 /* Add in force bits */
1104                 ret |= lp_force_create_mode(SNUM(conn));
1105                 break;
1106         case PERM_NEW_DIR:
1107                 ret &= lp_dir_mask(SNUM(conn));
1108                 /* Add in force bits */
1109                 ret |= lp_force_dir_mode(SNUM(conn));
1110                 break;
1111         case PERM_EXISTING_FILE:
1112                 /* Apply mode mask */
1113                 ret &= lp_security_mask(SNUM(conn));
1114                 /* Add in force bits */
1115                 ret |= lp_force_security_mode(SNUM(conn));
1116                 break;
1117         case PERM_EXISTING_DIR:
1118                 /* Apply mode mask */
1119                 ret &= lp_dir_security_mask(SNUM(conn));
1120                 /* Add in force bits */
1121                 ret |= lp_force_dir_security_mode(SNUM(conn));
1122                 break;
1123         }
1124
1125         *ret_perms = ret;
1126         return NT_STATUS_OK;
1127 }
1128
1129 /****************************************************************************
1130  Get a level dependent lanman2 dir entry.
1131 ****************************************************************************/
1132
1133 static BOOL get_lanman2_dir_entry(connection_struct *conn, uint16 flags2,
1134                                  char *path_mask,uint32 dirtype,int info_level,
1135                                  int requires_resume_key,
1136                                  BOOL dont_descend,char **ppdata, 
1137                                  char *base_data, char *end_data,
1138                                  int space_remaining,
1139                                  BOOL *out_of_space, BOOL *got_exact_match,
1140                                  int *last_entry_off, struct ea_list *name_list, TALLOC_CTX *ea_ctx)
1141 {
1142         const char *dname;
1143         BOOL found = False;
1144         SMB_STRUCT_STAT sbuf;
1145         pstring mask;
1146         pstring pathreal;
1147         pstring fname;
1148         char *p, *q, *pdata = *ppdata;
1149         uint32 reskey=0;
1150         long prev_dirpos=0;
1151         uint32 mode=0;
1152         SMB_OFF_T file_size = 0;
1153         SMB_BIG_UINT allocation_size = 0;
1154         uint32 len;
1155         struct timespec mdate_ts, adate_ts, create_date_ts;
1156         time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1157         char *nameptr;
1158         char *last_entry_ptr;
1159         BOOL was_8_3;
1160         uint32 nt_extmode; /* Used for NT connections instead of mode */
1161         BOOL needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
1162         BOOL check_mangled_names = lp_manglednames(conn->params);
1163
1164         *fname = 0;
1165         *out_of_space = False;
1166         *got_exact_match = False;
1167
1168         ZERO_STRUCT(mdate_ts);
1169         ZERO_STRUCT(adate_ts);
1170         ZERO_STRUCT(create_date_ts);
1171
1172         if (!conn->dirptr)
1173                 return(False);
1174
1175         p = strrchr_m(path_mask,'/');
1176         if(p != NULL) {
1177                 if(p[1] == '\0')
1178                         pstrcpy(mask,"*.*");
1179                 else
1180                         pstrcpy(mask, p+1);
1181         } else
1182                 pstrcpy(mask, path_mask);
1183
1184
1185         while (!found) {
1186                 BOOL got_match;
1187                 BOOL ms_dfs_link = False;
1188
1189                 /* Needed if we run out of space */
1190                 long curr_dirpos = prev_dirpos = dptr_TellDir(conn->dirptr);
1191                 dname = dptr_ReadDirName(conn->dirptr,&curr_dirpos,&sbuf);
1192
1193                 /*
1194                  * Due to bugs in NT client redirectors we are not using
1195                  * resume keys any more - set them to zero.
1196                  * Check out the related comments in findfirst/findnext.
1197                  * JRA.
1198                  */
1199
1200                 reskey = 0;
1201
1202                 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %ld\n",
1203                         (long)conn->dirptr,curr_dirpos));
1204       
1205                 if (!dname) {
1206                         return(False);
1207                 }
1208
1209                 /*
1210                  * fname may get mangled, dname is never mangled.
1211                  * Whenever we're accessing the filesystem we use
1212                  * pathreal which is composed from dname.
1213                  */
1214
1215                 pstrcpy(fname,dname);      
1216
1217                 /* This will mangle fname if it's an illegal name. */
1218                 mangle_map(fname,False,True,conn->params);
1219
1220                 if(!(got_match = *got_exact_match = exact_match(conn, fname, mask))) {
1221                         got_match = mask_match(fname, mask, conn->case_sensitive);
1222                 }
1223
1224                 if(!got_match && check_mangled_names &&
1225                    !mangle_is_8_3(fname, False, conn->params)) {
1226                         pstring mangled_name;
1227
1228                         /*
1229                          * It turns out that NT matches wildcards against
1230                          * both long *and* short names. This may explain some
1231                          * of the wildcard wierdness from old DOS clients
1232                          * that some people have been seeing.... JRA.
1233                          */
1234
1235                         pstrcpy(mangled_name, fname);
1236
1237                         /* Force the mangling into 8.3. */
1238                         mangle_map( mangled_name, True, False, conn->params);
1239                         if(!(got_match = *got_exact_match = exact_match(conn, mangled_name, mask))) {
1240                                 got_match = mask_match(mangled_name, mask, conn->case_sensitive);
1241                         }
1242                 }
1243
1244                 if (got_match) {
1245                         BOOL isdots = (strequal(dname,"..") || strequal(dname,"."));
1246                         if (dont_descend && !isdots) {
1247                                 continue;
1248                         }
1249           
1250                         pstrcpy(pathreal,conn->dirpath);
1251                         if(needslash) {
1252                                 pstrcat(pathreal,"/");
1253                         }
1254                         pstrcat(pathreal,dname);
1255
1256                         if (INFO_LEVEL_IS_UNIX(info_level)) {
1257                                 if (SMB_VFS_LSTAT(conn,pathreal,&sbuf) != 0) {
1258                                         DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",
1259                                                 pathreal,strerror(errno)));
1260                                         continue;
1261                                 }
1262                         } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,pathreal,&sbuf) != 0) {
1263                                 pstring link_target;
1264
1265                                 /* Needed to show the msdfs symlinks as 
1266                                  * directories */
1267
1268                                 if(lp_host_msdfs() && 
1269                                    lp_msdfs_root(SNUM(conn)) &&
1270                                    ((ms_dfs_link = is_msdfs_link(conn, pathreal, link_target, &sbuf)) == True)) {
1271                                         DEBUG(5,("get_lanman2_dir_entry: Masquerading msdfs link %s "
1272                                                 "as a directory\n",
1273                                                 pathreal));
1274                                         sbuf.st_mode = (sbuf.st_mode & 0xFFF) | S_IFDIR;
1275
1276                                 } else {
1277
1278                                         DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
1279                                                 pathreal,strerror(errno)));
1280                                         continue;
1281                                 }
1282                         }
1283
1284                         if (ms_dfs_link) {
1285                                 mode = dos_mode_msdfs(conn,pathreal,&sbuf);
1286                         } else {
1287                                 mode = dos_mode(conn,pathreal,&sbuf);
1288                         }
1289
1290                         if (!dir_check_ftype(conn,mode,dirtype)) {
1291                                 DEBUG(5,("get_lanman2_dir_entry: [%s] attribs didn't match %x\n",fname,dirtype));
1292                                 continue;
1293                         }
1294
1295                         if (!(mode & aDIR)) {
1296                                 file_size = get_file_size(sbuf);
1297                         }
1298                         allocation_size = get_allocation_size(conn,NULL,&sbuf);
1299
1300                         mdate_ts = get_mtimespec(&sbuf);
1301                         adate_ts = get_atimespec(&sbuf);
1302                         create_date_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
1303
1304                         if (lp_dos_filetime_resolution(SNUM(conn))) {
1305                                 dos_filetime_timespec(&create_date_ts);
1306                                 dos_filetime_timespec(&mdate_ts);
1307                                 dos_filetime_timespec(&adate_ts);
1308                         }
1309
1310                         create_date = convert_timespec_to_time_t(create_date_ts);
1311                         mdate = convert_timespec_to_time_t(mdate_ts);
1312                         adate = convert_timespec_to_time_t(adate_ts);
1313                         
1314                         DEBUG(5,("get_lanman2_dir_entry: found %s fname=%s\n",pathreal,fname));
1315           
1316                         found = True;
1317
1318                         dptr_DirCacheAdd(conn->dirptr, dname, curr_dirpos);
1319                 }
1320         }
1321
1322         p = pdata;
1323         last_entry_ptr = p;
1324
1325         nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
1326
1327         switch (info_level) {
1328                 case SMB_FIND_INFO_STANDARD:
1329                         DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1330                         if(requires_resume_key) {
1331                                 SIVAL(p,0,reskey);
1332                                 p += 4;
1333                         }
1334                         srv_put_dos_date2(p,0,create_date);
1335                         srv_put_dos_date2(p,4,adate);
1336                         srv_put_dos_date2(p,8,mdate);
1337                         SIVAL(p,12,(uint32)file_size);
1338                         SIVAL(p,16,(uint32)allocation_size);
1339                         SSVAL(p,20,mode);
1340                         p += 23;
1341                         nameptr = p;
1342                         p += align_string(pdata, p, 0);
1343                         len = srvstr_push(base_data, flags2, p,
1344                                           fname, PTR_DIFF(end_data, p),
1345                                           STR_TERMINATE);
1346                         if (flags2 & FLAGS2_UNICODE_STRINGS) {
1347                                 if (len > 2) {
1348                                         SCVAL(nameptr, -1, len - 2);
1349                                 } else {
1350                                         SCVAL(nameptr, -1, 0);
1351                                 }
1352                         } else {
1353                                 if (len > 1) {
1354                                         SCVAL(nameptr, -1, len - 1);
1355                                 } else {
1356                                         SCVAL(nameptr, -1, 0);
1357                                 }
1358                         }
1359                         p += len;
1360                         break;
1361
1362                 case SMB_FIND_EA_SIZE:
1363                         DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n"));
1364                         if(requires_resume_key) {
1365                                 SIVAL(p,0,reskey);
1366                                 p += 4;
1367                         }
1368                         srv_put_dos_date2(p,0,create_date);
1369                         srv_put_dos_date2(p,4,adate);
1370                         srv_put_dos_date2(p,8,mdate);
1371                         SIVAL(p,12,(uint32)file_size);
1372                         SIVAL(p,16,(uint32)allocation_size);
1373                         SSVAL(p,20,mode);
1374                         {
1375                                 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1376                                 SIVAL(p,22,ea_size); /* Extended attributes */
1377                         }
1378                         p += 27;
1379                         nameptr = p - 1;
1380                         len = srvstr_push(base_data, flags2,
1381                                           p, fname, PTR_DIFF(end_data, p),
1382                                           STR_TERMINATE | STR_NOALIGN);
1383                         if (flags2 & FLAGS2_UNICODE_STRINGS) {
1384                                 if (len > 2) {
1385                                         len -= 2;
1386                                 } else {
1387                                         len = 0;
1388                                 }
1389                         } else {
1390                                 if (len > 1) {
1391                                         len -= 1;
1392                                 } else {
1393                                         len = 0;
1394                                 }
1395                         }
1396                         SCVAL(nameptr,0,len);
1397                         p += len;
1398                         SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1399                         break;
1400
1401                 case SMB_FIND_EA_LIST:
1402                 {
1403                         struct ea_list *file_list = NULL;
1404                         size_t ea_len = 0;
1405
1406                         DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n"));
1407                         if (!name_list) {
1408                                 return False;
1409                         }
1410                         if(requires_resume_key) {
1411                                 SIVAL(p,0,reskey);
1412                                 p += 4;
1413                         }
1414                         srv_put_dos_date2(p,0,create_date);
1415                         srv_put_dos_date2(p,4,adate);
1416                         srv_put_dos_date2(p,8,mdate);
1417                         SIVAL(p,12,(uint32)file_size);
1418                         SIVAL(p,16,(uint32)allocation_size);
1419                         SSVAL(p,20,mode);
1420                         p += 22; /* p now points to the EA area. */
1421
1422                         file_list = get_ea_list_from_file(ea_ctx, conn, NULL, pathreal, &ea_len);
1423                         name_list = ea_list_union(name_list, file_list, &ea_len);
1424
1425                         /* We need to determine if this entry will fit in the space available. */
1426                         /* Max string size is 255 bytes. */
1427                         if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1428                                 /* Move the dirptr back to prev_dirpos */
1429                                 dptr_SeekDir(conn->dirptr, prev_dirpos);
1430                                 *out_of_space = True;
1431                                 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1432                                 return False; /* Not finished - just out of space */
1433                         }
1434
1435                         /* Push the ea_data followed by the name. */
1436                         p += fill_ea_buffer(ea_ctx, p, space_remaining, conn, name_list);
1437                         nameptr = p;
1438                         len = srvstr_push(base_data, flags2,
1439                                           p + 1, fname, PTR_DIFF(end_data, p),
1440                                           STR_TERMINATE | STR_NOALIGN);
1441                         if (flags2 & FLAGS2_UNICODE_STRINGS) {
1442                                 if (len > 2) {
1443                                         len -= 2;
1444                                 } else {
1445                                         len = 0;
1446                                 }
1447                         } else {
1448                                 if (len > 1) {
1449                                         len -= 1;
1450                                 } else {
1451                                         len = 0;
1452                                 }
1453                         }
1454                         SCVAL(nameptr,0,len);
1455                         p += len + 1;
1456                         SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1457                         break;
1458                 }
1459
1460                 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1461                         DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1462                         was_8_3 = mangle_is_8_3(fname, True, conn->params);
1463                         p += 4;
1464                         SIVAL(p,0,reskey); p += 4;
1465                         put_long_date_timespec(p,create_date_ts); p += 8;
1466                         put_long_date_timespec(p,adate_ts); p += 8;
1467                         put_long_date_timespec(p,mdate_ts); p += 8;
1468                         put_long_date_timespec(p,mdate_ts); p += 8;
1469                         SOFF_T(p,0,file_size); p += 8;
1470                         SOFF_T(p,0,allocation_size); p += 8;
1471                         SIVAL(p,0,nt_extmode); p += 4;
1472                         q = p; p += 4; /* q is placeholder for name length. */
1473                         {
1474                                 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1475                                 SIVAL(p,0,ea_size); /* Extended attributes */
1476                                 p += 4;
1477                         }
1478                         /* Clear the short name buffer. This is
1479                          * IMPORTANT as not doing so will trigger
1480                          * a Win2k client bug. JRA.
1481                          */
1482                         if (!was_8_3 && check_mangled_names) {
1483                                 pstring mangled_name;
1484                                 pstrcpy(mangled_name, fname);
1485                                 mangle_map(mangled_name,True,True,
1486                                            conn->params);
1487                                 mangled_name[12] = 0;
1488                                 len = srvstr_push(base_data, flags2,
1489                                                   p+2, mangled_name, 24,
1490                                                   STR_UPPER|STR_UNICODE);
1491                                 if (len < 24) {
1492                                         memset(p + 2 + len,'\0',24 - len);
1493                                 }
1494                                 SSVAL(p, 0, len);
1495                         } else {
1496                                 memset(p,'\0',26);
1497                         }
1498                         p += 2 + 24;
1499                         len = srvstr_push(base_data, flags2, p,
1500                                           fname, PTR_DIFF(end_data, p),
1501                                           STR_TERMINATE_ASCII);
1502                         SIVAL(q,0,len);
1503                         p += len;
1504                         SIVAL(p,0,0); /* Ensure any padding is null. */
1505                         len = PTR_DIFF(p, pdata);
1506                         len = (len + 3) & ~3;
1507                         SIVAL(pdata,0,len);
1508                         p = pdata + len;
1509                         break;
1510
1511                 case SMB_FIND_FILE_DIRECTORY_INFO:
1512                         DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1513                         p += 4;
1514                         SIVAL(p,0,reskey); p += 4;
1515                         put_long_date_timespec(p,create_date_ts); p += 8;
1516                         put_long_date_timespec(p,adate_ts); p += 8;
1517                         put_long_date_timespec(p,mdate_ts); p += 8;
1518                         put_long_date_timespec(p,mdate_ts); p += 8;
1519                         SOFF_T(p,0,file_size); p += 8;
1520                         SOFF_T(p,0,allocation_size); p += 8;
1521                         SIVAL(p,0,nt_extmode); p += 4;
1522                         len = srvstr_push(base_data, flags2,
1523                                           p + 4, fname, PTR_DIFF(end_data, p),
1524                                           STR_TERMINATE_ASCII);
1525                         SIVAL(p,0,len);
1526                         p += 4 + len;
1527                         SIVAL(p,0,0); /* Ensure any padding is null. */
1528                         len = PTR_DIFF(p, pdata);
1529                         len = (len + 3) & ~3;
1530                         SIVAL(pdata,0,len);
1531                         p = pdata + len;
1532                         break;
1533       
1534                 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1535                         DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1536                         p += 4;
1537                         SIVAL(p,0,reskey); p += 4;
1538                         put_long_date_timespec(p,create_date_ts); p += 8;
1539                         put_long_date_timespec(p,adate_ts); p += 8;
1540                         put_long_date_timespec(p,mdate_ts); p += 8;
1541                         put_long_date_timespec(p,mdate_ts); p += 8;
1542                         SOFF_T(p,0,file_size); p += 8;
1543                         SOFF_T(p,0,allocation_size); p += 8;
1544                         SIVAL(p,0,nt_extmode); p += 4;
1545                         q = p; p += 4; /* q is placeholder for name length. */
1546                         {
1547                                 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1548                                 SIVAL(p,0,ea_size); /* Extended attributes */
1549                                 p +=4;
1550                         }
1551                         len = srvstr_push(base_data, flags2, p,
1552                                           fname, PTR_DIFF(end_data, p),
1553                                           STR_TERMINATE_ASCII);
1554                         SIVAL(q, 0, len);
1555                         p += len;
1556
1557                         SIVAL(p,0,0); /* Ensure any padding is null. */
1558                         len = PTR_DIFF(p, pdata);
1559                         len = (len + 3) & ~3;
1560                         SIVAL(pdata,0,len);
1561                         p = pdata + len;
1562                         break;
1563
1564                 case SMB_FIND_FILE_NAMES_INFO:
1565                         DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1566                         p += 4;
1567                         SIVAL(p,0,reskey); p += 4;
1568                         p += 4;
1569                         /* this must *not* be null terminated or w2k gets in a loop trying to set an
1570                            acl on a dir (tridge) */
1571                         len = srvstr_push(base_data, flags2, p,
1572                                           fname, PTR_DIFF(end_data, p),
1573                                           STR_TERMINATE_ASCII);
1574                         SIVAL(p, -4, len);
1575                         p += len;
1576                         SIVAL(p,0,0); /* Ensure any padding is null. */
1577                         len = PTR_DIFF(p, pdata);
1578                         len = (len + 3) & ~3;
1579                         SIVAL(pdata,0,len);
1580                         p = pdata + len;
1581                         break;
1582
1583                 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1584                         DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1585                         p += 4;
1586                         SIVAL(p,0,reskey); p += 4;
1587                         put_long_date_timespec(p,create_date_ts); p += 8;
1588                         put_long_date_timespec(p,adate_ts); p += 8;
1589                         put_long_date_timespec(p,mdate_ts); p += 8;
1590                         put_long_date_timespec(p,mdate_ts); p += 8;
1591                         SOFF_T(p,0,file_size); p += 8;
1592                         SOFF_T(p,0,allocation_size); p += 8;
1593                         SIVAL(p,0,nt_extmode); p += 4;
1594                         q = p; p += 4; /* q is placeholder for name length. */
1595                         {
1596                                 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1597                                 SIVAL(p,0,ea_size); /* Extended attributes */
1598                                 p +=4;
1599                         }
1600                         SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1601                         SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1602                         SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1603                         len = srvstr_push(base_data, flags2, p,
1604                                           fname, PTR_DIFF(end_data, p),
1605                                           STR_TERMINATE_ASCII);
1606                         SIVAL(q, 0, len);
1607                         p += len; 
1608                         SIVAL(p,0,0); /* Ensure any padding is null. */
1609                         len = PTR_DIFF(p, pdata);
1610                         len = (len + 3) & ~3;
1611                         SIVAL(pdata,0,len);
1612                         p = pdata + len;
1613                         break;
1614
1615                 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1616                         DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1617                         was_8_3 = mangle_is_8_3(fname, True, conn->params);
1618                         p += 4;
1619                         SIVAL(p,0,reskey); p += 4;
1620                         put_long_date_timespec(p,create_date_ts); p += 8;
1621                         put_long_date_timespec(p,adate_ts); p += 8;
1622                         put_long_date_timespec(p,mdate_ts); p += 8;
1623                         put_long_date_timespec(p,mdate_ts); p += 8;
1624                         SOFF_T(p,0,file_size); p += 8;
1625                         SOFF_T(p,0,allocation_size); p += 8;
1626                         SIVAL(p,0,nt_extmode); p += 4;
1627                         q = p; p += 4; /* q is placeholder for name length */
1628                         {
1629                                 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1630                                 SIVAL(p,0,ea_size); /* Extended attributes */
1631                                 p +=4;
1632                         }
1633                         /* Clear the short name buffer. This is
1634                          * IMPORTANT as not doing so will trigger
1635                          * a Win2k client bug. JRA.
1636                          */
1637                         if (!was_8_3 && check_mangled_names) {
1638                                 pstring mangled_name;
1639                                 pstrcpy(mangled_name, fname);
1640                                 mangle_map(mangled_name,True,True,
1641                                            conn->params);
1642                                 mangled_name[12] = 0;
1643                                 len = srvstr_push(base_data, flags2,
1644                                                   p+2, mangled_name, 24,
1645                                                   STR_UPPER|STR_UNICODE);
1646                                 SSVAL(p, 0, len);
1647                                 if (len < 24) {
1648                                         memset(p + 2 + len,'\0',24 - len);
1649                                 }
1650                                 SSVAL(p, 0, len);
1651                         } else {
1652                                 memset(p,'\0',26);
1653                         }
1654                         p += 26;
1655                         SSVAL(p,0,0); p += 2; /* Reserved ? */
1656                         SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1657                         SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1658                         len = srvstr_push(base_data, flags2, p,
1659                                           fname, PTR_DIFF(end_data, p),
1660                                           STR_TERMINATE_ASCII);
1661                         SIVAL(q,0,len);
1662                         p += len;
1663                         SIVAL(p,0,0); /* Ensure any padding is null. */
1664                         len = PTR_DIFF(p, pdata);
1665                         len = (len + 3) & ~3;
1666                         SIVAL(pdata,0,len);
1667                         p = pdata + len;
1668                         break;
1669
1670                 /* CIFS UNIX Extension. */
1671
1672                 case SMB_FIND_FILE_UNIX:
1673                 case SMB_FIND_FILE_UNIX_INFO2:
1674                         p+= 4;
1675                         SIVAL(p,0,reskey); p+= 4;    /* Used for continuing search. */
1676
1677                         /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1678
1679                         if (info_level == SMB_FIND_FILE_UNIX) {
1680                                 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1681                                 p = store_file_unix_basic(conn, p,
1682                                                         NULL, &sbuf);
1683                                 len = srvstr_push(base_data, flags2, p,
1684                                                   fname, PTR_DIFF(end_data, p),
1685                                                   STR_TERMINATE);
1686                         } else {
1687                                 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
1688                                 p = store_file_unix_basic_info2(conn, p,
1689                                                         NULL, &sbuf);
1690                                 nameptr = p;
1691                                 p += 4;
1692                                 len = srvstr_push(base_data, flags2, p, fname,
1693                                                   PTR_DIFF(end_data, p), 0);
1694                                 SIVAL(nameptr, 0, len);
1695                         }
1696
1697                         p += len;
1698                         SIVAL(p,0,0); /* Ensure any padding is null. */
1699
1700                         len = PTR_DIFF(p, pdata);
1701                         len = (len + 3) & ~3;
1702                         SIVAL(pdata,0,len);     /* Offset from this structure to the beginning of the next one */
1703                         p = pdata + len;
1704                         /* End of SMB_QUERY_FILE_UNIX_BASIC */
1705
1706                         break;
1707
1708                 default:      
1709                         return(False);
1710         }
1711
1712
1713         if (PTR_DIFF(p,pdata) > space_remaining) {
1714                 /* Move the dirptr back to prev_dirpos */
1715                 dptr_SeekDir(conn->dirptr, prev_dirpos);
1716                 *out_of_space = True;
1717                 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1718                 return False; /* Not finished - just out of space */
1719         }
1720
1721         /* Setup the last entry pointer, as an offset from base_data */
1722         *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
1723         /* Advance the data pointer to the next slot */
1724         *ppdata = p;
1725
1726         return(found);
1727 }
1728
1729 /****************************************************************************
1730  Reply to a TRANS2_FINDFIRST.
1731 ****************************************************************************/
1732
1733 static void call_trans2findfirst(connection_struct *conn,
1734                                  struct smb_request *req,
1735                                  char **pparams, int total_params,
1736                                  char **ppdata, int total_data,
1737                                  unsigned int max_data_bytes)
1738 {
1739         /* We must be careful here that we don't return more than the
1740                 allowed number of data bytes. If this means returning fewer than
1741                 maxentries then so be it. We assume that the redirector has
1742                 enough room for the fixed number of parameter bytes it has
1743                 requested. */
1744         char *params = *pparams;
1745         char *pdata = *ppdata;
1746         char *data_end;
1747         uint32 dirtype;
1748         int maxentries;
1749         uint16 findfirst_flags;
1750         BOOL close_after_first;
1751         BOOL close_if_end;
1752         BOOL requires_resume_key;
1753         int info_level;
1754         pstring directory;
1755         pstring mask;
1756         char *p;
1757         int last_entry_off=0;
1758         int dptr_num = -1;
1759         int numentries = 0;
1760         int i;
1761         BOOL finished = False;
1762         BOOL dont_descend = False;
1763         BOOL out_of_space = False;
1764         int space_remaining;
1765         BOOL mask_contains_wcard = False;
1766         SMB_STRUCT_STAT sbuf;
1767         TALLOC_CTX *ea_ctx = NULL;
1768         struct ea_list *ea_list = NULL;
1769         NTSTATUS ntstatus = NT_STATUS_OK;
1770
1771         if (total_params < 13) {
1772                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1773                 return;
1774         }
1775
1776         dirtype = SVAL(params,0);
1777         maxentries = SVAL(params,2);
1778         findfirst_flags = SVAL(params,4);
1779         close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
1780         close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1781         requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1782         info_level = SVAL(params,6);
1783
1784         *directory = *mask = 0;
1785
1786         DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
1787 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
1788                 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
1789                 info_level, max_data_bytes));
1790
1791         if (!maxentries) {
1792                 /* W2K3 seems to treat zero as 1. */
1793                 maxentries = 1;
1794         }
1795  
1796         switch (info_level) {
1797                 case SMB_FIND_INFO_STANDARD:
1798                 case SMB_FIND_EA_SIZE:
1799                 case SMB_FIND_EA_LIST:
1800                 case SMB_FIND_FILE_DIRECTORY_INFO:
1801                 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1802                 case SMB_FIND_FILE_NAMES_INFO:
1803                 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1804                 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1805                 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1806                         break;
1807                 case SMB_FIND_FILE_UNIX:
1808                 case SMB_FIND_FILE_UNIX_INFO2:
1809                         if (!lp_unix_extensions()) {
1810                                 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1811                                 return;
1812                         }
1813                         break;
1814                 default:
1815                         reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1816                         return;
1817         }
1818
1819         srvstr_get_path_wcard(params, req->flags2, directory,
1820                               params+12, sizeof(directory), total_params - 12,
1821                               STR_TERMINATE, &ntstatus, &mask_contains_wcard);
1822         if (!NT_STATUS_IS_OK(ntstatus)) {
1823                 reply_nterror(req, ntstatus);
1824                 return;
1825         }
1826
1827         ntstatus = resolve_dfspath_wcard(conn, req->flags2 & FLAGS2_DFS_PATHNAMES, directory, &mask_contains_wcard);
1828         if (!NT_STATUS_IS_OK(ntstatus)) {
1829                 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
1830                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1831                                         ERRSRV, ERRbadpath);
1832                         return;
1833                 }
1834                 reply_nterror(req, ntstatus);
1835                 return;
1836         }
1837
1838         ntstatus = unix_convert(conn, directory, True, NULL, &sbuf);
1839         if (!NT_STATUS_IS_OK(ntstatus)) {
1840                 reply_nterror(req, ntstatus);
1841                 return;
1842         }
1843         ntstatus = check_name(conn, directory);
1844         if (!NT_STATUS_IS_OK(ntstatus)) {
1845                 reply_nterror(req, ntstatus);
1846                 return;
1847         }
1848
1849         p = strrchr_m(directory,'/');
1850         if(p == NULL) {
1851                 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
1852                 if((directory[0] == '.') && (directory[1] == '\0')) {
1853                         pstrcpy(mask,"*");
1854                         mask_contains_wcard = True;
1855                 } else {
1856                         pstrcpy(mask,directory);
1857                 }
1858                 pstrcpy(directory,"./");
1859         } else {
1860                 pstrcpy(mask,p+1);
1861                 *p = 0;
1862         }
1863
1864         DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
1865
1866         if (info_level == SMB_FIND_EA_LIST) {
1867                 uint32 ea_size;
1868
1869                 if (total_data < 4) {
1870                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1871                         return;
1872                 }
1873
1874                 ea_size = IVAL(pdata,0);
1875                 if (ea_size != total_data) {
1876                         DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
1877 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
1878                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1879                         return;
1880                 }
1881
1882                 if (!lp_ea_support(SNUM(conn))) {
1883                         reply_doserror(req, ERRDOS, ERReasnotsupported);
1884                         return;
1885                 }
1886                                                                                                                                                         
1887                 if ((ea_ctx = talloc_init("findnext_ea_list")) == NULL) {
1888                         reply_nterror(req, NT_STATUS_NO_MEMORY);
1889                         return;
1890                 }
1891
1892                 /* Pull out the list of names. */
1893                 ea_list = read_ea_name_list(ea_ctx, pdata + 4, ea_size - 4);
1894                 if (!ea_list) {
1895                         talloc_destroy(ea_ctx);
1896                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1897                         return;
1898                 }
1899         }
1900
1901         *ppdata = (char *)SMB_REALLOC(
1902                 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1903         if(*ppdata == NULL ) {
1904                 talloc_destroy(ea_ctx);
1905                 reply_nterror(req, NT_STATUS_NO_MEMORY);
1906                 return;
1907         }
1908         pdata = *ppdata;
1909         data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
1910
1911         /* Realloc the params space */
1912         *pparams = (char *)SMB_REALLOC(*pparams, 10);
1913         if (*pparams == NULL) {
1914                 talloc_destroy(ea_ctx);
1915                 reply_nterror(req, NT_STATUS_NO_MEMORY);
1916                 return;
1917         }
1918         params = *pparams;
1919
1920         /* Save the wildcard match and attribs we are using on this directory - 
1921                 needed as lanman2 assumes these are being saved between calls */
1922
1923         ntstatus = dptr_create(conn,
1924                                 directory,
1925                                 False,
1926                                 True,
1927                                 req->smbpid,
1928                                 mask,
1929                                 mask_contains_wcard,
1930                                 dirtype,
1931                                 &conn->dirptr);
1932
1933         if (!NT_STATUS_IS_OK(ntstatus)) {
1934                 talloc_destroy(ea_ctx);
1935                 reply_nterror(req, ntstatus);
1936                 return;
1937         }
1938
1939         dptr_num = dptr_dnum(conn->dirptr);
1940         DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
1941
1942         /* We don't need to check for VOL here as this is returned by 
1943                 a different TRANS2 call. */
1944   
1945         DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
1946         if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
1947                 dont_descend = True;
1948     
1949         p = pdata;
1950         space_remaining = max_data_bytes;
1951         out_of_space = False;
1952
1953         for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
1954                 BOOL got_exact_match = False;
1955
1956                 /* this is a heuristic to avoid seeking the dirptr except when 
1957                         absolutely necessary. It allows for a filename of about 40 chars */
1958                 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
1959                         out_of_space = True;
1960                         finished = False;
1961                 } else {
1962                         finished = !get_lanman2_dir_entry(conn,
1963                                         req->flags2,
1964                                         mask,dirtype,info_level,
1965                                         requires_resume_key,dont_descend,
1966                                         &p,pdata,data_end,
1967                                         space_remaining, &out_of_space,
1968                                         &got_exact_match,
1969                                         &last_entry_off, ea_list, ea_ctx);
1970                 }
1971
1972                 if (finished && out_of_space)
1973                         finished = False;
1974
1975                 if (!finished && !out_of_space)
1976                         numentries++;
1977
1978                 /*
1979                  * As an optimisation if we know we aren't looking
1980                  * for a wildcard name (ie. the name matches the wildcard exactly)
1981                  * then we can finish on any (first) match.
1982                  * This speeds up large directory searches. JRA.
1983                  */
1984
1985                 if(got_exact_match)
1986                         finished = True;
1987
1988                 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
1989         }
1990   
1991         talloc_destroy(ea_ctx);
1992
1993         /* Check if we can close the dirptr */
1994         if(close_after_first || (finished && close_if_end)) {
1995                 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
1996                 dptr_close(&dptr_num);
1997         }
1998
1999         /* 
2000          * If there are no matching entries we must return ERRDOS/ERRbadfile - 
2001          * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2002          * the protocol level is less than NT1. Tested with smbclient. JRA.
2003          * This should fix the OS/2 client bug #2335.
2004          */
2005
2006         if(numentries == 0) {
2007                 dptr_close(&dptr_num);
2008                 if (Protocol < PROTOCOL_NT1) {
2009                         reply_doserror(req, ERRDOS, ERRnofiles);
2010                         return;
2011                 } else {
2012                         reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2013                                         ERRDOS, ERRbadfile);
2014                         return;
2015                 }
2016         }
2017
2018         /* At this point pdata points to numentries directory entries. */
2019
2020         /* Set up the return parameter block */
2021         SSVAL(params,0,dptr_num);
2022         SSVAL(params,2,numentries);
2023         SSVAL(params,4,finished);
2024         SSVAL(params,6,0); /* Never an EA error */
2025         SSVAL(params,8,last_entry_off);
2026
2027         send_trans2_replies_new(req, params, 10, pdata, PTR_DIFF(p,pdata),
2028                                 max_data_bytes);
2029
2030         if ((! *directory) && dptr_path(dptr_num))
2031                 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
2032
2033         DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2034                 smb_fn_name(CVAL(req->inbuf,smb_com)),
2035                 mask, directory, dirtype, numentries ) );
2036
2037         /* 
2038          * Force a name mangle here to ensure that the
2039          * mask as an 8.3 name is top of the mangled cache.
2040          * The reasons for this are subtle. Don't remove
2041          * this code unless you know what you are doing
2042          * (see PR#13758). JRA.
2043          */
2044
2045         if(!mangle_is_8_3_wildcards( mask, False, conn->params))
2046                 mangle_map(mask, True, True, conn->params);
2047
2048         return;
2049 }
2050
2051 /****************************************************************************
2052  Reply to a TRANS2_FINDNEXT.
2053 ****************************************************************************/
2054
2055 static void call_trans2findnext(connection_struct *conn,
2056                                 struct smb_request *req,
2057                                 char **pparams, int total_params,
2058                                 char **ppdata, int total_data,
2059                                 unsigned int max_data_bytes)
2060 {
2061         /* We must be careful here that we don't return more than the
2062                 allowed number of data bytes. If this means returning fewer than
2063                 maxentries then so be it. We assume that the redirector has
2064                 enough room for the fixed number of parameter bytes it has
2065                 requested. */
2066         char *params = *pparams;
2067         char *pdata = *ppdata;
2068         char *data_end;
2069         int dptr_num;
2070         int maxentries;
2071         uint16 info_level;
2072         uint32 resume_key;
2073         uint16 findnext_flags;
2074         BOOL close_after_request;
2075         BOOL close_if_end;
2076         BOOL requires_resume_key;
2077         BOOL continue_bit;
2078         BOOL mask_contains_wcard = False;
2079         pstring resume_name;
2080         pstring mask;
2081         pstring directory;
2082         char *p;
2083         uint16 dirtype;
2084         int numentries = 0;
2085         int i, last_entry_off=0;
2086         BOOL finished = False;
2087         BOOL dont_descend = False;
2088         BOOL out_of_space = False;
2089         int space_remaining;
2090         TALLOC_CTX *ea_ctx = NULL;
2091         struct ea_list *ea_list = NULL;
2092         NTSTATUS ntstatus = NT_STATUS_OK;
2093
2094         if (total_params < 13) {
2095                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2096                 return;
2097         }
2098
2099         dptr_num = SVAL(params,0);
2100         maxentries = SVAL(params,2);
2101         info_level = SVAL(params,4);
2102         resume_key = IVAL(params,6);
2103         findnext_flags = SVAL(params,10);
2104         close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2105         close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2106         requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2107         continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2108
2109         *mask = *directory = *resume_name = 0;
2110
2111         srvstr_get_path_wcard(params, req->flags2, resume_name,
2112                               params+12, sizeof(resume_name),
2113                               total_params - 12, STR_TERMINATE, &ntstatus,
2114                               &mask_contains_wcard);
2115         if (!NT_STATUS_IS_OK(ntstatus)) {
2116                 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2117                    complain (it thinks we're asking for the directory above the shared
2118                    path or an invalid name). Catch this as the resume name is only compared, never used in
2119                    a file access. JRA. */
2120                 srvstr_pull(params, req->flags2,
2121                                 resume_name, params+12,
2122                                 sizeof(resume_name), total_params - 12,
2123                                 STR_TERMINATE);
2124
2125                 if (!(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2126                         reply_nterror(req, ntstatus);
2127                         return;
2128                 }
2129         }
2130
2131         DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2132 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2133 resume_key = %d resume name = %s continue=%d level = %d\n",
2134                 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end, 
2135                 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
2136
2137         if (!maxentries) {
2138                 /* W2K3 seems to treat zero as 1. */
2139                 maxentries = 1;
2140         }
2141
2142         switch (info_level) {
2143                 case SMB_FIND_INFO_STANDARD:
2144                 case SMB_FIND_EA_SIZE:
2145                 case SMB_FIND_EA_LIST:
2146                 case SMB_FIND_FILE_DIRECTORY_INFO:
2147                 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2148                 case SMB_FIND_FILE_NAMES_INFO:
2149                 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2150                 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2151                 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2152                         break;
2153                 case SMB_FIND_FILE_UNIX:
2154                 case SMB_FIND_FILE_UNIX_INFO2:
2155                         if (!lp_unix_extensions()) {
2156                                 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2157                                 return;
2158                         }
2159                         break;
2160                 default:
2161                         reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2162                         return;
2163         }
2164
2165         if (info_level == SMB_FIND_EA_LIST) {
2166                 uint32 ea_size;
2167
2168                 if (total_data < 4) {
2169                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2170                         return;
2171                 }
2172
2173                 ea_size = IVAL(pdata,0);
2174                 if (ea_size != total_data) {
2175                         DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2176 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2177                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2178                         return;
2179                 }
2180                                                                                                                                                      
2181                 if (!lp_ea_support(SNUM(conn))) {
2182                         reply_doserror(req, ERRDOS, ERReasnotsupported);
2183                         return;
2184                 }
2185                                                                                                                                                      
2186                 if ((ea_ctx = talloc_init("findnext_ea_list")) == NULL) {
2187                         reply_nterror(req, NT_STATUS_NO_MEMORY);
2188                         return;
2189                 }
2190
2191                 /* Pull out the list of names. */
2192                 ea_list = read_ea_name_list(ea_ctx, pdata + 4, ea_size - 4);
2193                 if (!ea_list) {
2194                         talloc_destroy(ea_ctx);
2195                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2196                         return;
2197                 }
2198         }
2199
2200         *ppdata = (char *)SMB_REALLOC(
2201                 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2202         if(*ppdata == NULL) {
2203                 talloc_destroy(ea_ctx);
2204                 reply_nterror(req, NT_STATUS_NO_MEMORY);
2205                 return;
2206         }
2207
2208         pdata = *ppdata;
2209         data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2210
2211         /* Realloc the params space */
2212         *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2213         if(*pparams == NULL ) {
2214                 talloc_destroy(ea_ctx);
2215                 reply_nterror(req, NT_STATUS_NO_MEMORY);
2216                 return;
2217         }
2218
2219         params = *pparams;
2220
2221         /* Check that the dptr is valid */
2222         if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num))) {
2223                 talloc_destroy(ea_ctx);
2224                 reply_doserror(req, ERRDOS, ERRnofiles);
2225                 return;
2226         }
2227
2228         string_set(&conn->dirpath,dptr_path(dptr_num));
2229
2230         /* Get the wildcard mask from the dptr */
2231         if((p = dptr_wcard(dptr_num))== NULL) {
2232                 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2233                 talloc_destroy(ea_ctx);
2234                 reply_doserror(req, ERRDOS, ERRnofiles);
2235                 return;
2236         }
2237
2238         pstrcpy(mask, p);
2239         pstrcpy(directory,conn->dirpath);
2240
2241         /* Get the attr mask from the dptr */
2242         dirtype = dptr_attr(dptr_num);
2243
2244         DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2245                 dptr_num, mask, dirtype, 
2246                 (long)conn->dirptr,
2247                 dptr_TellDir(conn->dirptr)));
2248
2249         /* We don't need to check for VOL here as this is returned by 
2250                 a different TRANS2 call. */
2251
2252         DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
2253         if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2254                 dont_descend = True;
2255     
2256         p = pdata;
2257         space_remaining = max_data_bytes;
2258         out_of_space = False;
2259
2260         /* 
2261          * Seek to the correct position. We no longer use the resume key but
2262          * depend on the last file name instead.
2263          */
2264
2265         if(*resume_name && !continue_bit) {
2266                 SMB_STRUCT_STAT st;
2267
2268                 long current_pos = 0;
2269                 /*
2270                  * Remember, mangle_map is called by
2271                  * get_lanman2_dir_entry(), so the resume name
2272                  * could be mangled. Ensure we check the unmangled name.
2273                  */
2274
2275                 if (mangle_is_mangled(resume_name, conn->params)) {
2276                         mangle_check_cache(resume_name, sizeof(resume_name)-1,
2277                                            conn->params);
2278                 }
2279
2280                 /*
2281                  * Fix for NT redirector problem triggered by resume key indexes
2282                  * changing between directory scans. We now return a resume key of 0
2283                  * and instead look for the filename to continue from (also given
2284                  * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2285                  * findfirst/findnext (as is usual) then the directory pointer
2286                  * should already be at the correct place.
2287                  */
2288
2289                 finished = !dptr_SearchDir(conn->dirptr, resume_name, &current_pos, &st);
2290         } /* end if resume_name && !continue_bit */
2291
2292         for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2293                 BOOL got_exact_match = False;
2294
2295                 /* this is a heuristic to avoid seeking the dirptr except when 
2296                         absolutely necessary. It allows for a filename of about 40 chars */
2297                 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2298                         out_of_space = True;
2299                         finished = False;
2300                 } else {
2301                         finished = !get_lanman2_dir_entry(conn,
2302                                                 req->flags2,
2303                                                 mask,dirtype,info_level,
2304                                                 requires_resume_key,dont_descend,
2305                                                 &p,pdata,data_end,
2306                                                 space_remaining, &out_of_space,
2307                                                 &got_exact_match,
2308                                                 &last_entry_off, ea_list, ea_ctx);
2309                 }
2310
2311                 if (finished && out_of_space)
2312                         finished = False;
2313
2314                 if (!finished && !out_of_space)
2315                         numentries++;
2316
2317                 /*
2318                  * As an optimisation if we know we aren't looking
2319                  * for a wildcard name (ie. the name matches the wildcard exactly)
2320                  * then we can finish on any (first) match.
2321                  * This speeds up large directory searches. JRA.
2322                  */
2323
2324                 if(got_exact_match)
2325                         finished = True;
2326
2327                 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2328         }
2329   
2330         talloc_destroy(ea_ctx);
2331
2332         /* Check if we can close the dirptr */
2333         if(close_after_request || (finished && close_if_end)) {
2334                 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2335                 dptr_close(&dptr_num); /* This frees up the saved mask */
2336         }
2337
2338         /* Set up the return parameter block */
2339         SSVAL(params,0,numentries);
2340         SSVAL(params,2,finished);
2341         SSVAL(params,4,0); /* Never an EA error */
2342         SSVAL(params,6,last_entry_off);
2343
2344         send_trans2_replies_new(req, params, 8, pdata, PTR_DIFF(p,pdata),
2345                                 max_data_bytes);
2346
2347         if ((! *directory) && dptr_path(dptr_num))
2348                 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
2349
2350         DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2351                 smb_fn_name(CVAL(req->inbuf,smb_com)),
2352                 mask, directory, dirtype, numentries ) );
2353
2354         return;
2355 }
2356
2357 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
2358 {
2359         E_md4hash(lp_servicename(SNUM(conn)),objid);
2360         return objid;
2361 }
2362
2363 /****************************************************************************
2364  Reply to a TRANS2_QFSINFO (query filesystem info).
2365 ****************************************************************************/
2366
2367 static void call_trans2qfsinfo(connection_struct *conn,
2368                                struct smb_request *req,
2369                                char **pparams, int total_params,
2370                                char **ppdata, int total_data,
2371                                unsigned int max_data_bytes)
2372 {
2373         char *pdata, *end_data;
2374         char *params = *pparams;
2375         uint16 info_level;
2376         int data_len, len;
2377         SMB_STRUCT_STAT st;
2378         const char *vname = volume_label(SNUM(conn));
2379         int snum = SNUM(conn);
2380         char *fstype = lp_fstype(SNUM(conn));
2381         int quota_flag = 0;
2382
2383         if (total_params < 2) {
2384                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2385                 return;
2386         }
2387
2388         info_level = SVAL(params,0);
2389
2390         DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
2391
2392         if(SMB_VFS_STAT(conn,".",&st)!=0) {
2393                 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
2394                 reply_doserror(req, ERRSRV, ERRinvdevice);
2395                 return;
2396         }
2397
2398         *ppdata = (char *)SMB_REALLOC(
2399                 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2400         if (*ppdata == NULL ) {
2401                 reply_nterror(req, NT_STATUS_NO_MEMORY);
2402                 return;
2403         }
2404
2405         pdata = *ppdata;
2406         memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2407         end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2408
2409         switch (info_level) {
2410                 case SMB_INFO_ALLOCATION:
2411                 {
2412                         SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2413                         data_len = 18;
2414                         if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2415                                 reply_unixerror(req, ERRHRD, ERRgeneral);
2416                                 return;
2417                         }
2418
2419                         block_size = lp_block_size(snum);
2420                         if (bsize < block_size) {
2421                                 SMB_BIG_UINT factor = block_size/bsize;
2422                                 bsize = block_size;
2423                                 dsize /= factor;
2424                                 dfree /= factor;
2425                         }
2426                         if (bsize > block_size) {
2427                                 SMB_BIG_UINT factor = bsize/block_size;
2428                                 bsize = block_size;
2429                                 dsize *= factor;
2430                                 dfree *= factor;
2431                         }
2432                         bytes_per_sector = 512;
2433                         sectors_per_unit = bsize/bytes_per_sector;
2434
2435                         DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2436 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2437                                 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2438
2439                         SIVAL(pdata,l1_idFileSystem,st.st_dev);
2440                         SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2441                         SIVAL(pdata,l1_cUnit,dsize);
2442                         SIVAL(pdata,l1_cUnitAvail,dfree);
2443                         SSVAL(pdata,l1_cbSector,bytes_per_sector);
2444                         break;
2445                 }
2446
2447                 case SMB_INFO_VOLUME:
2448                         /* Return volume name */
2449                         /* 
2450                          * Add volume serial number - hash of a combination of
2451                          * the called hostname and the service name.
2452                          */
2453                         SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2454                         /*
2455                          * Win2k3 and previous mess this up by sending a name length
2456                          * one byte short. I believe only older clients (OS/2 Win9x) use
2457                          * this call so try fixing this by adding a terminating null to
2458                          * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2459                          */
2460                         len = srvstr_push(
2461                                 pdata, req->flags2,
2462                                 pdata+l2_vol_szVolLabel, vname,
2463                                 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
2464                                 STR_NOALIGN|STR_TERMINATE);
2465                         SCVAL(pdata,l2_vol_cch,len);
2466                         data_len = l2_vol_szVolLabel + len;
2467                         DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
2468                                 (unsigned)st.st_ctime, len, vname));
2469                         break;
2470
2471                 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2472                 case SMB_FS_ATTRIBUTE_INFORMATION:
2473
2474
2475 #if defined(HAVE_SYS_QUOTAS)
2476                         quota_flag = FILE_VOLUME_QUOTAS;
2477 #endif
2478
2479                         SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2480                                 (lp_nt_acl_support(SNUM(conn)) ? FILE_PERSISTENT_ACLS : 0)|
2481                                 FILE_SUPPORTS_OBJECT_IDS|
2482                                 FILE_UNICODE_ON_DISK|
2483                                 quota_flag); /* FS ATTRIBUTES */
2484
2485                         SIVAL(pdata,4,255); /* Max filename component length */
2486                         /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2487                                 and will think we can't do long filenames */
2488                         len = srvstr_push(pdata, req->flags2, pdata+12, fstype,
2489                                           PTR_DIFF(end_data, pdata+12),
2490                                           STR_UNICODE);
2491                         SIVAL(pdata,8,len);
2492                         data_len = 12 + len;
2493                         break;
2494
2495                 case SMB_QUERY_FS_LABEL_INFO:
2496                 case SMB_FS_LABEL_INFORMATION:
2497                         len = srvstr_push(pdata, req->flags2, pdata+4, vname,
2498                                           PTR_DIFF(end_data, pdata+4), 0);
2499                         data_len = 4 + len;
2500                         SIVAL(pdata,0,len);
2501                         break;
2502
2503                 case SMB_QUERY_FS_VOLUME_INFO:      
2504                 case SMB_FS_VOLUME_INFORMATION:
2505
2506                         /* 
2507                          * Add volume serial number - hash of a combination of
2508                          * the called hostname and the service name.
2509                          */
2510                         SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^ 
2511                                 (str_checksum(get_local_machine_name())<<16));
2512
2513                         /* Max label len is 32 characters. */
2514                         len = srvstr_push(pdata, req->flags2, pdata+18, vname,
2515                                           PTR_DIFF(end_data, pdata+18),
2516                                           STR_UNICODE);
2517                         SIVAL(pdata,12,len);
2518                         data_len = 18+len;
2519
2520                         DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n", 
2521                                 (int)strlen(vname),vname, lp_servicename(snum)));
2522                         break;
2523
2524                 case SMB_QUERY_FS_SIZE_INFO:
2525                 case SMB_FS_SIZE_INFORMATION:
2526                 {
2527                         SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2528                         data_len = 24;
2529                         if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2530                                 reply_unixerror(req, ERRHRD, ERRgeneral);
2531                                 return;
2532                         }
2533                         block_size = lp_block_size(snum);
2534                         if (bsize < block_size) {
2535                                 SMB_BIG_UINT factor = block_size/bsize;
2536                                 bsize = block_size;
2537                                 dsize /= factor;
2538                                 dfree /= factor;
2539                         }
2540                         if (bsize > block_size) {
2541                                 SMB_BIG_UINT factor = bsize/block_size;
2542                                 bsize = block_size;
2543                                 dsize *= factor;
2544                                 dfree *= factor;
2545                         }
2546                         bytes_per_sector = 512;
2547                         sectors_per_unit = bsize/bytes_per_sector;
2548                         DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2549 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2550                                 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2551                         SBIG_UINT(pdata,0,dsize);
2552                         SBIG_UINT(pdata,8,dfree);
2553                         SIVAL(pdata,16,sectors_per_unit);
2554                         SIVAL(pdata,20,bytes_per_sector);
2555                         break;
2556                 }
2557
2558                 case SMB_FS_FULL_SIZE_INFORMATION:
2559                 {
2560                         SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2561                         data_len = 32;
2562                         if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2563                                 reply_unixerror(req, ERRHRD, ERRgeneral);
2564                                 return;
2565                         }
2566                         block_size = lp_block_size(snum);
2567                         if (bsize < block_size) {
2568                                 SMB_BIG_UINT factor = block_size/bsize;
2569                                 bsize = block_size;
2570                                 dsize /= factor;
2571                                 dfree /= factor;
2572                         }
2573                         if (bsize > block_size) {
2574                                 SMB_BIG_UINT factor = bsize/block_size;
2575                                 bsize = block_size;
2576                                 dsize *= factor;
2577                                 dfree *= factor;
2578                         }
2579                         bytes_per_sector = 512;
2580                         sectors_per_unit = bsize/bytes_per_sector;
2581                         DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2582 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2583                                 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2584                         SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2585                         SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2586                         SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2587                         SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2588                         SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2589                         break;
2590                 }
2591
2592                 case SMB_QUERY_FS_DEVICE_INFO:
2593                 case SMB_FS_DEVICE_INFORMATION:
2594                         data_len = 8;
2595                         SIVAL(pdata,0,0); /* dev type */
2596                         SIVAL(pdata,4,0); /* characteristics */
2597                         break;
2598
2599 #ifdef HAVE_SYS_QUOTAS
2600                 case SMB_FS_QUOTA_INFORMATION:
2601                 /* 
2602                  * what we have to send --metze:
2603                  *
2604                  * Unknown1:            24 NULL bytes
2605                  * Soft Quota Treshold: 8 bytes seems like SMB_BIG_UINT or so
2606                  * Hard Quota Limit:    8 bytes seems like SMB_BIG_UINT or so
2607                  * Quota Flags:         2 byte :
2608                  * Unknown3:            6 NULL bytes
2609                  *
2610                  * 48 bytes total
2611                  * 
2612                  * details for Quota Flags:
2613                  * 
2614                  * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2615                  * 0x0010 Log Warn:  log if the user exceeds his Soft Quota
2616                  * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2617                  * 0x0001 Enable Quotas: enable quota for this fs
2618                  *
2619                  */
2620                 {
2621                         /* we need to fake up a fsp here,
2622                          * because its not send in this call
2623                          */
2624                         files_struct fsp;
2625                         SMB_NTQUOTA_STRUCT quotas;
2626                         
2627                         ZERO_STRUCT(fsp);
2628                         ZERO_STRUCT(quotas);
2629                         
2630                         fsp.conn = conn;
2631                         fsp.fnum = -1;
2632                         
2633                         /* access check */
2634                         if (current_user.ut.uid != 0) {
2635                                 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2636                                         lp_servicename(SNUM(conn)),conn->user));
2637                                 reply_doserror(req, ERRDOS, ERRnoaccess);
2638                                 return;
2639                         }
2640                         
2641                         if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
2642                                 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2643                                 reply_doserror(req, ERRSRV, ERRerror);
2644                                 return;
2645                         }
2646
2647                         data_len = 48;
2648
2649                         DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn))));          
2650                 
2651                         /* Unknown1 24 NULL bytes*/
2652                         SBIG_UINT(pdata,0,(SMB_BIG_UINT)0);
2653                         SBIG_UINT(pdata,8,(SMB_BIG_UINT)0);
2654                         SBIG_UINT(pdata,16,(SMB_BIG_UINT)0);
2655                 
2656                         /* Default Soft Quota 8 bytes */
2657                         SBIG_UINT(pdata,24,quotas.softlim);
2658
2659                         /* Default Hard Quota 8 bytes */
2660                         SBIG_UINT(pdata,32,quotas.hardlim);
2661         
2662                         /* Quota flag 2 bytes */
2663                         SSVAL(pdata,40,quotas.qflags);
2664                 
2665                         /* Unknown3 6 NULL bytes */
2666                         SSVAL(pdata,42,0);
2667                         SIVAL(pdata,44,0);
2668                         
2669                         break;
2670                 }
2671 #endif /* HAVE_SYS_QUOTAS */
2672                 case SMB_FS_OBJECTID_INFORMATION:
2673                 {
2674                         unsigned char objid[16];
2675                         memcpy(pdata,create_volume_objectid(conn, objid),16);
2676                         data_len = 64;
2677                         break;
2678                 }
2679
2680                 /*
2681                  * Query the version and capabilities of the CIFS UNIX extensions
2682                  * in use.
2683                  */
2684
2685                 case SMB_QUERY_CIFS_UNIX_INFO:
2686                         if (!lp_unix_extensions()) {
2687                                 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2688                                 return;
2689                         }
2690                         data_len = 12;
2691                         SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2692                         SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2693                         /* We have POSIX ACLs, pathname and locking capability. */
2694                         SBIG_UINT(pdata,4,((SMB_BIG_UINT)(
2695                                         CIFS_UNIX_POSIX_ACLS_CAP|
2696                                         CIFS_UNIX_POSIX_PATHNAMES_CAP|
2697                                         CIFS_UNIX_FCNTL_LOCKS_CAP|
2698                                         CIFS_UNIX_EXTATTR_CAP|
2699                                         CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
2700                                         /* Ensure we don't do this on signed or sealed data. */
2701                                         (srv_is_signing_active() ? 0 : CIFS_UNIX_LARGE_READ_CAP)
2702                                         )));
2703                         break;
2704
2705                 case SMB_QUERY_POSIX_FS_INFO:
2706                 {
2707                         int rc;
2708                         vfs_statvfs_struct svfs;
2709
2710                         if (!lp_unix_extensions()) {
2711                                 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2712                                 return;
2713                         }
2714
2715                         rc = SMB_VFS_STATVFS(conn, ".", &svfs);
2716
2717                         if (!rc) {
2718                                 data_len = 56;
2719                                 SIVAL(pdata,0,svfs.OptimalTransferSize);
2720                                 SIVAL(pdata,4,svfs.BlockSize);
2721                                 SBIG_UINT(pdata,8,svfs.TotalBlocks);
2722                                 SBIG_UINT(pdata,16,svfs.BlocksAvail);
2723                                 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
2724                                 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
2725                                 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
2726                                 SBIG_UINT(pdata,48,svfs.FsIdentifier);
2727                                 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
2728 #ifdef EOPNOTSUPP
2729                         } else if (rc == EOPNOTSUPP) {
2730                                 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2731                                 return;
2732 #endif /* EOPNOTSUPP */
2733                         } else {
2734                                 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2735                                 reply_doserror(req, ERRSRV, ERRerror);
2736                                 return;
2737                         }
2738                         break;
2739                 }
2740
2741                 case SMB_QUERY_POSIX_WHOAMI:
2742                 {
2743                         uint32_t flags = 0;
2744                         uint32_t sid_bytes;
2745                         int i;
2746
2747                         if (!lp_unix_extensions()) {
2748                                 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2749                                 return;
2750                         }
2751
2752                         if (max_data_bytes < 40) {
2753                                 reply_nterror(req, NT_STATUS_BUFFER_TOO_SMALL);
2754                                 return;
2755                         }
2756
2757                         /* We ARE guest if global_sid_Builtin_Guests is
2758                          * in our list of SIDs.
2759                          */
2760                         if (nt_token_check_sid(&global_sid_Builtin_Guests,
2761                                     current_user.nt_user_token)) {
2762                                 flags |= SMB_WHOAMI_GUEST;
2763                         }
2764
2765                         /* We are NOT guest if global_sid_Authenticated_Users
2766                          * is in our list of SIDs.
2767                          */
2768                         if (nt_token_check_sid(&global_sid_Authenticated_Users,
2769                                     current_user.nt_user_token)) {
2770                                 flags &= ~SMB_WHOAMI_GUEST;
2771                         }
2772
2773                         /* NOTE: 8 bytes for UID/GID, irrespective of native
2774                          * platform size. This matches
2775                          * SMB_QUERY_FILE_UNIX_BASIC and friends.
2776                          */
2777                         data_len = 4 /* flags */
2778                             + 4 /* flag mask */
2779                             + 8 /* uid */
2780                             + 8 /* gid */
2781                             + 4 /* ngroups */
2782                             + 4 /* num_sids */
2783                             + 4 /* SID bytes */
2784                             + 4 /* pad/reserved */
2785                             + (current_user.ut.ngroups * 8)
2786                                 /* groups list */
2787                             + (current_user.nt_user_token->num_sids *
2788                                     SID_MAX_SIZE)
2789                                 /* SID list */;
2790
2791                         SIVAL(pdata, 0, flags);
2792                         SIVAL(pdata, 4, SMB_WHOAMI_MASK);
2793                         SBIG_UINT(pdata, 8, (SMB_BIG_UINT)current_user.ut.uid);
2794                         SBIG_UINT(pdata, 16, (SMB_BIG_UINT)current_user.ut.gid);
2795
2796
2797                         if (data_len >= max_data_bytes) {
2798                                 /* Potential overflow, skip the GIDs and SIDs. */
2799
2800                                 SIVAL(pdata, 24, 0); /* num_groups */
2801                                 SIVAL(pdata, 28, 0); /* num_sids */
2802                                 SIVAL(pdata, 32, 0); /* num_sid_bytes */
2803                                 SIVAL(pdata, 36, 0); /* reserved */
2804
2805                                 data_len = 40;
2806                                 break;
2807                         }
2808
2809                         SIVAL(pdata, 24, current_user.ut.ngroups);
2810                         SIVAL(pdata, 28,
2811                                 current_user.nt_user_token->num_sids);
2812
2813                         /* We walk the SID list twice, but this call is fairly
2814                          * infrequent, and I don't expect that it's performance
2815                          * sensitive -- jpeach
2816                          */
2817                         for (i = 0, sid_bytes = 0;
2818                             i < current_user.nt_user_token->num_sids; ++i) {
2819                                 sid_bytes +=
2820                                     sid_size(&current_user.nt_user_token->user_sids[i]);
2821                         }
2822
2823                         /* SID list byte count */
2824                         SIVAL(pdata, 32, sid_bytes);
2825
2826                         /* 4 bytes pad/reserved - must be zero */
2827                         SIVAL(pdata, 36, 0);
2828                         data_len = 40;
2829
2830                         /* GID list */
2831                         for (i = 0; i < current_user.ut.ngroups; ++i) {
2832                                 SBIG_UINT(pdata, data_len,
2833                                         (SMB_BIG_UINT)current_user.ut.groups[i]);
2834                                 data_len += 8;
2835                         }
2836
2837                         /* SID list */
2838                         for (i = 0;
2839                             i < current_user.nt_user_token->num_sids; ++i) {
2840                                 int sid_len =
2841                                     sid_size(&current_user.nt_user_token->user_sids[i]);
2842
2843                                 sid_linearize(pdata + data_len, sid_len,
2844                                     &current_user.nt_user_token->user_sids[i]);
2845                                 data_len += sid_len;
2846                         }
2847
2848                         break;
2849                 }
2850
2851                 case SMB_MAC_QUERY_FS_INFO:
2852                         /*
2853                          * Thursby MAC extension... ONLY on NTFS filesystems
2854                          * once we do streams then we don't need this
2855                          */
2856                         if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
2857                                 data_len = 88;
2858                                 SIVAL(pdata,84,0x100); /* Don't support mac... */
2859                                 break;
2860                         }
2861                         /* drop through */
2862                 default:
2863                         reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2864                         return;
2865         }
2866
2867
2868         send_trans2_replies_new(req, params, 0, pdata, data_len,
2869                                 max_data_bytes);
2870
2871         DEBUG( 4, ( "%s info_level = %d\n",
2872                     smb_fn_name(CVAL(req->inbuf,smb_com)), info_level) );
2873
2874         return;
2875 }
2876
2877 /****************************************************************************
2878  Reply to a TRANS2_SETFSINFO (set filesystem info).
2879 ****************************************************************************/
2880
2881 static void call_trans2setfsinfo(connection_struct *conn,
2882                                  struct smb_request *req,
2883                                  char **pparams, int total_params,
2884                                  char **ppdata, int total_data,
2885                                  unsigned int max_data_bytes)
2886 {
2887         char *pdata = *ppdata;
2888         char *params = *pparams;
2889         uint16 info_level;
2890
2891         DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
2892
2893         /*  */
2894         if (total_params < 4) {
2895                 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
2896                         total_params));
2897                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2898                 return;
2899         }
2900
2901         info_level = SVAL(params,2);
2902
2903         switch(info_level) {
2904                 case SMB_SET_CIFS_UNIX_INFO:
2905                         {
2906                                 uint16 client_unix_major;
2907                                 uint16 client_unix_minor;
2908                                 uint32 client_unix_cap_low;
2909                                 uint32 client_unix_cap_high;
2910
2911                                 if (!lp_unix_extensions()) {
2912                                         reply_nterror(req,
2913                                                       NT_STATUS_INVALID_LEVEL);
2914                                         return;
2915                                 }
2916
2917                                 /* There should be 12 bytes of capabilities set. */
2918                                 if (total_data < 8) {
2919                                         reply_nterror(
2920                                                 req,
2921                                                 NT_STATUS_INVALID_PARAMETER);
2922                                         return;
2923                                 }
2924                                 client_unix_major = SVAL(pdata,0);
2925                                 client_unix_minor = SVAL(pdata,2);
2926                                 client_unix_cap_low = IVAL(pdata,4);
2927                                 client_unix_cap_high = IVAL(pdata,8);
2928                                 /* Just print these values for now. */
2929                                 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
2930 cap_low = 0x%x, cap_high = 0x%x\n",
2931                                         (unsigned int)client_unix_major,
2932                                         (unsigned int)client_unix_minor,
2933                                         (unsigned int)client_unix_cap_low,
2934                                         (unsigned int)client_unix_cap_high ));
2935
2936                                 /* Here is where we must switch to posix pathname processing... */
2937                                 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
2938                                         lp_set_posix_pathnames();
2939                                         mangle_change_to_posix();
2940                                 }
2941
2942                                 if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
2943                                     !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
2944                                         /* Client that knows how to do posix locks,
2945                                          * but not posix open/mkdir operations. Set a
2946                                          * default type for read/write checks. */
2947
2948                                         lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
2949
2950                                 }
2951                                 break;
2952                         }
2953                 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
2954                         {
2955                                 NTSTATUS status;
2956                                 size_t param_len = 0;
2957                                 size_t data_len = total_data;
2958
2959                                 if (!lp_unix_extensions()) {
2960                                         reply_nterror(
2961                                                 req, NT_STATUS_INVALID_LEVEL);
2962                                         return;
2963                                 }
2964
2965                                 DEBUG( 4,("call_trans2setfsinfo: request transport encrption.\n"));
2966
2967                                 status = srv_request_encryption_setup(conn,
2968                                                                         (unsigned char **)ppdata,
2969                                                                         &data_len,
2970                                                                         (unsigned char **)pparams,
2971                                                                         &param_len
2972                                                                         );
2973
2974                                 if (!NT_STATUS_IS_OK(status)) {
2975                                         /*
2976                                          * TODO: Check
2977                                          * MORE_PROCESSING_REQUIRED, this used
2978                                          * to have special handling here.
2979                                          */
2980                                         reply_nterror(req, status);
2981                                         return;
2982                                 }
2983
2984                                 send_trans2_replies_new(req,
2985                                                         *pparams, param_len,
2986                                                         *ppdata, data_len,
2987                                                         max_data_bytes);
2988
2989                                 if (NT_STATUS_IS_OK(status)) {
2990                                         /* Server-side transport encryption is now *on*. */
2991                                         status = srv_encryption_start(conn);
2992                                         if (!NT_STATUS_IS_OK(status)) {
2993                                                 exit_server_cleanly("Failure in setting up encrypted transport");
2994                                         }
2995                                 }
2996                                 return;
2997                         }
2998                 case SMB_FS_QUOTA_INFORMATION:
2999                         {
3000                                 files_struct *fsp = NULL;
3001                                 SMB_NTQUOTA_STRUCT quotas;
3002         
3003                                 ZERO_STRUCT(quotas);
3004
3005                                 /* access check */
3006                                 if ((current_user.ut.uid != 0)||!CAN_WRITE(conn)) {
3007                                         DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3008                                                 lp_servicename(SNUM(conn)),conn->user));
3009                                         reply_doserror(req, ERRSRV, ERRaccess);
3010                                         return;
3011                                 }
3012
3013                                 /* note: normaly there're 48 bytes,
3014                                  * but we didn't use the last 6 bytes for now 
3015                                  * --metze 
3016                                  */
3017                                 fsp = file_fsp(SVAL(params,0));
3018                                 if (!CHECK_NTQUOTA_HANDLE_OK(fsp,conn)) {
3019                                         DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3020                                         reply_nterror(
3021                                                 req, NT_STATUS_INVALID_HANDLE);
3022                                         return;
3023                                 }
3024
3025                                 if (total_data < 42) {
3026                                         DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3027                                                 total_data));
3028                                         reply_nterror(
3029                                                 req,
3030                                                 NT_STATUS_INVALID_PARAMETER);
3031                                         return;
3032                                 }
3033                         
3034                                 /* unknown_1 24 NULL bytes in pdata*/
3035                 
3036                                 /* the soft quotas 8 bytes (SMB_BIG_UINT)*/
3037                                 quotas.softlim = (SMB_BIG_UINT)IVAL(pdata,24);
3038 #ifdef LARGE_SMB_OFF_T
3039                                 quotas.softlim |= (((SMB_BIG_UINT)IVAL(pdata,28)) << 32);
3040 #else /* LARGE_SMB_OFF_T */
3041                                 if ((IVAL(pdata,28) != 0)&&
3042                                         ((quotas.softlim != 0xFFFFFFFF)||
3043                                         (IVAL(pdata,28)!=0xFFFFFFFF))) {
3044                                         /* more than 32 bits? */
3045                                         reply_nterror(
3046                                                 req,
3047                                                 NT_STATUS_INVALID_PARAMETER);
3048                                         return;
3049                                 }
3050 #endif /* LARGE_SMB_OFF_T */
3051                 
3052                                 /* the hard quotas 8 bytes (SMB_BIG_UINT)*/
3053                                 quotas.hardlim = (SMB_BIG_UINT)IVAL(pdata,32);
3054 #ifdef LARGE_SMB_OFF_T
3055                                 quotas.hardlim |= (((SMB_BIG_UINT)IVAL(pdata,36)) << 32);
3056 #else /* LARGE_SMB_OFF_T */
3057                                 if ((IVAL(pdata,36) != 0)&&
3058                                         ((quotas.hardlim != 0xFFFFFFFF)||
3059                                         (IVAL(pdata,36)!=0xFFFFFFFF))) {
3060                                         /* more than 32 bits? */
3061                                         reply_nterror(
3062                                                 req,
3063                                                 NT_STATUS_INVALID_PARAMETER);
3064                                         return;
3065                                 }
3066 #endif /* LARGE_SMB_OFF_T */
3067                 
3068                                 /* quota_flags 2 bytes **/
3069                                 quotas.qflags = SVAL(pdata,40);
3070                 
3071                                 /* unknown_2 6 NULL bytes follow*/
3072                 
3073                                 /* now set the quotas */
3074                                 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
3075                                         DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3076                                         reply_doserror(req, ERRSRV, ERRerror);
3077                                         return;
3078                                 }
3079                         
3080                                 break;
3081                         }
3082                 default:
3083                         DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3084                                 info_level));
3085                         reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3086                         return;
3087                         break;
3088         }
3089
3090         /* 
3091          * sending this reply works fine, 
3092          * but I'm not sure it's the same 
3093          * like windows do...
3094          * --metze
3095          */
3096         reply_outbuf(req, 10, 0);
3097 }
3098
3099 #if defined(HAVE_POSIX_ACLS)
3100 /****************************************************************************
3101  Utility function to count the number of entries in a POSIX acl.
3102 ****************************************************************************/
3103
3104 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3105 {
3106         unsigned int ace_count = 0;
3107         int entry_id = SMB_ACL_FIRST_ENTRY;
3108         SMB_ACL_ENTRY_T entry;
3109
3110         while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3111                 /* get_next... */
3112                 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3113                         entry_id = SMB_ACL_NEXT_ENTRY;
3114                 }
3115                 ace_count++;
3116         }
3117         return ace_count;
3118 }
3119
3120 /****************************************************************************
3121  Utility function to marshall a POSIX acl into wire format.
3122 ****************************************************************************/
3123
3124 static BOOL marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3125 {
3126         int entry_id = SMB_ACL_FIRST_ENTRY;
3127         SMB_ACL_ENTRY_T entry;
3128
3129         while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3130                 SMB_ACL_TAG_T tagtype;
3131                 SMB_ACL_PERMSET_T permset;
3132                 unsigned char perms = 0;
3133                 unsigned int own_grp;
3134
3135                 /* get_next... */
3136                 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3137                         entry_id = SMB_ACL_NEXT_ENTRY;
3138                 }
3139
3140                 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
3141                         DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3142                         return False;
3143                 }
3144
3145                 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
3146                         DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3147                         return False;
3148                 }
3149
3150                 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3151                 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3152                 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3153
3154                 SCVAL(pdata,1,perms);
3155
3156                 switch (tagtype) {
3157                         case SMB_ACL_USER_OBJ:
3158                                 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3159                                 own_grp = (unsigned int)pst->st_uid;
3160                                 SIVAL(pdata,2,own_grp);
3161                                 SIVAL(pdata,6,0);
3162                                 break;
3163                         case SMB_ACL_USER:
3164                                 {
3165                                         uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3166                                         if (!puid) {
3167                                                 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3168                                                 return False;
3169                                         }
3170                                         own_grp = (unsigned int)*puid;
3171                                         SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
3172                                         SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3173                                         SIVAL(pdata,2,own_grp);
3174                                         SIVAL(pdata,6,0);
3175                                         break;
3176                                 }
3177                         case SMB_ACL_GROUP_OBJ:
3178                                 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3179                                 own_grp = (unsigned int)pst->st_gid;
3180                                 SIVAL(pdata,2,own_grp);
3181                                 SIVAL(pdata,6,0);
3182                                 break;
3183                         case SMB_ACL_GROUP:
3184                                 {
3185                                         gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3186                                         if (!pgid) {
3187                                                 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3188                                                 return False;
3189                                         }
3190                                         own_grp = (unsigned int)*pgid;
3191                                         SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
3192                                         SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3193                                         SIVAL(pdata,2,own_grp);
3194                                         SIVAL(pdata,6,0);
3195                                         break;
3196                                 }
3197                         case SMB_ACL_MASK:
3198                                 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3199                                 SIVAL(pdata,2,0xFFFFFFFF);
3200                                 SIVAL(pdata,6,0xFFFFFFFF);
3201                                 break;
3202                         case SMB_ACL_OTHER:
3203                                 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3204                                 SIVAL(pdata,2,0xFFFFFFFF);
3205                                 SIVAL(pdata,6,0xFFFFFFFF);
3206                                 break;
3207                         default:
3208                                 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3209                                 return False;
3210                 }
3211                 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3212         }
3213
3214         return True;
3215 }
3216 #endif
3217
3218 /****************************************************************************
3219  Store the FILE_UNIX_BASIC info.
3220 ****************************************************************************/
3221
3222 static char *store_file_unix_basic(connection_struct *conn,
3223                                 char *pdata,
3224                                 files_struct *fsp,
3225                                 const SMB_STRUCT_STAT *psbuf)
3226 {
3227         DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3228         DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_mode));
3229
3230         SOFF_T(pdata,0,get_file_size(*psbuf));             /* File size 64 Bit */
3231         pdata += 8;
3232
3233         SOFF_T(pdata,0,get_allocation_size(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3234         pdata += 8;
3235
3236         put_long_date_timespec(pdata,get_ctimespec(psbuf));       /* Change Time 64 Bit */
3237         put_long_date_timespec(pdata+8,get_atimespec(psbuf));     /* Last access time 64 Bit */
3238         put_long_date_timespec(pdata+16,get_mtimespec(psbuf));    /* Last modification time 64 Bit */
3239         pdata += 24;
3240
3241         SIVAL(pdata,0,psbuf->st_uid);               /* user id for the owner */
3242         SIVAL(pdata,4,0);
3243         pdata += 8;
3244
3245         SIVAL(pdata,0,psbuf->st_gid);               /* group id of owner */
3246         SIVAL(pdata,4,0);
3247         pdata += 8;
3248
3249         SIVAL(pdata,0,unix_filetype(psbuf->st_mode));
3250         pdata += 4;
3251
3252         SIVAL(pdata,0,unix_dev_major(psbuf->st_rdev));   /* Major device number if type is device */
3253         SIVAL(pdata,4,0);
3254         pdata += 8;
3255
3256         SIVAL(pdata,0,unix_dev_minor(psbuf->st_rdev));   /* Minor device number if type is device */
3257         SIVAL(pdata,4,0);
3258         pdata += 8;
3259
3260         SINO_T_VAL(pdata,0,(SMB_INO_T)psbuf->st_ino);   /* inode number */
3261         pdata += 8;
3262                                 
3263         SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_mode));     /* Standard UNIX file permissions */
3264         SIVAL(pdata,4,0);
3265         pdata += 8;
3266
3267         SIVAL(pdata,0,psbuf->st_nlink);             /* number of hard links */
3268         SIVAL(pdata,4,0);
3269         pdata += 8;
3270
3271         return pdata;
3272 }
3273
3274 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3275  * the chflags(2) (or equivalent) flags.
3276  *
3277  * XXX: this really should be behind the VFS interface. To do this, we would
3278  * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3279  * Each VFS module could then implement it's own mapping as appropriate for the
3280  * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3281  */
3282 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
3283         info2_flags_map[] =
3284 {
3285 #ifdef UF_NODUMP
3286     { UF_NODUMP, EXT_DO_NOT_BACKUP },
3287 #endif
3288
3289 #ifdef UF_IMMUTABLE
3290     { UF_IMMUTABLE, EXT_IMMUTABLE },
3291 #endif
3292
3293 #ifdef UF_APPEND
3294     { UF_APPEND, EXT_OPEN_APPEND_ONLY },
3295 #endif
3296
3297 #ifdef UF_HIDDEN
3298     { UF_HIDDEN, EXT_HIDDEN },
3299 #endif
3300
3301     /* Do not remove. We need to guarantee that this array has at least one
3302      * entry to build on HP-UX.
3303      */
3304     { 0, 0 }
3305
3306 };
3307
3308 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
3309                                 uint32 *smb_fflags, uint32 *smb_fmask)
3310 {
3311 #ifdef HAVE_STAT_ST_FLAGS
3312         int i;
3313
3314         for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3315             *smb_fmask |= info2_flags_map[i].smb_fflag;
3316             if (psbuf->st_flags & info2_flags_map[i].stat_fflag) {
3317                     *smb_fflags |= info2_flags_map[i].smb_fflag;
3318             }
3319         }
3320 #endif /* HAVE_STAT_ST_FLAGS */
3321 }
3322
3323 static BOOL map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
3324                                 const uint32 smb_fflags,
3325                                 const uint32 smb_fmask,
3326                                 int *stat_fflags)
3327 {
3328 #ifdef HAVE_STAT_ST_FLAGS
3329         uint32 max_fmask = 0;
3330         int i;
3331
3332         *stat_fflags = psbuf->st_flags;
3333
3334         /* For each flags requested in smb_fmask, check the state of the
3335          * corresponding flag in smb_fflags and set or clear the matching
3336          * stat flag.
3337          */
3338
3339         for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3340             max_fmask |= info2_flags_map[i].smb_fflag;
3341             if (smb_fmask & info2_flags_map[i].smb_fflag) {
3342                     if (smb_fflags & info2_flags_map[i].smb_fflag) {
3343                             *stat_fflags |= info2_flags_map[i].stat_fflag;
3344                     } else {
3345                             *stat_fflags &= ~info2_flags_map[i].stat_fflag;
3346                     }
3347             }
3348         }
3349
3350         /* If smb_fmask is asking to set any bits that are not supported by
3351          * our flag mappings, we should fail.
3352          */
3353         if ((smb_fmask & max_fmask) != smb_fmask) {
3354                 return False;
3355         }
3356
3357         return True;
3358 #else
3359         return False;
3360 #endif /* HAVE_STAT_ST_FLAGS */
3361 }
3362
3363
3364 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
3365  * of file flags and birth (create) time.
3366  */
3367 static char *store_file_unix_basic_info2(connection_struct *conn,
3368                                 char *pdata,
3369                                 files_struct *fsp,
3370                                 const SMB_STRUCT_STAT *psbuf)
3371 {
3372         uint32 file_flags = 0;
3373         uint32 flags_mask = 0;
3374
3375         pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
3376
3377         /* Create (birth) time 64 bit */
3378         put_long_date_timespec(pdata, get_create_timespec(psbuf, False));
3379         pdata += 8;
3380
3381         map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
3382         SIVAL(pdata, 0, file_flags); /* flags */
3383         SIVAL(pdata, 4, flags_mask); /* mask */
3384         pdata += 8;
3385
3386         return pdata;
3387 }
3388
3389 /****************************************************************************
3390  Reply to a TRANSACT2_QFILEINFO on a PIPE !
3391 ****************************************************************************/
3392
3393 static void call_trans2qpipeinfo(connection_struct *conn,
3394                                  struct smb_request *req,
3395                                  unsigned int tran_call,
3396                                  char **pparams, int total_params,
3397                                  char **ppdata, int total_data,
3398                                  unsigned int max_data_bytes)
3399 {
3400         char *params = *pparams;
3401         char *pdata = *ppdata;
3402         unsigned int data_size = 0;
3403         unsigned int param_size = 2;
3404         uint16 info_level;
3405         smb_np_struct *p_pipe = NULL;
3406
3407         if (!params) {
3408                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3409                 return;
3410         }
3411
3412         if (total_params < 4) {
3413                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3414                 return;
3415         }
3416
3417         p_pipe = get_rpc_pipe_p(SVAL(params,0));
3418         if (p_pipe == NULL) {
3419                 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
3420                 return;
3421         }
3422
3423         info_level = SVAL(params,2);
3424
3425         *pparams = (char *)SMB_REALLOC(*pparams,2);
3426         if (*pparams == NULL) {
3427                 reply_nterror(req, NT_STATUS_NO_MEMORY);
3428                 return;
3429         }
3430         params = *pparams;
3431         SSVAL(params,0,0);
3432         data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3433         *ppdata = (char *)SMB_REALLOC(*ppdata, data_size); 
3434         if (*ppdata == NULL ) {
3435                 reply_nterror(req, NT_STATUS_NO_MEMORY);
3436                 return;
3437         }
3438         pdata = *ppdata;
3439
3440         switch (info_level) {
3441                 case SMB_FILE_STANDARD_INFORMATION:
3442                         memset(pdata,24,0);
3443                         SOFF_T(pdata,0,4096LL);
3444                         SIVAL(pdata,16,1);
3445                         SIVAL(pdata,20,1);
3446                         data_size = 24;
3447                         break;
3448
3449                 default:
3450                         reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3451                         return;
3452         }
3453
3454         send_trans2_replies_new(req, params, param_size, *ppdata, data_size,
3455                                 max_data_bytes);
3456
3457         return;
3458 }
3459
3460 /****************************************************************************
3461  Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
3462  file name or file id).
3463 ****************************************************************************/
3464
3465 static void call_trans2qfilepathinfo(connection_struct *conn,
3466                                      struct smb_request *req,
3467                                      unsigned int tran_call,
3468                                      char **pparams, int total_params,
3469                                      char **ppdata, int total_data,
3470                                      unsigned int max_data_bytes)
3471 {
3472         char *params = *pparams;
3473         char *pdata = *ppdata;
3474         char *dstart, *dend;
3475         uint16 info_level;
3476         int mode=0;
3477         int nlink;
3478         SMB_OFF_T file_size=0;
3479         SMB_BIG_UINT allocation_size=0;
3480         unsigned int data_size = 0;
3481         unsigned int param_size = 2;
3482         SMB_STRUCT_STAT sbuf;
3483         pstring fname, dos_fname;
3484         char *fullpathname;
3485         char *base_name;
3486         char *p;
3487         SMB_OFF_T pos = 0;
3488         BOOL delete_pending = False;
3489         int len;
3490         time_t create_time, mtime, atime;
3491         struct timespec create_time_ts, mtime_ts, atime_ts;
3492         files_struct *fsp = NULL;
3493         struct file_id fileid;
3494         TALLOC_CTX *data_ctx = NULL;
3495         struct ea_list *ea_list = NULL;
3496         uint32 access_mask = 0x12019F; /* Default - GENERIC_EXECUTE mapping from Windows */
3497         char *lock_data = NULL;
3498
3499         if (!params) {
3500                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3501                 return;
3502         }
3503
3504         ZERO_STRUCT(sbuf);
3505
3506         if (tran_call == TRANSACT2_QFILEINFO) {
3507                 if (total_params < 4) {
3508                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3509                         return;
3510                 }
3511
3512                 if (IS_IPC(conn)) {
3513                         call_trans2qpipeinfo(conn, req, tran_call,
3514                                              pparams, total_params,
3515                                              ppdata, total_data,
3516                                              max_data_bytes);
3517                         return;
3518                 }
3519
3520                 fsp = file_fsp(SVAL(params,0));
3521                 info_level = SVAL(params,2);
3522
3523                 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
3524
3525                 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3526                         reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3527                         return;
3528                 }
3529
3530                 if(fsp && (fsp->fake_file_handle)) {
3531                         /*
3532                          * This is actually for the QUOTA_FAKE_FILE --metze
3533                          */
3534                                                 
3535                         pstrcpy(fname, fsp->fsp_name);
3536                         /* We know this name is ok, it's already passed the checks. */
3537                         
3538                 } else if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
3539                         /*
3540                          * This is actually a QFILEINFO on a directory
3541                          * handle (returned from an NT SMB). NT5.0 seems
3542                          * to do this call. JRA.
3543                          */
3544                         /* We know this name is ok, it's already passed the checks. */
3545                         pstrcpy(fname, fsp->fsp_name);
3546                   
3547                         if (INFO_LEVEL_IS_UNIX(info_level)) {
3548                                 /* Always do lstat for UNIX calls. */
3549                                 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
3550                                         DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
3551                                         reply_unixerror(req,ERRDOS,ERRbadpath);
3552                                         return;
3553                                 }
3554                         } else if (SMB_VFS_STAT(conn,fname,&sbuf)) {
3555                                 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
3556                                 reply_unixerror(req, ERRDOS, ERRbadpath);
3557                                 return;
3558                         }
3559
3560                         fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3561                         delete_pending = get_delete_on_close_flag(fileid);
3562                 } else {
3563                         /*
3564                          * Original code - this is an open file.
3565                          */
3566                         if (!check_fsp(conn, req, fsp, &current_user)) {
3567                                 return;
3568                         }
3569
3570                         pstrcpy(fname, fsp->fsp_name);
3571                         if (SMB_VFS_FSTAT(fsp,fsp->fh->fd,&sbuf) != 0) {
3572                                 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
3573                                 reply_unixerror(req, ERRDOS, ERRbadfid);
3574                                 return;
3575                         }
3576                         pos = fsp->fh->position_information;
3577                         fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3578                         delete_pending = get_delete_on_close_flag(fileid);
3579                         access_mask = fsp->access_mask;
3580                 }
3581         } else {
3582                 NTSTATUS status = NT_STATUS_OK;
3583
3584                 /* qpathinfo */
3585                 if (total_params < 7) {
3586                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3587                         return;
3588                 }
3589
3590                 info_level = SVAL(params,0);
3591
3592                 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
3593
3594                 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3595                         reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3596                         return;
3597                 }
3598
3599                 srvstr_get_path(params, req->flags2, fname, &params[6],
3600                                 sizeof(fname), total_params - 6,
3601                                 STR_TERMINATE, &status);
3602                 if (!NT_STATUS_IS_OK(status)) {
3603                         reply_nterror(req, status);
3604                         return;
3605                 }
3606
3607                 status = resolve_dfspath(conn,
3608                                          req->flags2 & FLAGS2_DFS_PATHNAMES,
3609                                          fname);
3610                 if (!NT_STATUS_IS_OK(status)) {
3611                         if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
3612                                 reply_botherror(req,
3613                                                 NT_STATUS_PATH_NOT_COVERED,
3614                                                 ERRSRV, ERRbadpath);
3615                         }
3616                         reply_nterror(req, status);
3617                         return;
3618                 }
3619
3620                 status = unix_convert(conn, fname, False, NULL, &sbuf);
3621                 if (!NT_STATUS_IS_OK(status)) {
3622                         reply_nterror(req, status);
3623                         return;
3624                 }
3625                 status = check_name(conn, fname);
3626                 if (!NT_STATUS_IS_OK(status)) {
3627                         DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,nt_errstr(status)));
3628                         reply_nterror(req, status);
3629                         return;
3630                 }
3631
3632                 if (INFO_LEVEL_IS_UNIX(info_level)) {
3633                         /* Always do lstat for UNIX calls. */
3634                         if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
3635                                 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
3636                                 reply_unixerror(req, ERRDOS, ERRbadpath);
3637                                 return;
3638                         }
3639                 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) {
3640                         DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
3641                         reply_unixerror(req, ERRDOS, ERRbadpath);
3642                         return;
3643                 }
3644
3645                 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3646                 delete_pending = get_delete_on_close_flag(fileid);
3647                 if (delete_pending) {
3648                         reply_nterror(req, NT_STATUS_DELETE_PENDING);
3649                         return;
3650                 }
3651         }
3652
3653         nlink = sbuf.st_nlink;
3654
3655         if ((nlink > 0) && S_ISDIR(sbuf.st_mode)) {
3656                 /* NTFS does not seem to count ".." */
3657                 nlink -= 1;
3658         }
3659
3660         if ((nlink > 0) && delete_pending) {
3661                 nlink -= 1;
3662         }
3663
3664         if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3665                 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3666                 return;
3667         }
3668
3669         DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
3670                 fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
3671
3672         p = strrchr_m(fname,'/'); 
3673         if (!p)
3674                 base_name = fname;
3675         else
3676                 base_name = p+1;
3677
3678         mode = dos_mode(conn,fname,&sbuf);
3679         if (!mode)
3680                 mode = FILE_ATTRIBUTE_NORMAL;
3681
3682         fullpathname = fname;
3683         if (!(mode & aDIR))
3684                 file_size = get_file_size(sbuf);
3685
3686         /* Pull out any data sent here before we realloc. */
3687         switch (info_level) {
3688                 case SMB_INFO_QUERY_EAS_FROM_LIST:
3689                 {
3690                         /* Pull any EA list from the data portion. */
3691                         uint32 ea_size;
3692
3693                         if (total_data < 4) {
3694                                 reply_nterror(
3695                                         req, NT_STATUS_INVALID_PARAMETER);
3696                                 return;
3697                         }
3698                         ea_size = IVAL(pdata,0);
3699
3700                         if (total_data > 0 && ea_size != total_data) {
3701                                 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
3702 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
3703                                 reply_nterror(
3704                                         req, NT_STATUS_INVALID_PARAMETER);
3705                                 return;
3706                         }
3707
3708                         if (!lp_ea_support(SNUM(conn))) {
3709                                 reply_doserror(req, ERRDOS,
3710                                                ERReasnotsupported);
3711                                 return;
3712                         }
3713
3714                         if ((data_ctx = talloc_init("ea_list")) == NULL) {
3715                                 reply_nterror(req, NT_STATUS_NO_MEMORY);
3716                                 return;
3717                         }
3718
3719                         /* Pull out the list of names. */
3720                         ea_list = read_ea_name_list(data_ctx, pdata + 4, ea_size - 4);
3721                         if (!ea_list) {
3722                                 talloc_destroy(data_ctx);
3723                                 reply_nterror(
3724                                         req, NT_STATUS_INVALID_PARAMETER);
3725                                 return;
3726                         }
3727                         break;
3728                 }
3729
3730                 case SMB_QUERY_POSIX_LOCK:
3731                 {
3732                         if (fsp == NULL || fsp->fh->fd == -1) {
3733                                 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
3734                                 return;
3735                         }
3736
3737                         if (total_data != POSIX_LOCK_DATA_SIZE) {
3738                                 reply_nterror(
3739                                         req, NT_STATUS_INVALID_PARAMETER);
3740                                 return;
3741                         }
3742
3743                         if ((data_ctx = talloc_init("lock_request")) == NULL) {
3744                                 reply_nterror(req, NT_STATUS_NO_MEMORY);
3745                                 return;
3746                         }
3747
3748                         /* Copy the lock range data. */
3749                         lock_data = (char *)TALLOC_MEMDUP(
3750                                 data_ctx, pdata, total_data);
3751                         if (!lock_data) {
3752                                 talloc_destroy(data_ctx);
3753                                 reply_nterror(req, NT_STATUS_NO_MEMORY);
3754                                 return;
3755                         }
3756                 }
3757                 default:
3758                         break;
3759         }
3760
3761         *pparams = (char *)SMB_REALLOC(*pparams,2);
3762         if (*pparams == NULL) {
3763                 talloc_destroy(data_ctx);
3764                 reply_nterror(req, NT_STATUS_NO_MEMORY);
3765                 return;
3766         }
3767         params = *pparams;
3768         SSVAL(params,0,0);
3769         data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3770         *ppdata = (char *)SMB_REALLOC(*ppdata, data_size); 
3771         if (*ppdata == NULL ) {
3772                 talloc_destroy(data_ctx);
3773                 reply_nterror(req, NT_STATUS_NO_MEMORY);
3774                 return;
3775         }
3776         pdata = *ppdata;
3777         dstart = pdata;
3778         dend = dstart + data_size - 1;
3779
3780         create_time_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
3781         mtime_ts = get_mtimespec(&sbuf);
3782         atime_ts = get_atimespec(&sbuf);
3783
3784         allocation_size = get_allocation_size(conn,fsp,&sbuf);
3785
3786         if (fsp) {
3787                 if (!null_timespec(fsp->pending_modtime)) {
3788                         /* the pending modtime overrides the current modtime */
3789                         mtime_ts = fsp->pending_modtime;
3790                 }
3791         } else {
3792                 files_struct *fsp1;
3793                 /* Do we have this path open ? */
3794                 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3795                 fsp1 = file_find_di_first(fileid);
3796                 if (fsp1 && !null_timespec(fsp1->pending_modtime)) {
3797                         /* the pending modtime overrides the current modtime */
3798                         mtime_ts = fsp1->pending_modtime;
3799                 }
3800                 if (fsp1 && fsp1->initial_allocation_size) {
3801                         allocation_size = get_allocation_size(conn, fsp1, &sbuf);
3802                 }
3803         }
3804
3805         if (lp_dos_filetime_resolution(SNUM(conn))) {
3806                 dos_filetime_timespec(&create_time_ts);
3807                 dos_filetime_timespec(&mtime_ts);
3808                 dos_filetime_timespec(&atime_ts);
3809         }
3810
3811         create_time = convert_timespec_to_time_t(create_time_ts);
3812         mtime = convert_timespec_to_time_t(mtime_ts);
3813         atime = convert_timespec_to_time_t(atime_ts);
3814
3815         /* NT expects the name to be in an exact form of the *full*
3816            filename. See the trans2 torture test */
3817         if (strequal(base_name,".")) {
3818                 pstrcpy(dos_fname, "\\");
3819         } else {
3820                 pstr_sprintf(dos_fname, "\\%s", fname);
3821                 string_replace(dos_fname, '/', '\\');
3822         }
3823
3824         switch (info_level) {
3825                 case SMB_INFO_STANDARD:
3826                         DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
3827                         data_size = 22;
3828                         srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
3829                         srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
3830                         srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
3831                         SIVAL(pdata,l1_cbFile,(uint32)file_size);
3832                         SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
3833                         SSVAL(pdata,l1_attrFile,mode);
3834                         break;
3835
3836                 case SMB_INFO_QUERY_EA_SIZE:
3837                 {
3838                         unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3839                         DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
3840                         data_size = 26;
3841                         srv_put_dos_date2(pdata,0,create_time);
3842                         srv_put_dos_date2(pdata,4,atime);
3843                         srv_put_dos_date2(pdata,8,mtime); /* write time */
3844                         SIVAL(pdata,12,(uint32)file_size);
3845                         SIVAL(pdata,16,(uint32)allocation_size);
3846                         SSVAL(pdata,20,mode);
3847                         SIVAL(pdata,22,ea_size);
3848                         break;
3849                 }
3850
3851                 case SMB_INFO_IS_NAME_VALID:
3852                         DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
3853                         if (tran_call == TRANSACT2_QFILEINFO) {
3854                                 /* os/2 needs this ? really ?*/      
3855                                 reply_doserror(req, ERRDOS, ERRbadfunc);
3856                                 return;
3857                         }
3858                         data_size = 0;
3859                         param_size = 0;
3860                         break;
3861                         
3862                 case SMB_INFO_QUERY_EAS_FROM_LIST:
3863                 {
3864                         size_t total_ea_len = 0;
3865                         struct ea_list *ea_file_list = NULL;
3866
3867                         DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
3868
3869                         ea_file_list = get_ea_list_from_file(data_ctx, conn, fsp, fname, &total_ea_len);
3870                         ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
3871
3872                         if (!ea_list || (total_ea_len > data_size)) {
3873                                 talloc_destroy(data_ctx);
3874                                 data_size = 4;
3875                                 SIVAL(pdata,0,4);   /* EA List Length must be set to 4 if no EA's. */
3876                                 break;
3877                         }
3878
3879                         data_size = fill_ea_buffer(data_ctx, pdata, data_size, conn, ea_list);
3880                         talloc_destroy(data_ctx);
3881                         break;
3882                 }
3883
3884                 case SMB_INFO_QUERY_ALL_EAS:
3885                 {
3886                         /* We have data_size bytes to put EA's into. */
3887                         size_t total_ea_len = 0;
3888
3889                         DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
3890
3891                         data_ctx = talloc_init("ea_ctx");
3892                         if (!data_ctx) {
3893                                 reply_nterror(req, NT_STATUS_NO_MEMORY);
3894                                 return;
3895                         }
3896
3897                         ea_list = get_ea_list_from_file(data_ctx, conn, fsp, fname, &total_ea_len);
3898                         if (!ea_list || (total_ea_len > data_size)) {
3899                                 talloc_destroy(data_ctx);
3900                                 data_size = 4;
3901                                 SIVAL(pdata,0,4);   /* EA List Length must be set to 4 if no EA's. */
3902                                 break;
3903                         }
3904
3905                         data_size = fill_ea_buffer(data_ctx, pdata, data_size, conn, ea_list);
3906                         talloc_destroy(data_ctx);
3907                         break;
3908                 }
3909
3910                 case SMB_FILE_BASIC_INFORMATION:
3911                 case SMB_QUERY_FILE_BASIC_INFO:
3912
3913                         if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
3914                                 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
3915                                 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
3916                         } else {
3917                                 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
3918                                 data_size = 40;
3919                                 SIVAL(pdata,36,0);
3920                         }
3921                         put_long_date_timespec(pdata,create_time_ts);
3922                         put_long_date_timespec(pdata+8,atime_ts);
3923                         put_long_date_timespec(pdata+16,mtime_ts); /* write time */
3924                         put_long_date_timespec(pdata+24,mtime_ts); /* change time */
3925                         SIVAL(pdata,32,mode);
3926
3927                         DEBUG(5,("SMB_QFBI - "));
3928                         DEBUG(5,("create: %s ", ctime(&create_time)));
3929                         DEBUG(5,("access: %s ", ctime(&atime)));
3930                         DEBUG(5,("write: %s ", ctime(&mtime)));
3931                         DEBUG(5,("change: %s ", ctime(&mtime)));
3932                         DEBUG(5,("mode: %x\n", mode));
3933                         break;
3934
3935                 case SMB_FILE_STANDARD_INFORMATION:
3936                 case SMB_QUERY_FILE_STANDARD_INFO:
3937
3938                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
3939                         data_size = 24;
3940                         SOFF_T(pdata,0,allocation_size);
3941                         SOFF_T(pdata,8,file_size);
3942                         SIVAL(pdata,16,nlink);
3943                         SCVAL(pdata,20,delete_pending?1:0);
3944                         SCVAL(pdata,21,(mode&aDIR)?1:0);
3945                         SSVAL(pdata,22,0); /* Padding. */
3946                         break;
3947
3948                 case SMB_FILE_EA_INFORMATION:
3949                 case SMB_QUERY_FILE_EA_INFO:
3950                 {
3951                         unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3952                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
3953                         data_size = 4;
3954                         SIVAL(pdata,0,ea_size);
3955                         break;
3956                 }
3957
3958                 /* Get the 8.3 name - used if NT SMB was negotiated. */
3959                 case SMB_QUERY_FILE_ALT_NAME_INFO:
3960                 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
3961                 {
3962                         pstring short_name;
3963
3964                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
3965                         pstrcpy(short_name,base_name);
3966                         /* Mangle if not already 8.3 */
3967                         if(!mangle_is_8_3(short_name, True, conn->params)) {
3968                                 mangle_map(short_name,True,True,conn->params);
3969                         }
3970                         len = srvstr_push(dstart, req->flags2,
3971                                           pdata+4, short_name,
3972                                           PTR_DIFF(dend, pdata+4),
3973                                           STR_UNICODE);
3974                         data_size = 4 + len;
3975                         SIVAL(pdata,0,len);
3976                         break;
3977                 }
3978
3979                 case SMB_QUERY_FILE_NAME_INFO:
3980                         /*
3981                           this must be *exactly* right for ACLs on mapped drives to work
3982                          */
3983                         len = srvstr_push(dstart, req->flags2,
3984                                           pdata+4, dos_fname,
3985                                           PTR_DIFF(dend, pdata+4),
3986                                           STR_UNICODE);
3987                         DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
3988                         data_size = 4 + len;
3989                         SIVAL(pdata,0,len);
3990                         break;
3991
3992                 case SMB_FILE_ALLOCATION_INFORMATION:
3993                 case SMB_QUERY_FILE_ALLOCATION_INFO:
3994                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
3995                         data_size = 8;
3996                         SOFF_T(pdata,0,allocation_size);
3997                         break;
3998
3999                 case SMB_FILE_END_OF_FILE_INFORMATION:
4000                 case SMB_QUERY_FILE_END_OF_FILEINFO:
4001                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4002                         data_size = 8;
4003                         SOFF_T(pdata,0,file_size);
4004                         break;
4005
4006                 case SMB_QUERY_FILE_ALL_INFO:
4007                 case SMB_FILE_ALL_INFORMATION:
4008                 {
4009                         unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4010                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4011                         put_long_date_timespec(pdata,create_time_ts);
4012                         put_long_date_timespec(pdata+8,atime_ts);
4013                         put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4014                         put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4015                         SIVAL(pdata,32,mode);
4016                         SIVAL(pdata,36,0); /* padding. */
4017                         pdata += 40;
4018                         SOFF_T(pdata,0,allocation_size);
4019                         SOFF_T(pdata,8,file_size);
4020                         SIVAL(pdata,16,nlink);
4021                         SCVAL(pdata,20,delete_pending);
4022                         SCVAL(pdata,21,(mode&aDIR)?1:0);
4023                         SSVAL(pdata,22,0);
4024                         pdata += 24;
4025                         SIVAL(pdata,0,ea_size);
4026                         pdata += 4; /* EA info */
4027                         len = srvstr_push(dstart, req->flags2,
4028                                           pdata+4, dos_fname,
4029                                           PTR_DIFF(dend, pdata+4),
4030                                           STR_UNICODE);
4031                         SIVAL(pdata,0,len);
4032                         pdata += 4 + len;
4033                         data_size = PTR_DIFF(pdata,(*ppdata));
4034                         break;
4035                 }
4036                 case SMB_FILE_INTERNAL_INFORMATION:
4037                         /* This should be an index number - looks like
4038                            dev/ino to me :-) 
4039
4040                            I think this causes us to fail the IFSKIT
4041                            BasicFileInformationTest. -tpot */
4042
4043                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4044                         SIVAL(pdata,0,sbuf.st_ino); /* FileIndexLow */
4045                         SIVAL(pdata,4,sbuf.st_dev); /* FileIndexHigh */
4046                         data_size = 8;
4047                         break;
4048
4049                 case SMB_FILE_ACCESS_INFORMATION:
4050                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4051                         SIVAL(pdata,0,access_mask);
4052                         data_size = 4;
4053                         break;
4054
4055                 case SMB_FILE_NAME_INFORMATION:
4056                         /* Pathname with leading '\'. */
4057                         {
4058                                 size_t byte_len;
4059                                 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4060                                 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4061                                 SIVAL(pdata,0,byte_len);
4062                                 data_size = 4 + byte_len;
4063                                 break;
4064                         }
4065
4066                 case SMB_FILE_DISPOSITION_INFORMATION:
4067                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4068                         data_size = 1;
4069                         SCVAL(pdata,0,delete_pending);
4070                         break;
4071
4072                 case SMB_FILE_POSITION_INFORMATION:
4073                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4074                         data_size = 8;
4075                         SOFF_T(pdata,0,pos);
4076                         break;
4077
4078                 case SMB_FILE_MODE_INFORMATION:
4079                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4080                         SIVAL(pdata,0,mode);
4081                         data_size = 4;
4082                         break;
4083
4084                 case SMB_FILE_ALIGNMENT_INFORMATION:
4085                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4086                         SIVAL(pdata,0,0); /* No alignment needed. */
4087                         data_size = 4;
4088                         break;
4089
4090 #if 0
4091                 /*
4092                  * NT4 server just returns "invalid query" to this - if we try to answer
4093                  * it then NTws gets a BSOD! (tridge).
4094                  * W2K seems to want this. JRA.
4095                  */
4096                 case SMB_QUERY_FILE_STREAM_INFO:
4097 #endif
4098                 case SMB_FILE_STREAM_INFORMATION:
4099                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STREAM_INFORMATION\n"));
4100                         if (mode & aDIR) {
4101                                 data_size = 0;
4102                         } else {
4103                                 size_t byte_len = dos_PutUniCode(pdata+24,"::$DATA", (size_t)0xE, False);
4104                                 SIVAL(pdata,0,0); /* ??? */
4105                                 SIVAL(pdata,4,byte_len); /* Byte length of unicode string ::$DATA */
4106                                 SOFF_T(pdata,8,file_size);
4107                                 SOFF_T(pdata,16,allocation_size);
4108                                 data_size = 24 + byte_len;
4109                         }
4110                         break;
4111
4112                 case SMB_QUERY_COMPRESSION_INFO:
4113                 case SMB_FILE_COMPRESSION_INFORMATION:
4114                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4115                         SOFF_T(pdata,0,file_size);
4116                         SIVAL(pdata,8,0); /* ??? */
4117                         SIVAL(pdata,12,0); /* ??? */
4118                         data_size = 16;
4119                         break;
4120
4121                 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4122                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4123                         put_long_date_timespec(pdata,create_time_ts);
4124                         put_long_date_timespec(pdata+8,atime_ts);
4125                         put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4126                         put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4127                         SOFF_T(pdata,32,allocation_size);
4128                         SOFF_T(pdata,40,file_size);
4129                         SIVAL(pdata,48,mode);
4130                         SIVAL(pdata,52,0); /* ??? */
4131                         data_size = 56;
4132                         break;
4133
4134                 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4135                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4136                         SIVAL(pdata,0,mode);
4137                         SIVAL(pdata,4,0);
4138                         data_size = 8;
4139                         break;
4140
4141                 /*
4142                  * CIFS UNIX Extensions.
4143                  */
4144
4145                 case SMB_QUERY_FILE_UNIX_BASIC:
4146
4147                         pdata = store_file_unix_basic(conn, pdata, fsp, &sbuf);
4148                         data_size = PTR_DIFF(pdata,(*ppdata));
4149
4150                         {
4151                                 int i;
4152                                 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
4153
4154                                 for (i=0; i<100; i++)
4155                                         DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4156                                 DEBUG(4,("\n"));
4157                         }
4158
4159                         break;
4160
4161                 case SMB_QUERY_FILE_UNIX_INFO2:
4162
4163                         pdata = store_file_unix_basic_info2(conn, pdata, fsp, &sbuf);
4164                         data_size = PTR_DIFF(pdata,(*ppdata));
4165
4166                         {
4167                                 int i;
4168                                 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4169
4170                                 for (i=0; i<100; i++)
4171                                         DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4172                                 DEBUG(4,("\n"));
4173                         }
4174
4175                         break;
4176
4177                 case SMB_QUERY_FILE_UNIX_LINK:
4178                         {
4179                                 pstring buffer;
4180
4181                                 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4182 #ifdef S_ISLNK
4183                                 if(!S_ISLNK(sbuf.st_mode)) {
4184                                         reply_unixerror(req, ERRSRV,
4185                                                         ERRbadlink);
4186                                         return;
4187                                 }
4188 #else
4189                                 reply_unixerror(req, ERRDOS, ERRbadlink);
4190                                 return;
4191 #endif
4192                                 len = SMB_VFS_READLINK(conn,fullpathname, buffer, sizeof(pstring)-1);     /* read link */
4193                                 if (len == -1) {
4194                                         reply_unixerror(req, ERRDOS,
4195                                                         ERRnoaccess);
4196                                         return;
4197                                 }
4198                                 buffer[len] = 0;
4199                                 len = srvstr_push(dstart, req->flags2,
4200                                                   pdata, buffer,
4201                                                   PTR_DIFF(dend, pdata),
4202                                                   STR_TERMINATE);
4203                                 pdata += len;
4204                                 data_size = PTR_DIFF(pdata,(*ppdata));
4205
4206                                 break;
4207                         }
4208
4209 #if defined(HAVE_POSIX_ACLS)
4210                 case SMB_QUERY_POSIX_ACL:
4211                         {
4212                                 SMB_ACL_T file_acl = NULL;
4213                                 SMB_ACL_T def_acl = NULL;
4214                                 uint16 num_file_acls = 0;
4215                                 uint16 num_def_acls = 0;
4216
4217                                 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
4218                                         file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp, fsp->fh->fd);
4219                                 } else {
4220                                         file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
4221                                 }
4222
4223                                 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4224                                         DEBUG(5,("call_trans2qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
4225                                                 fname ));
4226                                         reply_nterror(
4227                                                 req,
4228                                                 NT_STATUS_NOT_IMPLEMENTED);
4229                                         return;
4230                                 }
4231
4232                                 if (S_ISDIR(sbuf.st_mode)) {
4233                                         if (fsp && fsp->is_directory) {
4234                                                 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT);
4235                                         } else {
4236                                                 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT);
4237                                         }
4238                                         def_acl = free_empty_sys_acl(conn, def_acl);
4239                                 }
4240
4241                                 num_file_acls = count_acl_entries(conn, file_acl);
4242                                 num_def_acls = count_acl_entries(conn, def_acl);
4243
4244                                 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4245                                         DEBUG(5,("call_trans2qfilepathinfo: data_size too small (%u) need %u\n",
4246                                                 data_size,
4247                                                 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4248                                                         SMB_POSIX_ACL_HEADER_SIZE) ));
4249                                         if (file_acl) {
4250                                                 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4251                                         }
4252                                         if (def_acl) {
4253                                                 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4254                                         }
4255                                         reply_nterror(
4256                                                 req,
4257                                                 NT_STATUS_BUFFER_TOO_SMALL);
4258                                         return;
4259                                 }
4260
4261                                 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4262                                 SSVAL(pdata,2,num_file_acls);
4263                                 SSVAL(pdata,4,num_def_acls);
4264                                 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
4265                                         if (file_acl) {
4266                                                 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4267                                         }
4268                                         if (def_acl) {
4269                                                 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4270                                         }
4271                                         reply_nterror(
4272                                                 req, NT_STATUS_INTERNAL_ERROR);
4273                                         return;
4274                                 }
4275                                 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
4276                                         if (file_acl) {
4277                                                 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4278                                         }
4279                                         if (def_acl) {
4280                                                 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4281                                         }
4282                                         reply_nterror(
4283                                                 req,
4284                                                 NT_STATUS_INTERNAL_ERROR);
4285                                         return;
4286                                 }
4287
4288                                 if (file_acl) {
4289                                         SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4290                                 }
4291                                 if (def_acl) {
4292                                         SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4293                                 }
4294                                 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
4295                                 break;
4296                         }
4297 #endif
4298
4299
4300                 case SMB_QUERY_POSIX_LOCK:
4301                 {
4302                         NTSTATUS status = NT_STATUS_INVALID_LEVEL;
4303                         SMB_BIG_UINT count;
4304                         SMB_BIG_UINT offset;
4305                         uint32 lock_pid;
4306                         enum brl_type lock_type;
4307
4308                         if (total_data != POSIX_LOCK_DATA_SIZE) {
4309                                 reply_nterror(
4310                                         req, NT_STATUS_INVALID_PARAMETER);
4311                                 return;
4312                         }
4313
4314                         switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4315                                 case POSIX_LOCK_TYPE_READ:
4316                                         lock_type = READ_LOCK;
4317                                         break;
4318                                 case POSIX_LOCK_TYPE_WRITE:
4319                                         lock_type = WRITE_LOCK;
4320                                         break;
4321                                 case POSIX_LOCK_TYPE_UNLOCK:
4322                                 default:
4323                                         /* There's no point in asking for an unlock... */
4324                                         talloc_destroy(data_ctx);
4325                                         reply_nterror(
4326                                                 req,
4327                                                 NT_STATUS_INVALID_PARAMETER);
4328                                         return;
4329                         }
4330
4331                         lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4332 #if defined(HAVE_LONGLONG)
4333                         offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4334                                         ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4335                         count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4336                                         ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4337 #else /* HAVE_LONGLONG */
4338                         offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4339                         count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4340 #endif /* HAVE_LONGLONG */
4341
4342                         status = query_lock(fsp,
4343                                         &lock_pid,
4344                                         &count,
4345                                         &offset,
4346                                         &lock_type,
4347                                         POSIX_LOCK);
4348
4349                         if (ERROR_WAS_LOCK_DENIED(status)) {
4350                                 /* Here we need to report who has it locked... */
4351                                 data_size = POSIX_LOCK_DATA_SIZE;
4352
4353                                 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
4354                                 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
4355                                 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, lock_pid);
4356 #if defined(HAVE_LONGLONG)
4357                                 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
4358                                 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
4359                                 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
4360                                 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
4361 #else /* HAVE_LONGLONG */
4362                                 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
4363                                 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
4364 #endif /* HAVE_LONGLONG */
4365
4366                         } else if (NT_STATUS_IS_OK(status)) {
4367                                 /* For success we just return a copy of what we sent
4368                                    with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4369                                 data_size = POSIX_LOCK_DATA_SIZE;
4370                                 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
4371                                 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
4372                         } else {
4373                                 reply_nterror(req, status);
4374                                 return;
4375                         }
4376                         break;
4377                 }
4378
4379                 default:
4380                         reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4381                         return;
4382         }
4383
4384         send_trans2_replies_new(req, params, param_size, *ppdata, data_size,
4385                                 max_data_bytes);
4386
4387         return;
4388 }
4389
4390 /****************************************************************************
4391  Set a hard link (called by UNIX extensions and by NT rename with HARD link
4392  code.
4393 ****************************************************************************/
4394
4395 NTSTATUS hardlink_internals(connection_struct *conn, pstring oldname, pstring newname)
4396 {
4397         SMB_STRUCT_STAT sbuf1, sbuf2;
4398         pstring last_component_oldname;
4399         pstring last_component_newname;
4400         NTSTATUS status = NT_STATUS_OK;
4401
4402         ZERO_STRUCT(sbuf1);
4403         ZERO_STRUCT(sbuf2);
4404
4405         status = unix_convert(conn, oldname, False, last_component_oldname, &sbuf1);
4406         if (!NT_STATUS_IS_OK(status)) {
4407                 return status;
4408         }
4409
4410         status = check_name(conn, oldname);
4411         if (!NT_STATUS_IS_OK(status)) {
4412                 return status;
4413         }
4414
4415         /* source must already exist. */
4416         if (!VALID_STAT(sbuf1)) {
4417                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4418         }
4419
4420         status = unix_convert(conn, newname, False, last_component_newname, &sbuf2);
4421         if (!NT_STATUS_IS_OK(status)) {
4422                 return status;
4423         }
4424
4425         status = check_name(conn, newname);
4426         if (!NT_STATUS_IS_OK(status)) {
4427                 return status;
4428         }
4429
4430         /* Disallow if newname already exists. */
4431         if (VALID_STAT(sbuf2)) {
4432                 return NT_STATUS_OBJECT_NAME_COLLISION;
4433         }
4434
4435         /* No links from a directory. */
4436         if (S_ISDIR(sbuf1.st_mode)) {
4437                 return NT_STATUS_FILE_IS_A_DIRECTORY;
4438         }
4439
4440         /* Ensure this is within the share. */
4441         status = check_reduced_name(conn, oldname);
4442         if (!NT_STATUS_IS_OK(status)) {
4443                 return status;
4444         }
4445
4446         DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
4447
4448         if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
4449                 status = map_nt_error_from_unix(errno);
4450                 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
4451                                 nt_errstr(status), newname, oldname));
4452         }
4453
4454         return status;
4455 }
4456
4457 /****************************************************************************
4458  Deal with setting the time from any of the setfilepathinfo functions.
4459 ****************************************************************************/
4460
4461 static NTSTATUS smb_set_file_time(connection_struct *conn,
4462                                 files_struct *fsp,
4463                                 const char *fname,
4464                                 const SMB_STRUCT_STAT *psbuf,
4465                                 struct timespec ts[2])
4466 {
4467         uint32 action =
4468                 FILE_NOTIFY_CHANGE_LAST_ACCESS
4469                 |FILE_NOTIFY_CHANGE_LAST_WRITE;
4470
4471         
4472         if (!VALID_STAT(*psbuf)) {
4473                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4474         }
4475
4476         /* get some defaults (no modifications) if any info is zero or -1. */
4477         if (null_timespec(ts[0])) {
4478                 ts[0] = get_atimespec(psbuf);
4479                 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
4480         }
4481
4482         if (null_timespec(ts[1])) {
4483                 ts[1] = get_mtimespec(psbuf);
4484                 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4485         }
4486
4487         DEBUG(6,("smb_set_file_time: actime: %s " , time_to_asc(convert_timespec_to_time_t(ts[0])) ));
4488         DEBUG(6,("smb_set_file_time: modtime: %s ", time_to_asc(convert_timespec_to_time_t(ts[1])) ));
4489
4490         /*
4491          * Try and set the times of this file if
4492          * they are different from the current values.
4493          */
4494
4495         {
4496                 struct timespec mts = get_mtimespec(psbuf);
4497                 struct timespec ats = get_atimespec(psbuf);
4498                 if ((timespec_compare(&ts[0], &ats) == 0) && (timespec_compare(&ts[1], &mts) == 0)) {
4499                         return NT_STATUS_OK;
4500                 }
4501         }
4502
4503         if(fsp != NULL) {
4504                 /*
4505                  * This was a setfileinfo on an open file.
4506                  * NT does this a lot. We also need to 
4507                  * set the time here, as it can be read by 
4508                  * FindFirst/FindNext and with the patch for bug #2045
4509                  * in smbd/fileio.c it ensures that this timestamp is
4510                  * kept sticky even after a write. We save the request
4511                  * away and will set it on file close and after a write. JRA.
4512                  */
4513
4514                 if (!null_timespec(ts[1])) {
4515                         DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
4516                                 time_to_asc(convert_timespec_to_time_t(ts[1])) ));
4517                         fsp_set_pending_modtime(fsp, ts[1]);
4518                 }
4519
4520         }
4521         DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
4522
4523         if(file_ntimes(conn, fname, ts)!=0) {
4524                 return map_nt_error_from_unix(errno);
4525         }
4526         if (action != 0) {
4527                 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action, fname);
4528         }
4529         return NT_STATUS_OK;
4530 }
4531
4532 /****************************************************************************
4533  Deal with setting the dosmode from any of the setfilepathinfo functions.
4534 ****************************************************************************/
4535
4536 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
4537                                 const char *fname,
4538                                 SMB_STRUCT_STAT *psbuf,
4539                                 uint32 dosmode)
4540 {
4541         if (!VALID_STAT(*psbuf)) {
4542                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4543         }
4544
4545         if (dosmode) {
4546                 if (S_ISDIR(psbuf->st_mode)) {
4547                         dosmode |= aDIR;
4548                 } else {
4549                         dosmode &= ~aDIR;
4550                 }
4551         }
4552
4553         DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
4554
4555         /* check the mode isn't different, before changing it */
4556         if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, psbuf))) {
4557
4558                 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode 0x%x\n",
4559                                         fname, (unsigned int)dosmode ));
4560
4561                 if(file_set_dosmode(conn, fname, dosmode, psbuf, False)) {
4562                         DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of %s failed (%s)\n",
4563                                                 fname, strerror(errno)));
4564                         return map_nt_error_from_unix(errno);
4565                 }
4566         }
4567         return NT_STATUS_OK;
4568 }
4569
4570 /****************************************************************************
4571  Deal with setting the size from any of the setfilepathinfo functions.
4572 ****************************************************************************/
4573
4574 static NTSTATUS smb_set_file_size(connection_struct *conn,
4575                                   struct smb_request *req,
4576                                 files_struct *fsp,
4577                                 const char *fname,
4578                                 SMB_STRUCT_STAT *psbuf,
4579                                 SMB_OFF_T size)
4580 {
4581         NTSTATUS status = NT_STATUS_OK;
4582         files_struct *new_fsp = NULL;
4583
4584         if (!VALID_STAT(*psbuf)) {
4585                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4586         }
4587
4588         DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
4589
4590         if (size == get_file_size(*psbuf)) {
4591                 return NT_STATUS_OK;
4592         }
4593
4594         DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
4595                 fname, (double)size ));
4596
4597         if (fsp && fsp->fh->fd != -1) {
4598                 /* Handle based call. */
4599                 if (vfs_set_filelen(fsp, size) == -1) {
4600                         return map_nt_error_from_unix(errno);
4601                 }
4602                 return NT_STATUS_OK;
4603         }
4604
4605         status = open_file_ntcreate(conn, req, fname, psbuf,
4606                                 FILE_WRITE_DATA,
4607                                 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4608                                 FILE_OPEN,
4609                                 0,
4610                                 FILE_ATTRIBUTE_NORMAL,
4611                                 FORCE_OPLOCK_BREAK_TO_NONE,
4612                                 NULL, &new_fsp);
4613         
4614         if (!NT_STATUS_IS_OK(status)) {
4615                 /* NB. We check for open_was_deferred in the caller. */
4616                 return status;
4617         }
4618
4619         if (vfs_set_filelen(new_fsp, size) == -1) {
4620                 status = map_nt_error_from_unix(errno);
4621                 close_file(new_fsp,NORMAL_CLOSE);
4622                 return status;
4623         }
4624
4625         close_file(new_fsp,NORMAL_CLOSE);
4626         return NT_STATUS_OK;
4627 }
4628
4629 /****************************************************************************
4630  Deal with SMB_INFO_SET_EA.
4631 ****************************************************************************/
4632
4633 static NTSTATUS smb_info_set_ea(connection_struct *conn,
4634                                 const char *pdata,
4635                                 int total_data,
4636                                 files_struct *fsp,
4637                                 const char *fname)
4638 {
4639         struct ea_list *ea_list = NULL;
4640         TALLOC_CTX *ctx = NULL;
4641         NTSTATUS status = NT_STATUS_OK;
4642
4643         if (total_data < 10) {
4644
4645                 /* OS/2 workplace shell seems to send SET_EA requests of "null"
4646                    length. They seem to have no effect. Bug #3212. JRA */
4647
4648                 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
4649                         /* We're done. We only get EA info in this call. */
4650                         return NT_STATUS_OK;
4651                 }
4652
4653                 return NT_STATUS_INVALID_PARAMETER;
4654         }
4655
4656         if (IVAL(pdata,0) > total_data) {
4657                 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
4658                         IVAL(pdata,0), (unsigned int)total_data));
4659                 return NT_STATUS_INVALID_PARAMETER;
4660         }
4661
4662         ctx = talloc_init("SMB_INFO_SET_EA");
4663         if (!ctx) {
4664                 return NT_STATUS_NO_MEMORY;
4665         }
4666         ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
4667         if (!ea_list) {
4668                 talloc_destroy(ctx);
4669                 return NT_STATUS_INVALID_PARAMETER;
4670         }
4671         status = set_ea(conn, fsp, fname, ea_list);
4672         talloc_destroy(ctx);
4673
4674         return status;
4675 }
4676
4677 /****************************************************************************
4678  Deal with SMB_SET_FILE_DISPOSITION_INFO.
4679 ****************************************************************************/
4680
4681 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
4682                                 const char *pdata,
4683                                 int total_data,
4684                                 files_struct *fsp,
4685                                 const char *fname,
4686                                 SMB_STRUCT_STAT *psbuf)
4687 {
4688         NTSTATUS status = NT_STATUS_OK;
4689         BOOL delete_on_close;
4690         uint32 dosmode = 0;
4691
4692         if (total_data < 1) {
4693                 return NT_STATUS_INVALID_PARAMETER;
4694         }
4695
4696         if (fsp == NULL) {
4697                 return NT_STATUS_INVALID_HANDLE;
4698         }
4699
4700         delete_on_close = (CVAL(pdata,0) ? True : False);
4701         dosmode = dos_mode(conn, fname, psbuf);
4702
4703         DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
4704                 "delete_on_close = %u\n",
4705                 fsp->fsp_name,
4706                 (unsigned int)dosmode,
4707                 (unsigned int)delete_on_close ));
4708
4709         status = can_set_delete_on_close(fsp, delete_on_close, dosmode);
4710  
4711         if (!NT_STATUS_IS_OK(status)) {
4712                 return status;
4713         }
4714
4715         /* The set is across all open files on this dev/inode pair. */
4716         if (!set_delete_on_close(fsp, delete_on_close, &current_user.ut)) {
4717                 return NT_STATUS_ACCESS_DENIED;
4718         }
4719         return NT_STATUS_OK;
4720 }
4721
4722 /****************************************************************************
4723  Deal with SMB_FILE_POSITION_INFORMATION.
4724 ****************************************************************************/
4725
4726 static NTSTATUS smb_file_position_information(connection_struct *conn,
4727                                 const char *pdata,
4728                                 int total_data,
4729                                 files_struct *fsp)
4730 {
4731         SMB_BIG_UINT position_information;
4732
4733         if (total_data < 8) {
4734                 return NT_STATUS_INVALID_PARAMETER;
4735         }
4736
4737         if (fsp == NULL) {
4738                 /* Ignore on pathname based set. */
4739                 return NT_STATUS_OK;
4740         }
4741
4742         position_information = (SMB_BIG_UINT)IVAL(pdata,0);
4743 #ifdef LARGE_SMB_OFF_T
4744         position_information |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
4745 #else /* LARGE_SMB_OFF_T */
4746         if (IVAL(pdata,4) != 0) {
4747                 /* more than 32 bits? */
4748                 return NT_STATUS_INVALID_PARAMETER;
4749         }
4750 #endif /* LARGE_SMB_OFF_T */
4751
4752         DEBUG(10,("smb_file_position_information: Set file position information for file %s to %.0f\n",
4753                 fsp->fsp_name, (double)position_information ));
4754         fsp->fh->position_information = position_information;
4755         return NT_STATUS_OK;
4756 }
4757
4758 /****************************************************************************
4759  Deal with SMB_FILE_MODE_INFORMATION.
4760 ****************************************************************************/
4761
4762 static NTSTATUS smb_file_mode_information(connection_struct *conn,
4763                                 const char *pdata,
4764                                 int total_data)
4765 {
4766         uint32 mode;
4767
4768         if (total_data < 4) {
4769                 return NT_STATUS_INVALID_PARAMETER;
4770         }
4771         mode = IVAL(pdata,0);
4772         if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
4773                 return NT_STATUS_INVALID_PARAMETER;
4774         }
4775         return NT_STATUS_OK;
4776 }
4777
4778 /****************************************************************************
4779  Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
4780 ****************************************************************************/
4781
4782 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
4783                                        struct smb_request *req,
4784                                        const char *pdata,
4785                                        int total_data,
4786                                        const char *fname)
4787 {
4788         pstring link_target;
4789         const char *newname = fname;
4790         NTSTATUS status = NT_STATUS_OK;
4791
4792         /* Set a symbolic link. */
4793         /* Don't allow this if follow links is false. */
4794
4795         if (total_data == 0) {
4796                 return NT_STATUS_INVALID_PARAMETER;
4797         }
4798
4799         if (!lp_symlinks(SNUM(conn))) {
4800                 return NT_STATUS_ACCESS_DENIED;
4801         }
4802
4803         srvstr_pull(pdata, req->flags2, link_target, pdata,
4804                     sizeof(link_target), total_data, STR_TERMINATE);
4805
4806         /* !widelinks forces the target path to be within the share. */
4807         /* This means we can interpret the target as a pathname. */
4808         if (!lp_widelinks(SNUM(conn))) {
4809                 pstring rel_name;
4810                 char *last_dirp = NULL;
4811
4812                 if (*link_target == '/') {
4813                         /* No absolute paths allowed. */
4814                         return NT_STATUS_ACCESS_DENIED;
4815                 }
4816                 pstrcpy(rel_name, newname);
4817                 last_dirp = strrchr_m(rel_name, '/');
4818                 if (last_dirp) {
4819                         last_dirp[1] = '\0';
4820                 } else {
4821                         pstrcpy(rel_name, "./");
4822                 }
4823                 pstrcat(rel_name, link_target);
4824
4825                 status = check_name(conn, rel_name);
4826                 if (!NT_STATUS_IS_OK(status)) {
4827                         return status;
4828                 }
4829         }
4830
4831         DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
4832                         newname, link_target ));
4833
4834         if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
4835                 return map_nt_error_from_unix(errno);
4836         }
4837
4838         return NT_STATUS_OK;
4839 }
4840
4841 /****************************************************************************
4842  Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
4843 ****************************************************************************/
4844
4845 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
4846                                         struct smb_request *req,
4847                                         const char *pdata, int total_data,
4848                                         pstring fname)
4849 {
4850         pstring oldname;
4851         NTSTATUS status = NT_STATUS_OK;
4852
4853         /* Set a hard link. */
4854         if (total_data == 0) {
4855                 return NT_STATUS_INVALID_PARAMETER;
4856         }
4857
4858         srvstr_get_path(pdata, req->flags2, oldname, pdata,
4859                         sizeof(oldname), total_data, STR_TERMINATE, &status);
4860         if (!NT_STATUS_IS_OK(status)) {
4861                 return status;
4862         }
4863
4864         status = resolve_dfspath(conn, req->flags2 & FLAGS2_DFS_PATHNAMES,
4865                                  oldname);
4866         if (!NT_STATUS_IS_OK(status)) {
4867                 return status;
4868         }
4869
4870         DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
4871                 fname, oldname));
4872
4873         return hardlink_internals(conn, oldname, fname);
4874 }
4875
4876 /****************************************************************************
4877  Deal with SMB_FILE_RENAME_INFORMATION.
4878 ****************************************************************************/
4879
4880 static NTSTATUS smb_file_rename_information(connection_struct *conn,
4881                                             struct smb_request *req,
4882                                             const char *pdata, int total_data,
4883                                             files_struct *fsp, pstring fname)
4884 {
4885         BOOL overwrite;
4886         uint32 root_fid;
4887         uint32 len;
4888         pstring newname;
4889         pstring base_name;
4890         BOOL dest_has_wcard = False;
4891         NTSTATUS status = NT_STATUS_OK;
4892         char *p;
4893
4894         if (total_data < 13) {
4895                 return NT_STATUS_INVALID_PARAMETER;
4896         }
4897
4898         overwrite = (CVAL(pdata,0) ? True : False);
4899         root_fid = IVAL(pdata,4);
4900         len = IVAL(pdata,8);
4901
4902         if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
4903                 return NT_STATUS_INVALID_PARAMETER;
4904         }
4905
4906         srvstr_get_path_wcard(pdata, req->flags2, newname, &pdata[12],
4907                               sizeof(newname), len, 0, &status,
4908                               &dest_has_wcard);
4909         if (!NT_STATUS_IS_OK(status)) {
4910                 return status;
4911         }
4912
4913         status = resolve_dfspath_wcard(conn,
4914                                        req->flags2 & FLAGS2_DFS_PATHNAMES,
4915                                        newname, &dest_has_wcard);
4916         if (!NT_STATUS_IS_OK(status)) {
4917                 return status;
4918         }
4919
4920         /* Check the new name has no '/' characters. */
4921         if (strchr_m(newname, '/')) {
4922                 return NT_STATUS_NOT_SUPPORTED;
4923         }
4924
4925         /* Create the base directory. */
4926         pstrcpy(base_name, fname);
4927         p = strrchr_m(base_name, '/');
4928         if (p) {
4929                 p[1] = '\0';
4930         } else {
4931                 pstrcpy(base_name, "./");
4932         }
4933         /* Append the new name. */
4934         pstrcat(base_name, newname);
4935
4936         if (fsp) {
4937                 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
4938                         fsp->fnum, fsp->fsp_name, base_name ));
4939                 status = rename_internals_fsp(conn, fsp, base_name, 0, overwrite);
4940         } else {
4941                 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
4942                         fname, newname ));
4943                 status = rename_internals(conn, req, fname, base_name, 0,
4944                                           overwrite, False, dest_has_wcard);
4945         }
4946
4947         return status;
4948 }
4949
4950 /****************************************************************************
4951  Deal with SMB_SET_POSIX_ACL.
4952 ****************************************************************************/
4953
4954 #if defined(HAVE_POSIX_ACLS)
4955 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
4956                                 const char *pdata,
4957                                 int total_data,
4958                                 files_struct *fsp,
4959                                 const char *fname,
4960                                 SMB_STRUCT_STAT *psbuf)
4961 {
4962         uint16 posix_acl_version;
4963         uint16 num_file_acls;
4964         uint16 num_def_acls;
4965         BOOL valid_file_acls = True;
4966         BOOL valid_def_acls = True;
4967
4968         if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
4969                 return NT_STATUS_INVALID_PARAMETER;
4970         }
4971         posix_acl_version = SVAL(pdata,0);
4972         num_file_acls = SVAL(pdata,2);
4973         num_def_acls = SVAL(pdata,4);
4974
4975         if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
4976                 valid_file_acls = False;
4977                 num_file_acls = 0;
4978         }
4979
4980         if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
4981                 valid_def_acls = False;
4982                 num_def_acls = 0;
4983         }
4984
4985         if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
4986                 return NT_STATUS_INVALID_PARAMETER;
4987         }
4988
4989         if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
4990                         (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
4991                 return NT_STATUS_INVALID_PARAMETER;
4992         }
4993
4994         DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
4995                 fname ? fname : fsp->fsp_name,
4996                 (unsigned int)num_file_acls,
4997                 (unsigned int)num_def_acls));
4998
4999         if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
5000                         pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
5001                 return map_nt_error_from_unix(errno);
5002         }
5003
5004         if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, psbuf, num_def_acls,
5005                         pdata + SMB_POSIX_ACL_HEADER_SIZE +
5006                         (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
5007                 return map_nt_error_from_unix(errno);
5008         }
5009         return NT_STATUS_OK;
5010 }
5011 #endif
5012
5013 /****************************************************************************
5014  Deal with SMB_SET_POSIX_LOCK.
5015 ****************************************************************************/
5016
5017 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
5018                                 const uint8 *inbuf,
5019                                 int length,
5020                                 const char *pdata,
5021                                 int total_data,
5022                                 files_struct *fsp)
5023 {
5024         SMB_BIG_UINT count;
5025         SMB_BIG_UINT offset;
5026         uint32 lock_pid;
5027         BOOL blocking_lock = False;
5028         enum brl_type lock_type;
5029         NTSTATUS status = NT_STATUS_OK;
5030
5031         if (fsp == NULL || fsp->fh->fd == -1) {
5032                 return NT_STATUS_INVALID_HANDLE;
5033         }
5034
5035         if (total_data != POSIX_LOCK_DATA_SIZE) {
5036                 return NT_STATUS_INVALID_PARAMETER;
5037         }
5038
5039         switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5040                 case POSIX_LOCK_TYPE_READ:
5041                         lock_type = READ_LOCK;
5042                         break;
5043                 case POSIX_LOCK_TYPE_WRITE:
5044                         /* Return the right POSIX-mappable error code for files opened read-only. */
5045                         if (!fsp->can_write) {
5046                                 return NT_STATUS_INVALID_HANDLE;
5047                         }
5048                         lock_type = WRITE_LOCK;
5049                         break;
5050                 case POSIX_LOCK_TYPE_UNLOCK:
5051                         lock_type = UNLOCK_LOCK;
5052                         break;
5053                 default:
5054                         return NT_STATUS_INVALID_PARAMETER;
5055         }
5056
5057         if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
5058                 blocking_lock = False;
5059         } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
5060                 blocking_lock = True;
5061         } else {
5062                 return NT_STATUS_INVALID_PARAMETER;
5063         }
5064
5065         if (!lp_blocking_locks(SNUM(conn))) { 
5066                 blocking_lock = False;
5067         }
5068
5069         lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5070 #if defined(HAVE_LONGLONG)
5071         offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
5072                         ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
5073         count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
5074                         ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
5075 #else /* HAVE_LONGLONG */
5076         offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
5077         count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5078 #endif /* HAVE_LONGLONG */
5079
5080         DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
5081                         "lock_pid = %u, count = %.0f, offset = %.0f\n",
5082                 fsp->fsp_name,
5083                 (unsigned int)lock_type,
5084                 (unsigned int)lock_pid,
5085                 (double)count,
5086                 (double)offset ));
5087
5088         if (lock_type == UNLOCK_LOCK) {
5089                 status = do_unlock(smbd_messaging_context(),
5090                                 fsp,
5091                                 lock_pid,
5092                                 count,
5093                                 offset,
5094                                 POSIX_LOCK);
5095         } else {
5096                 uint32 block_smbpid;
5097
5098                 struct byte_range_lock *br_lck = do_lock(smbd_messaging_context(),
5099                                                         fsp,
5100                                                         lock_pid,
5101                                                         count,
5102                                                         offset,
5103                                                         lock_type,
5104                                                         POSIX_LOCK,
5105                                                         blocking_lock,
5106                                                         &status,
5107                                                         &block_smbpid);
5108
5109                 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
5110                         /*
5111                          * A blocking lock was requested. Package up
5112                          * this smb into a queued request and push it
5113                          * onto the blocking lock queue.
5114                          */
5115                         if(push_blocking_lock_request(br_lck,
5116                                                 (char *)inbuf, length,
5117                                                 fsp,
5118                                                 -1, /* infinite timeout. */
5119                                                 0,
5120                                                 lock_pid,
5121                                                 lock_type,
5122                                                 POSIX_LOCK,
5123                                                 offset,
5124                                                 count,
5125                                                 block_smbpid)) {
5126                                 TALLOC_FREE(br_lck);
5127                                 return status;
5128                         }
5129                 }
5130                 TALLOC_FREE(br_lck);
5131         }
5132
5133         return status;
5134 }
5135
5136 /****************************************************************************
5137  Deal with SMB_INFO_STANDARD.
5138 ****************************************************************************/
5139
5140 static NTSTATUS smb_set_info_standard(connection_struct *conn,
5141                                         const char *pdata,
5142                                         int total_data,
5143                                         files_struct *fsp,
5144                                         const char *fname,
5145                                         const SMB_STRUCT_STAT *psbuf)
5146 {
5147         struct timespec ts[2];
5148
5149         if (total_data < 12) {
5150                 return NT_STATUS_INVALID_PARAMETER;
5151         }
5152
5153         /* access time */
5154         ts[0] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastAccess));
5155         /* write time */
5156         ts[1] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastWrite));
5157
5158         DEBUG(10,("smb_set_info_standard: file %s\n",
5159                 fname ? fname : fsp->fsp_name ));
5160
5161         return smb_set_file_time(conn,
5162                                 fsp,
5163                                 fname,
5164                                 psbuf,
5165                                 ts);
5166 }
5167
5168 /****************************************************************************
5169  Deal with SMB_SET_FILE_BASIC_INFO.
5170 ****************************************************************************/
5171
5172 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
5173                                         const char *pdata,
5174                                         int total_data,
5175                                         files_struct *fsp,
5176                                         const char *fname,
5177                                         SMB_STRUCT_STAT *psbuf)
5178 {
5179         /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
5180         struct timespec write_time;
5181         struct timespec changed_time;
5182         uint32 dosmode = 0;
5183         struct timespec ts[2];
5184         NTSTATUS status = NT_STATUS_OK;
5185
5186         if (total_data < 36) {
5187                 return NT_STATUS_INVALID_PARAMETER;
5188         }
5189
5190         /* Set the attributes */
5191         dosmode = IVAL(pdata,32);
5192         status = smb_set_file_dosmode(conn,
5193                                         fname,
5194                                         psbuf,
5195                                         dosmode);
5196         if (!NT_STATUS_IS_OK(status)) {
5197                 return status;
5198         }
5199
5200         /* Ignore create time at offset pdata. */
5201
5202         /* access time */
5203         ts[0] = interpret_long_date(pdata+8);
5204
5205         write_time = interpret_long_date(pdata+16);
5206         changed_time = interpret_long_date(pdata+24);
5207
5208         /* mtime */
5209         ts[1] = timespec_min(&write_time, &changed_time);
5210
5211         if ((timespec_compare(&write_time, &ts[1]) == 1) && !null_timespec(write_time)) {
5212                 ts[1] = write_time;
5213         }
5214
5215         /* Prefer a defined time to an undefined one. */
5216         if (null_timespec(ts[1])) {
5217                 ts[1] = null_timespec(write_time) ? changed_time : write_time;
5218         }
5219
5220         DEBUG(10,("smb_set_file_basic_info: file %s\n",
5221                 fname ? fname : fsp->fsp_name ));
5222
5223         return smb_set_file_time(conn,
5224                                 fsp,
5225                                 fname,
5226                                 psbuf,
5227                                 ts);
5228 }
5229
5230 /****************************************************************************
5231  Deal with SMB_SET_FILE_ALLOCATION_INFO.
5232 ****************************************************************************/
5233
5234 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
5235                                              struct smb_request *req,
5236                                         const char *pdata,
5237                                         int total_data,
5238                                         files_struct *fsp,
5239                                         const char *fname,
5240                                         SMB_STRUCT_STAT *psbuf)
5241 {
5242         SMB_BIG_UINT allocation_size = 0;
5243         NTSTATUS status = NT_STATUS_OK;
5244         files_struct *new_fsp = NULL;
5245
5246         if (!VALID_STAT(*psbuf)) {
5247                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5248         }
5249
5250         if (total_data < 8) {
5251                 return NT_STATUS_INVALID_PARAMETER;
5252         }
5253
5254         allocation_size = (SMB_BIG_UINT)IVAL(pdata,0);
5255 #ifdef LARGE_SMB_OFF_T
5256         allocation_size |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
5257 #else /* LARGE_SMB_OFF_T */
5258         if (IVAL(pdata,4) != 0) {
5259                 /* more than 32 bits? */
5260                 return NT_STATUS_INVALID_PARAMETER;
5261         }
5262 #endif /* LARGE_SMB_OFF_T */
5263
5264         DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for file %s to %.0f\n",
5265                         fname, (double)allocation_size ));
5266
5267         if (allocation_size) {
5268                 allocation_size = smb_roundup(conn, allocation_size);
5269         }
5270
5271         DEBUG(10,("smb_set_file_allocation_info: file %s : setting new allocation size to %.0f\n",
5272                         fname, (double)allocation_size ));
5273
5274         if (fsp && fsp->fh->fd != -1) {
5275                 /* Open file handle. */
5276                 /* Only change if needed. */
5277                 if (allocation_size != get_file_size(*psbuf)) {
5278                         if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
5279                                 return map_nt_error_from_unix(errno);
5280                         }
5281                 }
5282                 /* But always update the time. */
5283                 if (null_timespec(fsp->pending_modtime)) {
5284                         /*
5285                          * This is equivalent to a write. Ensure it's seen immediately
5286                          * if there are no pending writes.
5287                          */
5288                         set_filetime(fsp->conn, fsp->fsp_name, timespec_current());
5289                 }
5290                 return NT_STATUS_OK;
5291         }
5292
5293         /* Pathname or stat or directory file. */
5294
5295         status = open_file_ntcreate(conn, req, fname, psbuf,
5296                                 FILE_WRITE_DATA,
5297                                 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5298                                 FILE_OPEN,
5299                                 0,
5300                                 FILE_ATTRIBUTE_NORMAL,
5301                                 FORCE_OPLOCK_BREAK_TO_NONE,
5302                                 NULL, &new_fsp);
5303
5304         if (!NT_STATUS_IS_OK(status)) {
5305                 /* NB. We check for open_was_deferred in the caller. */
5306                 return status;
5307         }
5308
5309         /* Only change if needed. */
5310         if (allocation_size != get_file_size(*psbuf)) {
5311                 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
5312                         status = map_nt_error_from_unix(errno);
5313                         close_file(new_fsp,NORMAL_CLOSE);
5314                         return status;
5315                 }
5316         }
5317
5318         /* Changing the allocation size should set the last mod time. */
5319         /* Don't need to call set_filetime as this will be flushed on
5320          * close. */
5321
5322         fsp_set_pending_modtime(new_fsp, timespec_current());
5323
5324         close_file(new_fsp,NORMAL_CLOSE);
5325         return NT_STATUS_OK;
5326 }
5327
5328 /****************************************************************************
5329  Deal with SMB_SET_FILE_END_OF_FILE_INFO.
5330 ****************************************************************************/
5331
5332 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
5333                                               struct smb_request *req,
5334                                         const char *pdata,
5335                                         int total_data,
5336                                         files_struct *fsp,
5337                                         const char *fname,
5338                                         SMB_STRUCT_STAT *psbuf)
5339 {
5340         SMB_OFF_T size;
5341
5342         if (total_data < 8) {
5343                 return NT_STATUS_INVALID_PARAMETER;
5344         }
5345
5346         size = IVAL(pdata,0);
5347 #ifdef LARGE_SMB_OFF_T
5348         size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5349 #else /* LARGE_SMB_OFF_T */
5350         if (IVAL(pdata,4) != 0) {
5351                 /* more than 32 bits? */
5352                 return NT_STATUS_INVALID_PARAMETER;
5353         }
5354 #endif /* LARGE_SMB_OFF_T */
5355         DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
5356                 "file %s to %.0f\n", fname, (double)size ));
5357
5358         return smb_set_file_size(conn, req,
5359                                 fsp,
5360                                 fname,
5361                                 psbuf,
5362                                 size);
5363 }
5364
5365 /****************************************************************************
5366  Allow a UNIX info mknod.
5367 ****************************************************************************/
5368
5369 static NTSTATUS smb_unix_mknod(connection_struct *conn,
5370                                         const char *pdata,
5371                                         int total_data,
5372                                         const char *fname,
5373                                         SMB_STRUCT_STAT *psbuf)
5374 {
5375         uint32 file_type = IVAL(pdata,56);
5376 #if defined(HAVE_MAKEDEV)
5377         uint32 dev_major = IVAL(pdata,60);
5378         uint32 dev_minor = IVAL(pdata,68);
5379 #endif
5380         SMB_DEV_T dev = (SMB_DEV_T)0;
5381         uint32 raw_unixmode = IVAL(pdata,84);
5382         NTSTATUS status;
5383         mode_t unixmode;
5384
5385         if (total_data < 100) {
5386                 return NT_STATUS_INVALID_PARAMETER;
5387         }
5388
5389         status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_FILE, &unixmode);
5390         if (!NT_STATUS_IS_OK(status)) {
5391                 return status;
5392         }
5393
5394 #if defined(HAVE_MAKEDEV)
5395         dev = makedev(dev_major, dev_minor);
5396 #endif
5397
5398         switch (file_type) {
5399 #if defined(S_IFIFO)
5400                 case UNIX_TYPE_FIFO:
5401                         unixmode |= S_IFIFO;
5402                         break;
5403 #endif
5404 #if defined(S_IFSOCK)
5405                 case UNIX_TYPE_SOCKET:
5406                         unixmode |= S_IFSOCK;
5407                         break;
5408 #endif
5409 #if defined(S_IFCHR)
5410                 case UNIX_TYPE_CHARDEV:
5411                         unixmode |= S_IFCHR;
5412                         break;
5413 #endif
5414 #if defined(S_IFBLK)
5415                 case UNIX_TYPE_BLKDEV:
5416                         unixmode |= S_IFBLK;
5417                         break;
5418 #endif
5419                 default:
5420                         return NT_STATUS_INVALID_PARAMETER;
5421         }
5422
5423         DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
5424 0%o for file %s\n", (double)dev, (unsigned int)unixmode, fname ));
5425
5426         /* Ok - do the mknod. */
5427         if (SMB_VFS_MKNOD(conn, fname, unixmode, dev) != 0) {
5428                 return map_nt_error_from_unix(errno);
5429         }
5430
5431         /* If any of the other "set" calls fail we
5432          * don't want to end up with a half-constructed mknod.
5433          */
5434
5435         if (lp_inherit_perms(SNUM(conn))) {
5436                 inherit_access_acl(
5437                         conn, parent_dirname(fname),
5438                         fname, unixmode);
5439         }
5440
5441         if (SMB_VFS_STAT(conn, fname, psbuf) != 0) {
5442                 status = map_nt_error_from_unix(errno);
5443                 SMB_VFS_UNLINK(conn,fname);
5444                 return status;
5445         }
5446         return NT_STATUS_OK;
5447 }
5448
5449 /****************************************************************************
5450  Deal with SMB_SET_FILE_UNIX_BASIC.
5451 ****************************************************************************/
5452
5453 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
5454                                         struct smb_request *req,
5455                                         const char *pdata,
5456                                         int total_data,
5457                                         files_struct *fsp,
5458                                         const char *fname,
5459                                         SMB_STRUCT_STAT *psbuf)
5460 {
5461         struct timespec ts[2];
5462         uint32 raw_unixmode;
5463         mode_t unixmode;
5464         SMB_OFF_T size = 0;
5465         uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
5466         gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
5467         NTSTATUS status = NT_STATUS_OK;
5468         BOOL delete_on_fail = False;
5469         enum perm_type ptype;
5470
5471         if (total_data < 100) {
5472                 return NT_STATUS_INVALID_PARAMETER;
5473         }
5474
5475         if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
5476            IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
5477                 size=IVAL(pdata,0); /* first 8 Bytes are size */
5478 #ifdef LARGE_SMB_OFF_T
5479                 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5480 #else /* LARGE_SMB_OFF_T */
5481                 if (IVAL(pdata,4) != 0) {
5482                         /* more than 32 bits? */
5483                         return NT_STATUS_INVALID_PARAMETER;
5484                 }
5485 #endif /* LARGE_SMB_OFF_T */
5486         }
5487
5488         ts[0] = interpret_long_date(pdata+24); /* access_time */
5489         ts[1] = interpret_long_date(pdata+32); /* modification_time */
5490         set_owner = (uid_t)IVAL(pdata,40);
5491         set_grp = (gid_t)IVAL(pdata,48);
5492         raw_unixmode = IVAL(pdata,84);
5493
5494         if (VALID_STAT(*psbuf)) {
5495                 if (S_ISDIR(psbuf->st_mode)) {
5496                         ptype = PERM_EXISTING_DIR;
5497                 } else {
5498                         ptype = PERM_EXISTING_FILE;
5499                 }
5500         } else {
5501                 ptype = PERM_NEW_FILE;
5502         }
5503
5504         status = unix_perms_from_wire(conn, psbuf, raw_unixmode, ptype, &unixmode);
5505         if (!NT_STATUS_IS_OK(status)) {
5506                 return status;
5507         }
5508
5509         DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = %s \
5510 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
5511                 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
5512
5513         if (!VALID_STAT(*psbuf)) {
5514                 /*
5515                  * The only valid use of this is to create character and block
5516                  * devices, and named pipes. This is deprecated (IMHO) and 
5517                  * a new info level should be used for mknod. JRA.
5518                  */
5519
5520                 status = smb_unix_mknod(conn,
5521                                         pdata,
5522                                         total_data,
5523                                         fname,
5524                                         psbuf);
5525                 if (!NT_STATUS_IS_OK(status)) {
5526                         return status;
5527                 }
5528
5529                 /* Ensure we don't try and change anything else. */
5530                 raw_unixmode = SMB_MODE_NO_CHANGE;
5531                 size = get_file_size(*psbuf);
5532                 ts[0] = get_atimespec(psbuf);
5533                 ts[1] = get_mtimespec(psbuf);
5534                 /* 
5535                  * We continue here as we might want to change the 
5536                  * owner uid/gid.
5537                  */
5538                 delete_on_fail = True;
5539         }
5540
5541 #if 1
5542         /* Horrible backwards compatibility hack as an old server bug
5543          * allowed a CIFS client bug to remain unnoticed :-(. JRA.
5544          * */
5545
5546         if (!size) {
5547                 size = get_file_size(*psbuf);
5548         }
5549 #endif
5550
5551         /*
5552          * Deal with the UNIX specific mode set.
5553          */
5554
5555         if (raw_unixmode != SMB_MODE_NO_CHANGE) {
5556                 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
5557                         (unsigned int)unixmode, fname ));
5558                 if (SMB_VFS_CHMOD(conn, fname, unixmode) != 0) {
5559                         return map_nt_error_from_unix(errno);
5560                 }
5561         }
5562
5563         /*
5564          * Deal with the UNIX specific uid set.
5565          */
5566
5567         if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (psbuf->st_uid != set_owner)) {
5568                 int ret;
5569
5570                 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing owner %u for path %s\n",
5571                         (unsigned int)set_owner, fname ));
5572
5573                 if (S_ISLNK(psbuf->st_mode)) {
5574                         ret = SMB_VFS_LCHOWN(conn, fname, set_owner, (gid_t)-1);
5575                 } else {
5576                         ret = SMB_VFS_CHOWN(conn, fname, set_owner, (gid_t)-1);
5577                 }
5578
5579                 if (ret != 0) {
5580                         status = map_nt_error_from_unix(errno);
5581                         if (delete_on_fail) {
5582                                 SMB_VFS_UNLINK(conn,fname);
5583                         }
5584                         return status;
5585                 }
5586         }
5587
5588         /*
5589          * Deal with the UNIX specific gid set.
5590          */
5591
5592         if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (psbuf->st_gid != set_grp)) {
5593                 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
5594                         (unsigned int)set_owner, fname ));
5595                 if (SMB_VFS_CHOWN(conn, fname, (uid_t)-1, set_grp) != 0) {
5596                         status = map_nt_error_from_unix(errno);
5597                         if (delete_on_fail) {
5598                                 SMB_VFS_UNLINK(conn,fname);
5599                         }
5600                         return status;
5601                 }
5602         }
5603
5604         /* Deal with any size changes. */
5605
5606         status = smb_set_file_size(conn, req,
5607                                 fsp,
5608                                 fname,
5609                                 psbuf,
5610                                 size);
5611         if (!NT_STATUS_IS_OK(status)) {
5612                 return status;
5613         }
5614
5615         /* Deal with any time changes. */
5616
5617         return smb_set_file_time(conn,
5618                                 fsp,
5619                                 fname,
5620                                 psbuf,
5621                                 ts);
5622 }
5623
5624 /****************************************************************************
5625  Deal with SMB_SET_FILE_UNIX_INFO2.
5626 ****************************************************************************/
5627
5628 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
5629                                         struct smb_request *req,
5630                                         const char *pdata,
5631                                         int total_data,
5632                                         files_struct *fsp,
5633                                         const char *fname,
5634                                         SMB_STRUCT_STAT *psbuf)
5635 {
5636         NTSTATUS status;
5637         uint32 smb_fflags;
5638         uint32 smb_fmask;
5639
5640         if (total_data < 116) {
5641                 return NT_STATUS_INVALID_PARAMETER;
5642         }
5643
5644         /* Start by setting all the fields that are common between UNIX_BASIC
5645          * and UNIX_INFO2.
5646          */
5647         status = smb_set_file_unix_basic(conn, req, pdata, total_data,
5648                                 fsp, fname, psbuf);
5649         if (!NT_STATUS_IS_OK(status)) {
5650                 return status;
5651         }
5652
5653         smb_fflags = IVAL(pdata, 108);
5654         smb_fmask = IVAL(pdata, 112);
5655
5656         /* NB: We should only attempt to alter the file flags if the client
5657          * sends a non-zero mask.
5658          */
5659         if (smb_fmask != 0) {
5660                 int stat_fflags = 0;
5661
5662                 if (!map_info2_flags_to_sbuf(psbuf, smb_fflags, smb_fmask,
5663                             &stat_fflags)) {
5664                         /* Client asked to alter a flag we don't understand. */
5665                         return NT_STATUS_INVALID_PARAMETER;
5666                 }
5667
5668                 if (fsp && fsp->fh->fd != -1) {
5669                         /* XXX: we should be  using SMB_VFS_FCHFLAGS here. */
5670                         return NT_STATUS_NOT_SUPPORTED;
5671                 } else {
5672                         if (SMB_VFS_CHFLAGS(conn, fname, stat_fflags) != 0) {
5673                                 return map_nt_error_from_unix(errno);
5674                         }
5675                 }
5676         }
5677
5678         /* XXX: need to add support for changing the create_time here. You
5679          * can do this for paths on Darwin with setattrlist(2). The right way
5680          * to hook this up is probably by extending the VFS utimes interface.
5681          */
5682
5683         return NT_STATUS_OK;
5684 }
5685
5686 /****************************************************************************
5687  Create a directory with POSIX semantics.
5688 ****************************************************************************/
5689
5690 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
5691                                 struct smb_request *req,
5692                                 char **ppdata,
5693                                 int total_data,
5694                                 const char *fname,
5695                                 SMB_STRUCT_STAT *psbuf,
5696                                 int *pdata_return_size)
5697 {
5698         NTSTATUS status = NT_STATUS_OK;
5699         uint32 raw_unixmode = 0;
5700         uint32 mod_unixmode = 0;
5701         mode_t unixmode = (mode_t)0;
5702         files_struct *fsp = NULL;
5703         uint16 info_level_return = 0;
5704         int info;
5705         char *pdata = *ppdata;
5706
5707         if (total_data < 18) {
5708                 return NT_STATUS_INVALID_PARAMETER;
5709         }
5710
5711         raw_unixmode = IVAL(pdata,8);
5712         /* Next 4 bytes are not yet defined. */
5713
5714         status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_DIR, &unixmode);
5715         if (!NT_STATUS_IS_OK(status)) {
5716                 return status;
5717         }
5718
5719         mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
5720
5721         DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
5722                 fname, (unsigned int)unixmode ));
5723
5724         status = open_directory(conn, req,
5725                                 fname,
5726                                 psbuf,
5727                                 FILE_READ_ATTRIBUTES, /* Just a stat open */
5728                                 FILE_SHARE_NONE, /* Ignored for stat opens */
5729                                 FILE_CREATE,
5730                                 0,
5731                                 mod_unixmode,
5732                                 &info,
5733                                 &fsp);
5734
5735         if (NT_STATUS_IS_OK(status)) {
5736                 close_file(fsp, NORMAL_CLOSE);
5737         }
5738
5739         info_level_return = SVAL(pdata,16);
5740  
5741         if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
5742                 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
5743         } else if (info_level_return ==  SMB_QUERY_FILE_UNIX_INFO2) {
5744                 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
5745         } else {
5746                 *pdata_return_size = 12;
5747         }
5748
5749         /* Realloc the data size */
5750         *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
5751         if (*ppdata == NULL) {
5752                 *pdata_return_size = 0;
5753                 return NT_STATUS_NO_MEMORY;
5754         }
5755         pdata = *ppdata;
5756
5757         SSVAL(pdata,0,NO_OPLOCK_RETURN);
5758         SSVAL(pdata,2,0); /* No fnum. */
5759         SIVAL(pdata,4,info); /* Was directory created. */
5760
5761         switch (info_level_return) {
5762                 case SMB_QUERY_FILE_UNIX_BASIC:
5763                         SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
5764                         SSVAL(pdata,10,0); /* Padding. */
5765                         store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
5766                         break;
5767                 case SMB_QUERY_FILE_UNIX_INFO2:
5768                         SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
5769                         SSVAL(pdata,10,0); /* Padding. */
5770                         store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
5771                         break;
5772                 default:
5773                         SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
5774                         SSVAL(pdata,10,0); /* Padding. */
5775                         break;
5776         }
5777
5778         return status;
5779 }
5780
5781 /****************************************************************************
5782  Open/Create a file with POSIX semantics.
5783 ****************************************************************************/
5784
5785 static NTSTATUS smb_posix_open(connection_struct *conn,
5786                                struct smb_request *req,
5787                                 char **ppdata,
5788                                 int total_data,
5789                                 const char *fname,
5790                                 SMB_STRUCT_STAT *psbuf,
5791                                 int *pdata_return_size)
5792 {
5793         BOOL extended_oplock_granted = False;
5794         char *pdata = *ppdata;
5795         uint32 flags = 0;
5796         uint32 wire_open_mode = 0;
5797         uint32 raw_unixmode = 0;
5798         uint32 mod_unixmode = 0;
5799         uint32 create_disp = 0;
5800         uint32 access_mask = 0;
5801         uint32 create_options = 0;
5802         NTSTATUS status = NT_STATUS_OK;
5803         mode_t unixmode = (mode_t)0;
5804         files_struct *fsp = NULL;
5805         int oplock_request = 0;
5806         int info = 0;
5807         uint16 info_level_return = 0;
5808
5809         if (total_data < 18) {
5810                 return NT_STATUS_INVALID_PARAMETER;
5811         }
5812
5813         flags = IVAL(pdata,0);
5814         oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
5815         if (oplock_request) {
5816                 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
5817         }
5818
5819         wire_open_mode = IVAL(pdata,4);
5820
5821         if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
5822                 return smb_posix_mkdir(conn, req,
5823                                         ppdata,
5824                                         total_data,
5825                                         fname,
5826                                         psbuf,
5827                                         pdata_return_size);
5828         }
5829
5830         switch (wire_open_mode & SMB_ACCMODE) {
5831                 case SMB_O_RDONLY:
5832                         access_mask = FILE_READ_DATA;
5833                         break;
5834                 case SMB_O_WRONLY:
5835                         access_mask = FILE_WRITE_DATA;
5836                         break;
5837                 case SMB_O_RDWR:
5838                         access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
5839                         break;
5840                 default:
5841                         DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
5842                                 (unsigned int)wire_open_mode ));
5843                         return NT_STATUS_INVALID_PARAMETER;
5844         }
5845
5846         wire_open_mode &= ~SMB_ACCMODE;
5847
5848         if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) {
5849                 create_disp = FILE_CREATE;
5850         } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) {
5851                 create_disp = FILE_OVERWRITE_IF;
5852         } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
5853                 create_disp = FILE_OPEN_IF;
5854         } else {
5855                 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
5856                         (unsigned int)wire_open_mode ));
5857                 return NT_STATUS_INVALID_PARAMETER;
5858         }
5859
5860         raw_unixmode = IVAL(pdata,8);
5861         /* Next 4 bytes are not yet defined. */
5862
5863         status = unix_perms_from_wire(conn,
5864                                 psbuf,
5865                                 raw_unixmode,
5866                                 VALID_STAT(*psbuf) ? PERM_EXISTING_FILE : PERM_NEW_FILE,
5867                                 &unixmode);
5868
5869         if (!NT_STATUS_IS_OK(status)) {
5870                 return status;
5871         }
5872
5873         mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
5874
5875         if (wire_open_mode & SMB_O_SYNC) {
5876                 create_options |= FILE_WRITE_THROUGH;
5877         }
5878         if (wire_open_mode & SMB_O_APPEND) {
5879                 access_mask |= FILE_APPEND_DATA;
5880         }
5881         if (wire_open_mode & SMB_O_DIRECT) {
5882                 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
5883         }
5884
5885         DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
5886                 fname,
5887                 (unsigned int)wire_open_mode,
5888                 (unsigned int)unixmode ));
5889
5890         status = open_file_ntcreate(conn, req,
5891                                 fname,
5892                                 psbuf,
5893                                 access_mask,
5894                                 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5895                                 create_disp,
5896                                 0,              /* no create options yet. */
5897                                 mod_unixmode,
5898                                 oplock_request,
5899                                 &info,
5900                                 &fsp);
5901
5902         if (!NT_STATUS_IS_OK(status)) {
5903                 return status;
5904         }
5905
5906         if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
5907                 extended_oplock_granted = True;
5908         }
5909
5910         if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
5911                 extended_oplock_granted = True;
5912         }
5913
5914         info_level_return = SVAL(pdata,16);
5915  
5916         /* Allocate the correct return size. */
5917
5918         if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
5919                 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
5920         } else if (info_level_return ==  SMB_QUERY_FILE_UNIX_INFO2) {
5921                 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
5922         } else {
5923                 *pdata_return_size = 12;
5924         }
5925
5926         /* Realloc the data size */
5927         *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
5928         if (*ppdata == NULL) {
5929                 close_file(fsp,ERROR_CLOSE);
5930                 *pdata_return_size = 0;
5931                 return NT_STATUS_NO_MEMORY;
5932         }
5933         pdata = *ppdata;
5934
5935         if (extended_oplock_granted) {
5936                 if (flags & REQUEST_BATCH_OPLOCK) {
5937                         SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
5938                 } else {
5939                         SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
5940                 }
5941         } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
5942                 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
5943         } else {
5944                 SSVAL(pdata,0,NO_OPLOCK_RETURN);
5945         }
5946
5947         SSVAL(pdata,2,fsp->fnum);
5948         SIVAL(pdata,4,info); /* Was file created etc. */
5949
5950         switch (info_level_return) {
5951                 case SMB_QUERY_FILE_UNIX_BASIC:
5952                         SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
5953                         SSVAL(pdata,10,0); /* padding. */
5954                         store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
5955                         break;
5956                 case SMB_QUERY_FILE_UNIX_INFO2:
5957                         SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
5958                         SSVAL(pdata,10,0); /* padding. */
5959                         store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
5960                         break;
5961                 default:
5962                         SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
5963                         SSVAL(pdata,10,0); /* padding. */
5964                         break;
5965         }
5966         return NT_STATUS_OK;
5967 }
5968
5969 /****************************************************************************
5970  Delete a file with POSIX semantics.
5971 ****************************************************************************/
5972
5973 static NTSTATUS smb_posix_unlink(connection_struct *conn,
5974                                  struct smb_request *req,
5975                                 const char *pdata,
5976                                 int total_data,
5977                                 const char *fname,
5978                                 SMB_STRUCT_STAT *psbuf)
5979 {
5980         NTSTATUS status = NT_STATUS_OK;
5981         files_struct *fsp = NULL;
5982         uint16 flags = 0;
5983         char del = 1;
5984         int info = 0;
5985         int i;
5986         struct share_mode_lock *lck = NULL;
5987
5988         if (total_data < 2) {
5989                 return NT_STATUS_INVALID_PARAMETER;
5990         }
5991
5992         flags = SVAL(pdata,0);
5993
5994         if (!VALID_STAT(*psbuf)) {
5995                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5996         }
5997
5998         if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
5999                         !VALID_STAT_OF_DIR(*psbuf)) {
6000                 return NT_STATUS_NOT_A_DIRECTORY;
6001         }
6002
6003         DEBUG(10,("smb_posix_unlink: %s %s\n",
6004                 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
6005                 fname));
6006
6007         if (VALID_STAT_OF_DIR(*psbuf)) {
6008                 status = open_directory(conn, req,
6009                                         fname,
6010                                         psbuf,
6011                                         DELETE_ACCESS,
6012                                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6013                                         FILE_OPEN,
6014                                         0,
6015                                         FILE_FLAG_POSIX_SEMANTICS|0777,
6016                                         &info,
6017                                         &fsp);
6018         } else {
6019
6020                 status = open_file_ntcreate(conn, req,
6021                                 fname,
6022                                 psbuf,
6023                                 DELETE_ACCESS,
6024                                 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6025                                 FILE_OPEN,
6026                                 0,
6027                                 FILE_FLAG_POSIX_SEMANTICS|0777,
6028                                 0, /* No oplock, but break existing ones. */
6029                                 &info,
6030                                 &fsp);
6031         }
6032
6033         if (!NT_STATUS_IS_OK(status)) {
6034                 return status;
6035         }
6036
6037         /*
6038          * Don't lie to client. If we can't really delete due to
6039          * non-POSIX opens return SHARING_VIOLATION.
6040          */
6041
6042         lck = get_share_mode_lock(NULL, fsp->file_id, NULL, NULL);
6043         if (lck == NULL) {
6044                 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
6045                         "lock for file %s\n", fsp->fsp_name));
6046                 close_file(fsp, NORMAL_CLOSE);
6047                 return NT_STATUS_INVALID_PARAMETER;
6048         }
6049
6050         /*
6051          * See if others still have the file open. If this is the case, then
6052          * don't delete. If all opens are POSIX delete we can set the delete
6053          * on close disposition.
6054          */
6055         for (i=0; i<lck->num_share_modes; i++) {
6056                 struct share_mode_entry *e = &lck->share_modes[i];
6057                 if (is_valid_share_mode_entry(e)) {
6058                         if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
6059                                 continue;
6060                         }
6061                         /* Fail with sharing violation. */
6062                         close_file(fsp, NORMAL_CLOSE);
6063                         TALLOC_FREE(lck);
6064                         return NT_STATUS_SHARING_VIOLATION;
6065                 }
6066         }
6067
6068         /*
6069          * Set the delete on close.
6070          */
6071         status = smb_set_file_disposition_info(conn,
6072                                                 &del,
6073                                                 1,
6074                                                 fsp,
6075                                                 fname,
6076                                                 psbuf);
6077
6078         if (!NT_STATUS_IS_OK(status)) {
6079                 close_file(fsp, NORMAL_CLOSE);
6080                 TALLOC_FREE(lck);
6081                 return status;
6082         }
6083         TALLOC_FREE(lck);
6084         return close_file(fsp, NORMAL_CLOSE);
6085 }
6086
6087 /****************************************************************************
6088  Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
6089 ****************************************************************************/
6090
6091 static void call_trans2setfilepathinfo(connection_struct *conn,
6092                                        struct smb_request *req,
6093                                        unsigned int tran_call,
6094                                        char **pparams, int total_params,
6095                                        char **ppdata, int total_data,
6096                                        unsigned int max_data_bytes)
6097 {
6098         char *params = *pparams;
6099         char *pdata = *ppdata;
6100         uint16 info_level;
6101         SMB_STRUCT_STAT sbuf;
6102         pstring fname;
6103         files_struct *fsp = NULL;
6104         NTSTATUS status = NT_STATUS_OK;
6105         int data_return_size = 0;
6106
6107         if (!params) {
6108                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6109                 return;
6110         }
6111
6112         ZERO_STRUCT(sbuf);
6113
6114         if (tran_call == TRANSACT2_SETFILEINFO) {
6115                 if (total_params < 4) {
6116                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6117                         return;
6118                 }
6119
6120                 fsp = file_fsp(SVAL(params,0));
6121                 info_level = SVAL(params,2);    
6122
6123                 if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
6124                         /*
6125                          * This is actually a SETFILEINFO on a directory
6126                          * handle (returned from an NT SMB). NT5.0 seems
6127                          * to do this call. JRA.
6128                          */
6129                         pstrcpy(fname, fsp->fsp_name);
6130                         if (INFO_LEVEL_IS_UNIX(info_level)) {
6131                                 /* Always do lstat for UNIX calls. */
6132                                 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
6133                                         DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
6134                                         reply_unixerror(req,ERRDOS,ERRbadpath);
6135                                         return;
6136                                 }
6137                         } else {
6138                                 if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
6139                                         DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
6140                                         reply_unixerror(req,ERRDOS,ERRbadpath);
6141                                         return;
6142                                 }
6143                         }
6144                 } else if (fsp && fsp->print_file) {
6145                         /*
6146                          * Doing a DELETE_ON_CLOSE should cancel a print job.
6147                          */
6148                         if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
6149                                 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
6150
6151                                 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
6152         
6153                                 SSVAL(params,0,0);
6154                                 send_trans2_replies_new(req, params, 2,
6155                                                         *ppdata, 0,
6156                                                         max_data_bytes);
6157                                 return;
6158                         }
6159                         else {
6160                                 reply_unixerror(req, ERRDOS, ERRbadpath);
6161                                 return;
6162                         }
6163             } else {
6164                         /*
6165                          * Original code - this is an open file.
6166                          */
6167                         if (!check_fsp(conn, req, fsp, &current_user)) {
6168                                 return;
6169                         }
6170
6171                         pstrcpy(fname, fsp->fsp_name);
6172
6173                         if (SMB_VFS_FSTAT(fsp, fsp->fh->fd, &sbuf) != 0) {
6174                                 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
6175                                 reply_unixerror(req, ERRDOS, ERRbadfid);
6176                                 return;
6177                         }
6178                 }
6179         } else {
6180                 /* set path info */
6181                 if (total_params < 7) {
6182                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6183                         return;
6184                 }
6185
6186                 info_level = SVAL(params,0);    
6187                 srvstr_get_path(params, req->flags2, fname, &params[6],
6188                                 sizeof(fname), total_params - 6, STR_TERMINATE,
6189                                 &status);
6190                 if (!NT_STATUS_IS_OK(status)) {
6191                         reply_nterror(req, status);
6192                         return;
6193                 }
6194
6195                 status = resolve_dfspath(conn,
6196                                          req->flags2 & FLAGS2_DFS_PATHNAMES,
6197                                          fname);
6198                 if (!NT_STATUS_IS_OK(status)) {
6199                         if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6200                                 reply_botherror(req,
6201                                                 NT_STATUS_PATH_NOT_COVERED,
6202                                                 ERRSRV, ERRbadpath);
6203                                 return;
6204                         }
6205                         reply_nterror(req, status);
6206                         return;
6207                 }
6208
6209                 status = unix_convert(conn, fname, False, NULL, &sbuf);
6210                 if (!NT_STATUS_IS_OK(status)) {
6211                         reply_nterror(req, status);
6212                         return;
6213                 }
6214
6215                 status = check_name(conn, fname);
6216                 if (!NT_STATUS_IS_OK(status)) {
6217                         reply_nterror(req, status);
6218                         return;
6219                 }
6220
6221                 if (INFO_LEVEL_IS_UNIX(info_level)) {
6222                         /*
6223                          * For CIFS UNIX extensions the target name may not exist.
6224                          */
6225
6226                         /* Always do lstat for UNIX calls. */
6227                         SMB_VFS_LSTAT(conn,fname,&sbuf);
6228
6229                 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf)) {
6230                         DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
6231                         reply_unixerror(req, ERRDOS, ERRbadpath);
6232                         return;
6233                 }
6234         }
6235
6236         if (!CAN_WRITE(conn)) {
6237                 reply_doserror(req, ERRSRV, ERRaccess);
6238                 return;
6239         }
6240
6241         if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
6242                 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6243                 return;
6244         }
6245
6246         DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
6247                 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
6248
6249         /* Realloc the parameter size */
6250         *pparams = (char *)SMB_REALLOC(*pparams,2);
6251         if (*pparams == NULL) {
6252                 reply_nterror(req, NT_STATUS_NO_MEMORY);
6253                 return;
6254         }
6255         params = *pparams;
6256
6257         SSVAL(params,0,0);
6258
6259         if (fsp && !null_timespec(fsp->pending_modtime)) {
6260                 /* the pending modtime overrides the current modtime */
6261                 set_mtimespec(&sbuf, fsp->pending_modtime);
6262         }
6263
6264         switch (info_level) {
6265
6266                 case SMB_INFO_STANDARD:
6267                 {
6268                         status = smb_set_info_standard(conn,
6269                                         pdata,
6270                                         total_data,
6271                                         fsp,
6272                                         fname,
6273                                         &sbuf);
6274                         break;
6275                 }
6276
6277                 case SMB_INFO_SET_EA:
6278                 {
6279                         status = smb_info_set_ea(conn,
6280                                                 pdata,
6281                                                 total_data,
6282                                                 fsp,
6283                                                 fname);
6284                         break;
6285                 }
6286
6287                 case SMB_SET_FILE_BASIC_INFO:
6288                 case SMB_FILE_BASIC_INFORMATION:
6289                 {
6290                         status = smb_set_file_basic_info(conn,
6291                                                         pdata,
6292                                                         total_data,
6293                                                         fsp,
6294                                                         fname,
6295                                                         &sbuf);
6296                         break;
6297                 }
6298
6299                 case SMB_FILE_ALLOCATION_INFORMATION:
6300                 case SMB_SET_FILE_ALLOCATION_INFO:
6301                 {
6302                         status = smb_set_file_allocation_info(conn, req,
6303                                                                 pdata,
6304                                                                 total_data,
6305                                                                 fsp,
6306                                                                 fname,
6307                                                                 &sbuf);
6308                         break;
6309                 }
6310
6311                 case SMB_FILE_END_OF_FILE_INFORMATION:
6312                 case SMB_SET_FILE_END_OF_FILE_INFO:
6313                 {
6314                         status = smb_set_file_end_of_file_info(conn, req,
6315                                                                 pdata,
6316                                                                 total_data,
6317                                                                 fsp,
6318                                                                 fname,
6319                                                                 &sbuf);
6320                         break;
6321                 }
6322
6323                 case SMB_FILE_DISPOSITION_INFORMATION:
6324                 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
6325                 {
6326 #if 0
6327                         /* JRA - We used to just ignore this on a path ? 
6328                          * Shouldn't this be invalid level on a pathname
6329                          * based call ?
6330                          */
6331                         if (tran_call != TRANSACT2_SETFILEINFO) {
6332                                 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6333                         }
6334 #endif
6335                         status = smb_set_file_disposition_info(conn,
6336                                                 pdata,
6337                                                 total_data,
6338                                                 fsp,
6339                                                 fname,
6340                                                 &sbuf);
6341                         break;
6342                 }
6343
6344                 case SMB_FILE_POSITION_INFORMATION:
6345                 {
6346                         status = smb_file_position_information(conn,
6347                                                 pdata,
6348                                                 total_data,
6349                                                 fsp);
6350                         break;
6351                 }
6352
6353                 /* From tridge Samba4 : 
6354                  * MODE_INFORMATION in setfileinfo (I have no
6355                  * idea what "mode information" on a file is - it takes a value of 0,
6356                  * 2, 4 or 6. What could it be?).
6357                  */
6358
6359                 case SMB_FILE_MODE_INFORMATION:
6360                 {
6361                         status = smb_file_mode_information(conn,
6362                                                 pdata,
6363                                                 total_data);
6364                         break;
6365                 }
6366
6367                 /*
6368                  * CIFS UNIX extensions.
6369                  */
6370
6371                 case SMB_SET_FILE_UNIX_BASIC:
6372                 {
6373                         status = smb_set_file_unix_basic(conn, req,
6374                                                         pdata,
6375                                                         total_data,
6376                                                         fsp,
6377                                                         fname,
6378                                                         &sbuf);
6379                         break;
6380                 }
6381
6382                 case SMB_SET_FILE_UNIX_INFO2:
6383                 {
6384                         status = smb_set_file_unix_info2(conn, req,
6385                                                         pdata,
6386                                                         total_data,
6387                                                         fsp,
6388                                                         fname,
6389                                                         &sbuf);
6390                         break;
6391                 }
6392
6393                 case SMB_SET_FILE_UNIX_LINK:
6394                 {
6395                         if (tran_call != TRANSACT2_SETPATHINFO) {
6396                                 /* We must have a pathname for this. */
6397                                 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6398                                 return;
6399                         }
6400                         status = smb_set_file_unix_link(conn, req, pdata,
6401                                                         total_data, fname);
6402                         break;
6403                 }
6404
6405                 case SMB_SET_FILE_UNIX_HLINK:
6406                 {
6407                         if (tran_call != TRANSACT2_SETPATHINFO) {
6408                                 /* We must have a pathname for this. */
6409                                 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6410                                 return;
6411                         }
6412                         status = smb_set_file_unix_hlink(conn, req,
6413                                                          pdata, total_data,
6414                                                          fname);
6415                         break;
6416                 }
6417
6418                 case SMB_FILE_RENAME_INFORMATION:
6419                 {
6420                         status = smb_file_rename_information(conn, req,
6421                                                              pdata, total_data,
6422                                                              fsp, fname);
6423                         break;
6424                 }
6425
6426 #if defined(HAVE_POSIX_ACLS)
6427                 case SMB_SET_POSIX_ACL:
6428                 {
6429                         status = smb_set_posix_acl(conn,
6430                                                 pdata,
6431                                                 total_data,
6432                                                 fsp,
6433                                                 fname,
6434                                                 &sbuf);
6435                         break;
6436                 }
6437 #endif
6438
6439                 case SMB_SET_POSIX_LOCK:
6440                 {
6441                         if (tran_call != TRANSACT2_SETFILEINFO) {
6442                                 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6443                                 return;
6444                         }
6445                         status = smb_set_posix_lock(conn, req->inbuf,
6446                                                     smb_len(req->inbuf) + 4,
6447                                                     pdata, total_data, fsp);
6448                         break;
6449                 }
6450
6451                 case SMB_POSIX_PATH_OPEN:
6452                 {
6453                         if (tran_call != TRANSACT2_SETPATHINFO) {
6454                                 /* We must have a pathname for this. */
6455                                 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6456                                 return;
6457                         }
6458
6459                         status = smb_posix_open(conn, req,
6460                                                 ppdata,
6461                                                 total_data,
6462                                                 fname,
6463                                                 &sbuf,
6464                                                 &data_return_size);
6465                         break;
6466                 }
6467
6468                 case SMB_POSIX_PATH_UNLINK:
6469                 {
6470                         if (tran_call != TRANSACT2_SETPATHINFO) {
6471                                 /* We must have a pathname for this. */
6472                                 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6473                                 return;
6474                         }
6475
6476                         status = smb_posix_unlink(conn, req,
6477                                                 pdata,
6478                                                 total_data,
6479                                                 fname,
6480                                                 &sbuf);
6481                         break;
6482                 }
6483
6484                 default:
6485                         reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6486                         return;
6487         }
6488
6489         
6490         if (!NT_STATUS_IS_OK(status)) {
6491                 if (open_was_deferred(req->mid)) {
6492                         /* We have re-scheduled this call. */
6493                         return;
6494                 }
6495                 if (blocking_lock_was_deferred(req->mid)) {
6496                         /* We have re-scheduled this call. */
6497                         return;
6498                 }
6499                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6500                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6501                                         ERRSRV, ERRbadpath);
6502                         return;
6503                 }
6504                 reply_nterror(req, status);
6505                 return;
6506         }
6507
6508         SSVAL(params,0,0);
6509         send_trans2_replies_new(req, params, 2, *ppdata, data_return_size,
6510                                 max_data_bytes);
6511   
6512         return;
6513 }
6514
6515 /****************************************************************************
6516  Reply to a TRANS2_MKDIR (make directory with extended attributes).
6517 ****************************************************************************/
6518
6519 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
6520                              char **pparams, int total_params,
6521                              char **ppdata, int total_data,
6522                              unsigned int max_data_bytes)
6523 {
6524         char *params = *pparams;
6525         char *pdata = *ppdata;
6526         pstring directory;
6527         SMB_STRUCT_STAT sbuf;
6528         NTSTATUS status = NT_STATUS_OK;
6529         struct ea_list *ea_list = NULL;
6530
6531         if (!CAN_WRITE(conn)) {
6532                 reply_doserror(req, ERRSRV, ERRaccess);
6533                 return;
6534         }
6535
6536         if (total_params < 5) {
6537                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6538                 return;
6539         }
6540
6541         srvstr_get_path(params, req->flags2, directory, &params[4],
6542                         sizeof(directory), total_params - 4, STR_TERMINATE,
6543                         &status);
6544         if (!NT_STATUS_IS_OK(status)) {
6545                 reply_nterror(req, status);
6546                 return;
6547         }
6548
6549         DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
6550
6551         status = unix_convert(conn, directory, False, NULL, &sbuf);
6552         if (!NT_STATUS_IS_OK(status)) {
6553                 reply_nterror(req, status);
6554                 return;
6555         }
6556
6557         status = check_name(conn, directory);
6558         if (!NT_STATUS_IS_OK(status)) {
6559                 DEBUG(5,("call_trans2mkdir error (%s)\n", nt_errstr(status)));
6560                 reply_nterror(req, status);
6561                 return;
6562         }
6563
6564         /* Any data in this call is an EA list. */
6565         if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
6566                 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
6567                 return;
6568         }
6569
6570         /*
6571          * OS/2 workplace shell seems to send SET_EA requests of "null"
6572          * length (4 bytes containing IVAL 4).
6573          * They seem to have no effect. Bug #3212. JRA.
6574          */
6575
6576         if (total_data != 4) {
6577                 if (total_data < 10) {
6578                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6579                         return;
6580                 }
6581
6582                 if (IVAL(pdata,0) > total_data) {
6583                         DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
6584                                 IVAL(pdata,0), (unsigned int)total_data));
6585                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6586                         return;
6587                 }
6588
6589                 ea_list = read_ea_list(tmp_talloc_ctx(), pdata + 4,
6590                                        total_data - 4);
6591                 if (!ea_list) {
6592                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6593                         return;
6594                 }
6595         } else if (IVAL(pdata,0) != 4) {
6596                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6597                 return;
6598         }
6599
6600         status = create_directory(conn, directory);
6601
6602         if (!NT_STATUS_IS_OK(status)) {
6603                 reply_nterror(req, status);
6604                 return;
6605         }
6606   
6607         /* Try and set any given EA. */
6608         if (ea_list) {
6609                 status = set_ea(conn, NULL, directory, ea_list);
6610                 if (!NT_STATUS_IS_OK(status)) {
6611                         reply_nterror(req, status);
6612                         return;
6613                 }
6614         }
6615
6616         /* Realloc the parameter and data sizes */
6617         *pparams = (char *)SMB_REALLOC(*pparams,2);
6618         if(*pparams == NULL) {
6619                 reply_nterror(req, NT_STATUS_NO_MEMORY);
6620                 return;
6621         }
6622         params = *pparams;
6623
6624         SSVAL(params,0,0);
6625
6626         send_trans2_replies_new(req, params, 2, *ppdata, 0, max_data_bytes);
6627   
6628         return;
6629 }
6630
6631 /****************************************************************************
6632  Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
6633  We don't actually do this - we just send a null response.
6634 ****************************************************************************/
6635
6636 static void call_trans2findnotifyfirst(connection_struct *conn,
6637                                        struct smb_request *req,
6638                                        char **pparams, int total_params,
6639                                        char **ppdata, int total_data,
6640                                        unsigned int max_data_bytes)
6641 {
6642         static uint16 fnf_handle = 257;
6643         char *params = *pparams;
6644         uint16 info_level;
6645
6646         if (total_params < 6) {
6647                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6648                 return;
6649         }
6650
6651         info_level = SVAL(params,4);
6652         DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
6653
6654         switch (info_level) {
6655                 case 1:
6656                 case 2:
6657                         break;
6658                 default:
6659                         reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6660                         return;
6661         }
6662
6663         /* Realloc the parameter and data sizes */
6664         *pparams = (char *)SMB_REALLOC(*pparams,6);
6665         if (*pparams == NULL) {
6666                 reply_nterror(req, NT_STATUS_NO_MEMORY);
6667                 return;
6668         }
6669         params = *pparams;
6670
6671         SSVAL(params,0,fnf_handle);
6672         SSVAL(params,2,0); /* No changes */
6673         SSVAL(params,4,0); /* No EA errors */
6674
6675         fnf_handle++;
6676
6677         if(fnf_handle == 0)
6678                 fnf_handle = 257;
6679
6680         send_trans2_replies_new(req, params, 6, *ppdata, 0, max_data_bytes);
6681   
6682         return;
6683 }
6684
6685 /****************************************************************************
6686  Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for 
6687  changes). Currently this does nothing.
6688 ****************************************************************************/
6689
6690 static void call_trans2findnotifynext(connection_struct *conn,
6691                                       struct smb_request *req,
6692                                       char **pparams, int total_params,
6693                                       char **ppdata, int total_data,
6694                                       unsigned int max_data_bytes)
6695 {
6696         char *params = *pparams;
6697
6698         DEBUG(3,("call_trans2findnotifynext\n"));
6699
6700         /* Realloc the parameter and data sizes */
6701         *pparams = (char *)SMB_REALLOC(*pparams,4);
6702         if (*pparams == NULL) {
6703                 reply_nterror(req, NT_STATUS_NO_MEMORY);
6704                 return;
6705         }
6706         params = *pparams;
6707
6708         SSVAL(params,0,0); /* No changes */
6709         SSVAL(params,2,0); /* No EA errors */
6710
6711         send_trans2_replies_new(req, params, 4, *ppdata, 0, max_data_bytes);
6712   
6713         return;
6714 }
6715
6716 /****************************************************************************
6717  Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
6718 ****************************************************************************/
6719
6720 static void call_trans2getdfsreferral(connection_struct *conn,
6721                                       struct smb_request *req,
6722                                       char **pparams, int total_params,
6723                                       char **ppdata, int total_data,
6724                                       unsigned int max_data_bytes)
6725 {
6726         char *params = *pparams;
6727         pstring pathname;
6728         int reply_size = 0;
6729         int max_referral_level;
6730         NTSTATUS status = NT_STATUS_OK;
6731
6732         DEBUG(10,("call_trans2getdfsreferral\n"));
6733
6734         if (total_params < 3) {
6735                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6736                 return;
6737         }
6738
6739         max_referral_level = SVAL(params,0);
6740
6741         if(!lp_host_msdfs()) {
6742                 reply_doserror(req, ERRDOS, ERRbadfunc);
6743                 return;
6744         }
6745
6746         srvstr_pull(params, req->flags2, pathname, &params[2],
6747                     sizeof(pathname), total_params - 2, STR_TERMINATE);
6748         if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
6749                                             ppdata,&status)) < 0) {
6750                 reply_nterror(req, status);
6751                 return;
6752         }
6753     
6754         SSVAL(req->inbuf, smb_flg2,
6755               SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
6756         send_trans2_replies_new(req,0,0,*ppdata,reply_size, max_data_bytes);
6757
6758         return;
6759 }
6760
6761 #define LMCAT_SPL       0x53
6762 #define LMFUNC_GETJOBID 0x60
6763
6764 /****************************************************************************
6765  Reply to a TRANS2_IOCTL - used for OS/2 printing.
6766 ****************************************************************************/
6767
6768 static void call_trans2ioctl(connection_struct *conn,
6769                              struct smb_request *req,
6770                              char **pparams, int total_params,
6771                              char **ppdata, int total_data,
6772                              unsigned int max_data_bytes)
6773 {
6774         char *pdata = *ppdata;
6775         files_struct *fsp = file_fsp(SVAL(req->inbuf,smb_vwv15));
6776
6777         /* check for an invalid fid before proceeding */
6778         
6779         if (!fsp) {
6780                 reply_doserror(req, ERRDOS, ERRbadfid);
6781                 return;
6782         }
6783
6784         if ((SVAL(req->inbuf,(smb_setup+4)) == LMCAT_SPL)
6785             && (SVAL(req->inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
6786                 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
6787                 if (*ppdata == NULL) {
6788                         reply_nterror(req, NT_STATUS_NO_MEMORY);
6789                         return;
6790                 }
6791                 pdata = *ppdata;
6792
6793                 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
6794                         CAN ACCEPT THIS IN UNICODE. JRA. */
6795
6796                 SSVAL(pdata,0,fsp->rap_print_jobid);                     /* Job number */
6797                 srvstr_push(pdata, req->flags2, pdata + 2,
6798                             global_myname(), 15,
6799                             STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
6800                 srvstr_push(pdata, req->flags2, pdata+18,
6801                             lp_servicename(SNUM(conn)), 13,
6802                             STR_ASCII|STR_TERMINATE); /* Service name */
6803                 send_trans2_replies_new(req, *pparams, 0, *ppdata, 32,
6804                                         max_data_bytes);
6805                 return;
6806         }
6807
6808         DEBUG(2,("Unknown TRANS2_IOCTL\n"));
6809         reply_doserror(req, ERRSRV, ERRerror);
6810 }
6811
6812 /****************************************************************************
6813  Reply to a SMBfindclose (stop trans2 directory search).
6814 ****************************************************************************/
6815
6816 int reply_findclose(connection_struct *conn,
6817                     char *inbuf,char *outbuf,int length,int bufsize)
6818 {
6819         int outsize = 0;
6820         int dptr_num=SVALS(inbuf,smb_vwv0);
6821         START_PROFILE(SMBfindclose);
6822
6823         DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
6824
6825         dptr_close(&dptr_num);
6826
6827         outsize = set_message(inbuf, outbuf,0,0,False);
6828
6829         DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
6830
6831         END_PROFILE(SMBfindclose);
6832         return(outsize);
6833 }
6834
6835 /****************************************************************************
6836  Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
6837 ****************************************************************************/
6838
6839 int reply_findnclose(connection_struct *conn, 
6840                      char *inbuf,char *outbuf,int length,int bufsize)
6841 {
6842         int outsize = 0;
6843         int dptr_num= -1;
6844         START_PROFILE(SMBfindnclose);
6845         
6846         dptr_num = SVAL(inbuf,smb_vwv0);
6847
6848         DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
6849
6850         /* We never give out valid handles for a 
6851            findnotifyfirst - so any dptr_num is ok here. 
6852            Just ignore it. */
6853
6854         outsize = set_message(inbuf, outbuf,0,0,False);
6855
6856         DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
6857
6858         END_PROFILE(SMBfindnclose);
6859         return(outsize);
6860 }
6861
6862 static int handle_trans2(connection_struct *conn, struct smb_request *req,
6863                          struct trans_state *state,
6864                          char *inbuf, char *outbuf, int size, int bufsize)
6865 {
6866         int outsize = -1;
6867
6868         if (Protocol >= PROTOCOL_NT1) {
6869                 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | 0x40); /* IS_LONG_NAME */
6870         }
6871
6872         /* Now we must call the relevant TRANS2 function */
6873         switch(state->call)  {
6874         case TRANSACT2_OPEN:
6875         {
6876                 START_PROFILE(Trans2_open);
6877                 call_trans2open(conn, req,
6878                                 &state->param, state->total_param,
6879                                 &state->data, state->total_data,
6880                                 state->max_data_return);
6881                 END_PROFILE(Trans2_open);
6882                 break;
6883         }
6884
6885         case TRANSACT2_FINDFIRST:
6886         {
6887                 START_PROFILE(Trans2_findfirst);
6888                 call_trans2findfirst(conn, req,
6889                                      &state->param, state->total_param,
6890                                      &state->data, state->total_data,
6891                                      state->max_data_return);
6892                 END_PROFILE(Trans2_findfirst);
6893                 break;
6894         }
6895
6896         case TRANSACT2_FINDNEXT:
6897         {
6898                 START_PROFILE(Trans2_findnext);
6899                 call_trans2findnext(conn, req,
6900                                     &state->param, state->total_param,
6901                                     &state->data, state->total_data,
6902                                     state->max_data_return);
6903                 END_PROFILE(Trans2_findnext);
6904                 break;
6905         }
6906
6907         case TRANSACT2_QFSINFO:
6908         {
6909                 START_PROFILE(Trans2_qfsinfo);
6910                 call_trans2qfsinfo(conn, req,
6911                                    &state->param, state->total_param,
6912                                    &state->data, state->total_data,
6913                                    state->max_data_return);
6914                 END_PROFILE(Trans2_qfsinfo);
6915             break;
6916         }
6917
6918         case TRANSACT2_SETFSINFO:
6919         {
6920                 START_PROFILE(Trans2_setfsinfo);
6921                 call_trans2setfsinfo(conn, req,
6922                                      &state->param, state->total_param,
6923                                      &state->data, state->total_data,
6924                                      state->max_data_return);
6925                 END_PROFILE(Trans2_setfsinfo);
6926                 break;
6927         }
6928
6929         case TRANSACT2_QPATHINFO:
6930         case TRANSACT2_QFILEINFO:
6931         {
6932                 START_PROFILE(Trans2_qpathinfo);
6933                 call_trans2qfilepathinfo(conn, req, state->call,
6934                                          &state->param, state->total_param,
6935                                          &state->data, state->total_data,
6936                                          state->max_data_return);
6937                 END_PROFILE(Trans2_qpathinfo);
6938                 break;
6939         }
6940
6941         case TRANSACT2_SETPATHINFO:
6942         case TRANSACT2_SETFILEINFO:
6943         {
6944                 START_PROFILE(Trans2_setpathinfo);
6945                 call_trans2setfilepathinfo(conn, req, state->call,
6946                                            &state->param, state->total_param,
6947                                            &state->data, state->total_data,
6948                                            state->max_data_return);
6949                 END_PROFILE(Trans2_setpathinfo);
6950                 break;
6951         }
6952
6953         case TRANSACT2_FINDNOTIFYFIRST:
6954         {
6955                 START_PROFILE(Trans2_findnotifyfirst);
6956                 call_trans2findnotifyfirst(conn, req,
6957                                            &state->param, state->total_param,
6958                                            &state->data, state->total_data,
6959                                            state->max_data_return);
6960                 END_PROFILE(Trans2_findnotifyfirst);
6961                 break;
6962         }
6963
6964         case TRANSACT2_FINDNOTIFYNEXT:
6965         {
6966                 START_PROFILE(Trans2_findnotifynext);
6967                 call_trans2findnotifynext(conn, req,
6968                                           &state->param, state->total_param,
6969                                           &state->data, state->total_data,
6970                                           state->max_data_return);
6971                 END_PROFILE(Trans2_findnotifynext);
6972                 break;
6973         }
6974
6975         case TRANSACT2_MKDIR:
6976         {
6977                 START_PROFILE(Trans2_mkdir);
6978                 call_trans2mkdir(conn, req,
6979                                  &state->param, state->total_param,
6980                                  &state->data, state->total_data,
6981                                  state->max_data_return);
6982                 END_PROFILE(Trans2_mkdir);
6983                 break;
6984         }
6985
6986         case TRANSACT2_GET_DFS_REFERRAL:
6987         {
6988                 START_PROFILE(Trans2_get_dfs_referral);
6989                 call_trans2getdfsreferral(conn, req,
6990                                           &state->param, state->total_param,
6991                                           &state->data, state->total_data,
6992                                           state->max_data_return);
6993                 END_PROFILE(Trans2_get_dfs_referral);
6994                 break;
6995         }
6996
6997         case TRANSACT2_IOCTL:
6998         {
6999                 START_PROFILE(Trans2_ioctl);
7000                 call_trans2ioctl(conn, req,
7001                                  &state->param, state->total_param,
7002                                  &state->data, state->total_data,
7003                                  state->max_data_return);
7004                 END_PROFILE(Trans2_ioctl);
7005                 break;
7006         }
7007
7008         default:
7009                 /* Error in request */
7010                 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
7011                 outsize = ERROR_DOS(ERRSRV,ERRerror);
7012         }
7013
7014         return outsize;
7015 }
7016
7017 /****************************************************************************
7018  Reply to a SMBtrans2.
7019  ****************************************************************************/
7020
7021 int reply_trans2(connection_struct *conn, char *inbuf,char *outbuf,
7022                  int size, int bufsize)
7023 {
7024         int outsize = 0;
7025         unsigned int dsoff = SVAL(inbuf, smb_dsoff);
7026         unsigned int dscnt = SVAL(inbuf, smb_dscnt);
7027         unsigned int psoff = SVAL(inbuf, smb_psoff);
7028         unsigned int pscnt = SVAL(inbuf, smb_pscnt);
7029         unsigned int tran_call = SVAL(inbuf, smb_setup0);
7030         struct trans_state *state;
7031         NTSTATUS result;
7032
7033         START_PROFILE(SMBtrans2);
7034
7035         result = allow_new_trans(conn->pending_trans, SVAL(inbuf, smb_mid));
7036         if (!NT_STATUS_IS_OK(result)) {
7037                 DEBUG(2, ("Got invalid trans2 request: %s\n",
7038                           nt_errstr(result)));
7039                 END_PROFILE(SMBtrans2);
7040                 return ERROR_NT(result);
7041         }
7042
7043         if (IS_IPC(conn) && (tran_call != TRANSACT2_OPEN)
7044             && (tran_call != TRANSACT2_GET_DFS_REFERRAL)
7045             && (tran_call != TRANSACT2_QFILEINFO)) {
7046                 END_PROFILE(SMBtrans2);
7047                 return ERROR_DOS(ERRSRV,ERRaccess);
7048         }
7049
7050         if ((state = TALLOC_P(conn->mem_ctx, struct trans_state)) == NULL) {
7051                 DEBUG(0, ("talloc failed\n"));
7052                 END_PROFILE(SMBtrans2);
7053                 return ERROR_NT(NT_STATUS_NO_MEMORY);
7054         }
7055
7056         state->cmd = SMBtrans2;
7057
7058         state->mid = SVAL(inbuf, smb_mid);
7059         state->vuid = SVAL(inbuf, smb_uid);
7060         state->setup_count = SVAL(inbuf, smb_suwcnt);
7061         state->setup = NULL;
7062         state->total_param = SVAL(inbuf, smb_tpscnt);
7063         state->param = NULL;
7064         state->total_data =  SVAL(inbuf, smb_tdscnt);
7065         state->data = NULL;
7066         state->max_param_return = SVAL(inbuf, smb_mprcnt);
7067         state->max_data_return  = SVAL(inbuf, smb_mdrcnt);
7068         state->max_setup_return = SVAL(inbuf, smb_msrcnt);
7069         state->close_on_completion = BITSETW(inbuf+smb_vwv5,0);
7070         state->one_way = BITSETW(inbuf+smb_vwv5,1);
7071
7072         state->call = tran_call;
7073
7074         /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
7075            is so as a sanity check */
7076         if (state->setup_count != 1) {
7077                 /*
7078                  * Need to have rc=0 for ioctl to get job id for OS/2.
7079                  *  Network printing will fail if function is not successful.
7080                  *  Similar function in reply.c will be used if protocol
7081                  *  is LANMAN1.0 instead of LM1.2X002.
7082                  *  Until DosPrintSetJobInfo with PRJINFO3 is supported,
7083                  *  outbuf doesn't have to be set(only job id is used).
7084                  */
7085                 if ( (state->setup_count == 4) && (tran_call == TRANSACT2_IOCTL) &&
7086                                 (SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
7087                                 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
7088                         DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
7089                 } else {
7090                         DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
7091                         DEBUG(2,("Transaction is %d\n",tran_call));
7092                         TALLOC_FREE(state);
7093                         END_PROFILE(SMBtrans2);
7094                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
7095                 }
7096         }
7097
7098         if ((dscnt > state->total_data) || (pscnt > state->total_param))
7099                 goto bad_param;
7100
7101         if (state->total_data) {
7102                 /* Can't use talloc here, the core routines do realloc on the
7103                  * params and data. */
7104                 state->data = (char *)SMB_MALLOC(state->total_data);
7105                 if (state->data == NULL) {
7106                         DEBUG(0,("reply_trans2: data malloc fail for %u "
7107                                  "bytes !\n", (unsigned int)state->total_data));
7108                         TALLOC_FREE(state);
7109                         END_PROFILE(SMBtrans2);
7110                         return(ERROR_DOS(ERRDOS,ERRnomem));
7111                 }
7112                 if ((dsoff+dscnt < dsoff) || (dsoff+dscnt < dscnt))
7113                         goto bad_param;
7114                 if ((smb_base(inbuf)+dsoff+dscnt > inbuf + size) ||
7115                     (smb_base(inbuf)+dsoff+dscnt < smb_base(inbuf)))
7116                         goto bad_param;
7117
7118                 memcpy(state->data,smb_base(inbuf)+dsoff,dscnt);
7119         }
7120
7121         if (state->total_param) {
7122                 /* Can't use talloc here, the core routines do realloc on the
7123                  * params and data. */
7124                 state->param = (char *)SMB_MALLOC(state->total_param);
7125                 if (state->param == NULL) {
7126                         DEBUG(0,("reply_trans: param malloc fail for %u "
7127                                  "bytes !\n", (unsigned int)state->total_param));
7128                         SAFE_FREE(state->data);
7129                         TALLOC_FREE(state);
7130                         END_PROFILE(SMBtrans2);
7131                         return(ERROR_DOS(ERRDOS,ERRnomem));
7132                 } 
7133                 if ((psoff+pscnt < psoff) || (psoff+pscnt < pscnt))
7134                         goto bad_param;
7135                 if ((smb_base(inbuf)+psoff+pscnt > inbuf + size) ||
7136                     (smb_base(inbuf)+psoff+pscnt < smb_base(inbuf)))
7137                         goto bad_param;
7138
7139                 memcpy(state->param,smb_base(inbuf)+psoff,pscnt);
7140         }
7141
7142         state->received_data  = dscnt;
7143         state->received_param = pscnt;
7144
7145         if ((state->received_param == state->total_param) &&
7146             (state->received_data == state->total_data)) {
7147
7148                 struct smb_request *req;
7149
7150                 if (!(req = talloc(tmp_talloc_ctx(), struct smb_request))) {
7151                         END_PROFILE(SMBtrans2);
7152                         return ERROR_NT(NT_STATUS_NO_MEMORY);
7153                 }
7154
7155                 init_smb_request(req, (uint8 *)inbuf);
7156
7157                 outsize = handle_trans2(conn, req, state, inbuf, outbuf,
7158                                         size, bufsize);
7159                 if (req->outbuf != NULL) {
7160                         outsize = smb_len(req->outbuf) + 4;
7161                         memcpy(outbuf, req->outbuf, outsize);
7162                 }
7163                 TALLOC_FREE(req);
7164                 SAFE_FREE(state->data);
7165                 SAFE_FREE(state->param);
7166                 TALLOC_FREE(state);
7167                 END_PROFILE(SMBtrans2);
7168                 return outsize;
7169         }
7170
7171         DLIST_ADD(conn->pending_trans, state);
7172
7173         /* We need to send an interim response then receive the rest
7174            of the parameter/data bytes */
7175         outsize = set_message(inbuf, outbuf,0,0,False);
7176         show_msg(outbuf);
7177         END_PROFILE(SMBtrans2);
7178         return outsize;
7179
7180   bad_param:
7181
7182         DEBUG(0,("reply_trans2: invalid trans parameters\n"));
7183         SAFE_FREE(state->data);
7184         SAFE_FREE(state->param);
7185         TALLOC_FREE(state);
7186         END_PROFILE(SMBtrans2);
7187         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
7188 }
7189
7190
7191 /****************************************************************************
7192  Reply to a SMBtranss2
7193  ****************************************************************************/
7194
7195 int reply_transs2(connection_struct *conn,
7196                   char *inbuf,char *outbuf,int size,int bufsize)
7197 {
7198         int outsize = 0;
7199         unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
7200         struct trans_state *state;
7201         struct smb_request *req;
7202
7203         START_PROFILE(SMBtranss2);
7204
7205         show_msg(inbuf);
7206
7207         for (state = conn->pending_trans; state != NULL;
7208              state = state->next) {
7209                 if (state->mid == SVAL(inbuf,smb_mid)) {
7210                         break;
7211                 }
7212         }
7213
7214         if ((state == NULL) || (state->cmd != SMBtrans2)) {
7215                 END_PROFILE(SMBtranss2);
7216                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
7217         }
7218
7219         /* Revise state->total_param and state->total_data in case they have
7220            changed downwards */
7221
7222         if (SVAL(inbuf, smb_tpscnt) < state->total_param)
7223                 state->total_param = SVAL(inbuf, smb_tpscnt);
7224         if (SVAL(inbuf, smb_tdscnt) < state->total_data)
7225                 state->total_data = SVAL(inbuf, smb_tdscnt);
7226
7227         pcnt = SVAL(inbuf, smb_spscnt);
7228         poff = SVAL(inbuf, smb_spsoff);
7229         pdisp = SVAL(inbuf, smb_spsdisp);
7230
7231         dcnt = SVAL(inbuf, smb_sdscnt);
7232         doff = SVAL(inbuf, smb_sdsoff);
7233         ddisp = SVAL(inbuf, smb_sdsdisp);
7234
7235         state->received_param += pcnt;
7236         state->received_data += dcnt;
7237                 
7238         if ((state->received_data > state->total_data) ||
7239             (state->received_param > state->total_param))
7240                 goto bad_param;
7241
7242         if (pcnt) {
7243                 if (pdisp+pcnt > state->total_param)
7244                         goto bad_param;
7245                 if ((pdisp+pcnt < pdisp) || (pdisp+pcnt < pcnt))
7246                         goto bad_param;
7247                 if (pdisp > state->total_param)
7248                         goto bad_param;
7249                 if ((smb_base(inbuf) + poff + pcnt > inbuf + size) ||
7250                     (smb_base(inbuf) + poff + pcnt < smb_base(inbuf)))
7251                         goto bad_param;
7252                 if (state->param + pdisp < state->param)
7253                         goto bad_param;
7254
7255                 memcpy(state->param+pdisp,smb_base(inbuf)+poff,
7256                        pcnt);
7257         }
7258
7259         if (dcnt) {
7260                 if (ddisp+dcnt > state->total_data)
7261                         goto bad_param;
7262                 if ((ddisp+dcnt < ddisp) || (ddisp+dcnt < dcnt))
7263                         goto bad_param;
7264                 if (ddisp > state->total_data)
7265                         goto bad_param;
7266                 if ((smb_base(inbuf) + doff + dcnt > inbuf + size) ||
7267                     (smb_base(inbuf) + doff + dcnt < smb_base(inbuf)))
7268                         goto bad_param;
7269                 if (state->data + ddisp < state->data)
7270                         goto bad_param;
7271
7272                 memcpy(state->data+ddisp, smb_base(inbuf)+doff,
7273                        dcnt);      
7274         }
7275
7276         if ((state->received_param < state->total_param) ||
7277             (state->received_data < state->total_data)) {
7278                 END_PROFILE(SMBtranss2);
7279                 return -1;
7280         }
7281
7282         /* construct_reply_common has done us the favor to pre-fill the
7283          * command field with SMBtranss2 which is wrong :-)
7284          */
7285         SCVAL(outbuf,smb_com,SMBtrans2);
7286
7287         if (!(req = talloc(tmp_talloc_ctx(), struct smb_request))) {
7288                 END_PROFILE(SMBtranss2);
7289                 return ERROR_NT(NT_STATUS_NO_MEMORY);
7290         }
7291
7292         init_smb_request(req, (uint8 *)inbuf);
7293
7294         outsize = handle_trans2(conn, req, state, inbuf, outbuf, size,
7295                                 bufsize);
7296         if (req->outbuf != NULL) {
7297                 outsize = smb_len(req->outbuf) + 4;
7298                 memcpy(outbuf, req->outbuf, outsize);
7299         }
7300         TALLOC_FREE(req);
7301
7302         DLIST_REMOVE(conn->pending_trans, state);
7303         SAFE_FREE(state->data);
7304         SAFE_FREE(state->param);
7305         TALLOC_FREE(state);
7306
7307         if (outsize == 0) {
7308                 END_PROFILE(SMBtranss2);
7309                 return(ERROR_DOS(ERRSRV,ERRnosupport));
7310         }
7311         
7312         END_PROFILE(SMBtranss2);
7313         return(outsize);
7314
7315   bad_param:
7316
7317         DEBUG(0,("reply_transs2: invalid trans parameters\n"));
7318         DLIST_REMOVE(conn->pending_trans, state);
7319         SAFE_FREE(state->data);
7320         SAFE_FREE(state->param);
7321         TALLOC_FREE(state);
7322         END_PROFILE(SMBtranss2);
7323         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
7324 }