r6225: get rid of warnings from my compiler about nested externs
[vlendec/samba-autobuild/.git] / source3 / smbd / trans2.c
1 /* 
2    Unix SMB/CIFS implementation.
3    SMB transaction2 handling
4    Copyright (C) Jeremy Allison                 1994-2003
5    Copyright (C) Stefan (metze) Metzmacher      2003
6
7    Extensively modified by Andrew Tridgell, 1995
8
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 2 of the License, or
12    (at your option) any later version.
13    
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18    
19    You should have received a copy of the GNU General Public License
20    along with this program; if not, write to the Free Software
21    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 */
23
24 #include "includes.h"
25
26 extern int max_send;
27 extern enum protocol_types Protocol;
28 extern int smb_read_error;
29 extern int global_oplock_break;
30 extern uint32 global_client_caps;
31 extern struct current_user current_user;
32
33 #define get_file_size(sbuf) ((sbuf).st_size)
34 #define DIR_ENTRY_SAFETY_MARGIN 4096
35
36 /********************************************************************
37  Roundup a value to the nearest allocation roundup size boundary.
38  Only do this for Windows clients.
39 ********************************************************************/
40
41 SMB_BIG_UINT smb_roundup(connection_struct *conn, SMB_BIG_UINT val)
42 {
43         SMB_BIG_UINT rval = lp_allocation_roundup_size(SNUM(conn));
44
45         /* Only roundup for Windows clients. */
46         enum remote_arch_types ra_type = get_remote_arch();
47         if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
48                 val = SMB_ROUNDUP(val,rval);
49         }
50         return val;
51 }
52
53 /********************************************************************
54  Given a stat buffer return the allocated size on disk, taking into
55  account sparse files.
56 ********************************************************************/
57
58 SMB_BIG_UINT get_allocation_size(connection_struct *conn, files_struct *fsp, SMB_STRUCT_STAT *sbuf)
59 {
60         SMB_BIG_UINT ret;
61
62         if(S_ISDIR(sbuf->st_mode)) {
63                 return 0;
64         }
65
66 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
67         ret = (SMB_BIG_UINT)STAT_ST_BLOCKSIZE * (SMB_BIG_UINT)sbuf->st_blocks;
68 #else
69         ret = (SMB_BIG_UINT)get_file_size(*sbuf);
70 #endif
71
72         if (fsp && fsp->initial_allocation_size)
73                 ret = MAX(ret,fsp->initial_allocation_size);
74
75         return smb_roundup(conn, ret);
76 }
77
78 /****************************************************************************
79  Utility functions for dealing with extended attributes.
80 ****************************************************************************/
81
82 static const char *prohibited_ea_names[] = {
83         SAMBA_POSIX_INHERITANCE_EA_NAME,
84         SAMBA_XATTR_DOS_ATTRIB,
85         NULL
86 };
87
88 /****************************************************************************
89  Refuse to allow clients to overwrite our private xattrs.
90 ****************************************************************************/
91
92 static BOOL samba_private_attr_name(const char *unix_ea_name)
93 {
94         int i;
95
96         for (i = 0; prohibited_ea_names[i]; i++) {
97                 if (strequal( prohibited_ea_names[i], unix_ea_name))
98                         return True;
99         }
100         return False;
101 }
102
103 /****************************************************************************
104  Get one EA value. Fill in a struct ea_struct.
105 ****************************************************************************/
106
107 static BOOL get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
108                                 const char *fname, char *ea_name, struct ea_struct *pea)
109 {
110         /* Get the value of this xattr. Max size is 64k. */
111         size_t attr_size = 256;
112         char *val = NULL;
113         ssize_t sizeret;
114
115  again:
116
117         val = TALLOC_REALLOC_ARRAY(mem_ctx, val, char, attr_size);
118         if (!val) {
119                 return False;
120         }
121
122         if (fsp && fsp->fd != -1) {
123                 sizeret = SMB_VFS_FGETXATTR(fsp, fsp->fd, ea_name, val, attr_size);
124         } else {
125                 sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
126         }
127
128         if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
129                 attr_size = 65536;
130                 goto again;
131         }
132
133         if (sizeret == -1) {
134                 return False;
135         }
136
137         DEBUG(10,("get_ea_value: EA %s is of length %d: ", ea_name, sizeret));
138         dump_data(10, val, sizeret);
139
140         pea->flags = 0;
141         if (strnequal(ea_name, "user.", 5)) {
142                 pea->name = &ea_name[5];
143         } else {
144                 pea->name = ea_name;
145         }
146         pea->value.data = (unsigned char *)val;
147         pea->value.length = (size_t)sizeret;
148         return True;
149 }
150
151 /****************************************************************************
152  Return a linked list of the total EA's. Plus the total size
153 ****************************************************************************/
154
155 static struct ea_list *get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
156                                         const char *fname, size_t *pea_total_len)
157 {
158         /* Get a list of all xattrs. Max namesize is 64k. */
159         size_t ea_namelist_size = 1024;
160         char *ea_namelist;
161         char *p;
162         ssize_t sizeret;
163         int i;
164         struct ea_list *ea_list_head = NULL;
165
166         *pea_total_len = 0;
167
168         if (!lp_ea_support(SNUM(conn))) {
169                 return NULL;
170         }
171
172         for (i = 0, ea_namelist = TALLOC(mem_ctx, ea_namelist_size); i < 6;
173                         ea_namelist = TALLOC_REALLOC_ARRAY(mem_ctx, ea_namelist, char, ea_namelist_size), i++) {
174                 if (fsp && fsp->fd != -1) {
175                         sizeret = SMB_VFS_FLISTXATTR(fsp, fsp->fd, ea_namelist, ea_namelist_size);
176                 } else {
177                         sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist, ea_namelist_size);
178                 }
179
180                 if (sizeret == -1 && errno == ERANGE) {
181                         ea_namelist_size *= 2;
182                 } else {
183                         break;
184                 }
185         }
186
187         if (sizeret == -1)
188                 return NULL;
189
190         DEBUG(10,("get_ea_list_from_file: ea_namelist size = %d\n", sizeret ));
191
192         if (sizeret) {
193                 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p) + 1) {
194                         struct ea_list *listp, *tmp;
195
196                         if (strnequal(p, "system.", 7) || samba_private_attr_name(p))
197                                 continue;
198                 
199                         listp = TALLOC_P(mem_ctx, struct ea_list);
200                         if (!listp)
201                                 return NULL;
202
203                         if (!get_ea_value(mem_ctx, conn, fsp, fname, p, &listp->ea)) {
204                                 return NULL;
205                         }
206
207                         {
208                                 fstring dos_ea_name;
209                                 push_ascii_fstring(dos_ea_name, listp->ea.name);
210                                 *pea_total_len += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
211                                 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len = %u\n",
212                                         *pea_total_len, dos_ea_name,
213                                         (unsigned int)listp->ea.value.length ));
214                         }
215                         DLIST_ADD_END(ea_list_head, listp, tmp);
216                 }
217                 /* Add on 4 for total length. */
218                 if (*pea_total_len) {
219                         *pea_total_len += 4;
220                 }
221         }
222
223         DEBUG(10,("get_ea_list_from_file: total_len = %u\n", *pea_total_len));
224         return ea_list_head;
225 }
226
227 /****************************************************************************
228  Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
229  that was filled.
230 ****************************************************************************/
231
232 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
233         connection_struct *conn, struct ea_list *ea_list)
234 {
235         unsigned int ret_data_size = 4;
236         char *p = pdata;
237
238         SMB_ASSERT(total_data_size >= 4);
239
240         if (!lp_ea_support(SNUM(conn))) {
241                 SIVAL(pdata,4,0);
242                 return 4;
243         }
244
245         for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
246                 size_t dos_namelen;
247                 fstring dos_ea_name;
248                 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
249                 dos_namelen = strlen(dos_ea_name);
250                 if (dos_namelen > 255 || dos_namelen == 0) {
251                         break;
252                 }
253                 if (ea_list->ea.value.length > 65535) {
254                         break;
255                 }
256                 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
257                         break;
258                 }
259
260                 /* We know we have room. */
261                 SCVAL(p,0,ea_list->ea.flags);
262                 SCVAL(p,1,dos_namelen);
263                 SSVAL(p,2,ea_list->ea.value.length);
264                 fstrcpy(p+4, dos_ea_name);
265                 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
266
267                 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
268                 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
269         }
270
271         ret_data_size = PTR_DIFF(p, pdata);
272         DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
273         SIVAL(pdata,0,ret_data_size);
274         return ret_data_size;
275 }
276
277 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const char *fname)
278 {
279         size_t total_ea_len = 0;
280         TALLOC_CTX *mem_ctx = NULL;
281
282         if (!lp_ea_support(SNUM(conn))) {
283                 return 0;
284         }
285         mem_ctx = talloc_init("estimate_ea_size");
286         (void)get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
287         talloc_destroy(mem_ctx);
288         return total_ea_len;
289 }
290
291 /****************************************************************************
292  Ensure the EA name is case insensitive by matching any existing EA name.
293 ****************************************************************************/
294
295 static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
296 {
297         size_t total_ea_len;
298         TALLOC_CTX *mem_ctx = talloc_init("canonicalize_ea_name");
299         struct ea_list *ea_list = get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
300
301         for (; ea_list; ea_list = ea_list->next) {
302                 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
303                         DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
304                                 &unix_ea_name[5], ea_list->ea.name));
305                         safe_strcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-6);
306                         break;
307                 }
308         }
309         talloc_destroy(mem_ctx);
310 }
311
312 /****************************************************************************
313  Set or delete an extended attribute.
314 ****************************************************************************/
315
316 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp, const char *fname, struct ea_list *ea_list)
317 {
318         if (!lp_ea_support(SNUM(conn))) {
319                 return NT_STATUS_EAS_NOT_SUPPORTED;
320         }
321
322         for (;ea_list; ea_list = ea_list->next) {
323                 int ret;
324                 fstring unix_ea_name;
325
326                 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
327                 fstrcat(unix_ea_name, ea_list->ea.name);
328
329                 canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
330
331                 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, ea_list->ea.value.length));
332
333                 if (samba_private_attr_name(unix_ea_name)) {
334                         DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
335                         return NT_STATUS_ACCESS_DENIED;
336                 }
337
338                 if (ea_list->ea.value.length == 0) {
339                         /* Remove the attribute. */
340                         if (fsp && (fsp->fd != -1)) {
341                                 DEBUG(10,("set_ea: deleting ea name %s on file %s by file descriptor.\n",
342                                         unix_ea_name, fsp->fsp_name));
343                                 ret = SMB_VFS_FREMOVEXATTR(fsp, fsp->fd, unix_ea_name);
344                         } else {
345                                 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
346                                         unix_ea_name, fname));
347                                 ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
348                         }
349 #ifdef ENOATTR
350                         /* Removing a non existent attribute always succeeds. */
351                         if (ret == -1 && errno == ENOATTR) {
352                                 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
353                                                 unix_ea_name));
354                                 ret = 0;
355                         }
356 #endif
357                 } else {
358                         if (fsp && (fsp->fd != -1)) {
359                                 DEBUG(10,("set_ea: setting ea name %s on file %s by file descriptor.\n",
360                                         unix_ea_name, fsp->fsp_name));
361                                 ret = SMB_VFS_FSETXATTR(fsp, fsp->fd, unix_ea_name,
362                                                         ea_list->ea.value.data, ea_list->ea.value.length, 0);
363                         } else {
364                                 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
365                                         unix_ea_name, fname));
366                                 ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name,
367                                                         ea_list->ea.value.data, ea_list->ea.value.length, 0);
368                         }
369                 }
370
371                 if (ret == -1) {
372 #ifdef ENOTSUP
373                         if (errno == ENOTSUP) {
374                                 return NT_STATUS_EAS_NOT_SUPPORTED;
375                         }
376 #endif
377                         return map_nt_error_from_unix(errno);
378                 }
379
380         }
381         return NT_STATUS_OK;
382 }
383 /****************************************************************************
384  Read a list of EA names from an incoming data buffer. Create an ea_list with them.
385 ****************************************************************************/
386
387 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
388 {
389         struct ea_list *ea_list_head = NULL;
390         size_t offset = 0;
391
392         while (offset + 2 < data_size) {
393                 struct ea_list *tmp;
394                 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
395                 unsigned int namelen = CVAL(pdata,offset);
396
397                 offset++; /* Go past the namelen byte. */
398
399                 /* integer wrap paranioa. */
400                 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
401                                 (offset > data_size) || (namelen > data_size) ||
402                                 (offset + namelen >= data_size)) {
403                         break;
404                 }
405                 /* Ensure the name is null terminated. */
406                 if (pdata[offset + namelen] != '\0') {
407                         return NULL;
408                 }
409                 pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset]);
410                 if (!eal->ea.name) {
411                         return NULL;
412                 }
413
414                 offset += (namelen + 1); /* Go past the name + terminating zero. */
415                 DLIST_ADD_END(ea_list_head, eal, tmp);
416                 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
417         }
418
419         return ea_list_head;
420 }
421
422 /****************************************************************************
423  Read one EA list entry from the buffer.
424 ****************************************************************************/
425
426 struct ea_list *read_ea_list_entry(TALLOC_CTX *ctx, const char *pdata, size_t data_size, size_t *pbytes_used)
427 {
428         struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
429         uint16 val_len;
430         unsigned int namelen;
431
432         if (!eal) {
433                 return NULL;
434         }
435
436         if (data_size < 6) {
437                 return NULL;
438         }
439
440         eal->ea.flags = CVAL(pdata,0);
441         namelen = CVAL(pdata,1);
442         val_len = SVAL(pdata,2);
443
444         if (4 + namelen + 1 + val_len > data_size) {
445                 return NULL;
446         }
447
448         /* Ensure the name is null terminated. */
449         if (pdata[namelen + 4] != '\0') {
450                 return NULL;
451         }
452         pull_ascii_talloc(ctx, &eal->ea.name, pdata + 4);
453         if (!eal->ea.name) {
454                 return NULL;
455         }
456
457         eal->ea.value = data_blob(NULL, (size_t)val_len + 1);
458         if (!eal->ea.value.data) {
459                 return NULL;
460         }
461
462         memcpy(eal->ea.value.data, pdata + 4 + namelen + 1, val_len);
463
464         /* Ensure we're null terminated just in case we print the value. */
465         eal->ea.value.data[val_len] = '\0';
466         /* But don't count the null. */
467         eal->ea.value.length--;
468
469         if (pbytes_used) {
470                 *pbytes_used = 4 + namelen + 1 + val_len;
471         }
472
473         DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal->ea.name));
474         dump_data(10, eal->ea.value.data, eal->ea.value.length);
475
476         return eal;
477 }
478
479 /****************************************************************************
480  Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
481 ****************************************************************************/
482
483 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
484 {
485         struct ea_list *ea_list_head = NULL;
486         size_t offset = 0;
487         size_t bytes_used = 0;
488
489         while (offset < data_size) {
490                 struct ea_list *tmp;
491                 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
492
493                 if (!eal) {
494                         return NULL;
495                 }
496
497                 DLIST_ADD_END(ea_list_head, eal, tmp);
498                 offset += bytes_used;
499         }
500
501         return ea_list_head;
502 }
503
504 /****************************************************************************
505  Count the total EA size needed.
506 ****************************************************************************/
507
508 static size_t ea_list_size(struct ea_list *ealist)
509 {
510         fstring dos_ea_name;
511         struct ea_list *listp;
512         size_t ret = 0;
513
514         for (listp = ealist; listp; listp = listp->next) {
515                 push_ascii_fstring(dos_ea_name, listp->ea.name);
516                 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
517         }
518         /* Add on 4 for total length. */
519         if (ret) {
520                 ret += 4;
521         }
522
523         return ret;
524 }
525
526 /****************************************************************************
527  Return a union of EA's from a file list and a list of names.
528  The TALLOC context for the two lists *MUST* be identical as we steal
529  memory from one list to add to another. JRA.
530 ****************************************************************************/
531
532 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
533 {
534         struct ea_list *nlistp, *flistp;
535
536         for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
537                 for (flistp = file_list; flistp; flistp = flistp->next) {
538                         if (strequal(nlistp->ea.name, flistp->ea.name)) {
539                                 break;
540                         }
541                 }
542
543                 if (flistp) {
544                         /* Copy the data from this entry. */
545                         nlistp->ea.flags = flistp->ea.flags;
546                         nlistp->ea.value = flistp->ea.value;
547                 } else {
548                         /* Null entry. */
549                         nlistp->ea.flags = 0;
550                         ZERO_STRUCT(nlistp->ea.value);
551                 }
552         }
553
554         *total_ea_len = ea_list_size(name_list);
555         return name_list;
556 }
557
558 /****************************************************************************
559   Send the required number of replies back.
560   We assume all fields other than the data fields are
561   set correctly for the type of call.
562   HACK ! Always assumes smb_setup field is zero.
563 ****************************************************************************/
564
565 static int send_trans2_replies(char *outbuf,
566                         int bufsize,
567                         char *params, 
568                         int paramsize,
569                         char *pdata,
570                         int datasize)
571 {
572         /* As we are using a protocol > LANMAN1 then the max_send
573          variable must have been set in the sessetupX call.
574          This takes precedence over the max_xmit field in the
575          global struct. These different max_xmit variables should
576          be merged as this is now too confusing */
577
578         int data_to_send = datasize;
579         int params_to_send = paramsize;
580         int useable_space;
581         char *pp = params;
582         char *pd = pdata;
583         int params_sent_thistime, data_sent_thistime, total_sent_thistime;
584         int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
585         int data_alignment_offset = 0;
586
587         /* Initially set the wcnt area to be 10 - this is true for all trans2 replies */
588         
589         set_message(outbuf,10,0,True);
590
591         /* If there genuinely are no parameters or data to send just send the empty packet */
592
593         if(params_to_send == 0 && data_to_send == 0) {
594                 if (!send_smb(smbd_server_fd(),outbuf))
595                         exit_server("send_trans2_replies: send_smb failed.");
596                 return 0;
597         }
598
599         /* When sending params and data ensure that both are nicely aligned */
600         /* Only do this alignment when there is also data to send - else
601                 can cause NT redirector problems. */
602
603         if (((params_to_send % 4) != 0) && (data_to_send != 0))
604                 data_alignment_offset = 4 - (params_to_send % 4);
605
606         /* Space is bufsize minus Netbios over TCP header minus SMB header */
607         /* The alignment_offset is to align the param bytes on an even byte
608                 boundary. NT 4.0 Beta needs this to work correctly. */
609
610         useable_space = bufsize - ((smb_buf(outbuf)+ alignment_offset+data_alignment_offset) - outbuf);
611
612         /* useable_space can never be more than max_send minus the alignment offset. */
613
614         useable_space = MIN(useable_space, max_send - (alignment_offset+data_alignment_offset));
615
616         while (params_to_send || data_to_send) {
617                 /* Calculate whether we will totally or partially fill this packet */
618
619                 total_sent_thistime = params_to_send + data_to_send + alignment_offset + data_alignment_offset;
620
621                 /* We can never send more than useable_space */
622                 /*
623                  * Note that 'useable_space' does not include the alignment offsets,
624                  * but we must include the alignment offsets in the calculation of
625                  * the length of the data we send over the wire, as the alignment offsets
626                  * are sent here. Fix from Marc_Jacobsen@hp.com.
627                  */
628
629                 total_sent_thistime = MIN(total_sent_thistime, useable_space+ alignment_offset + data_alignment_offset);
630
631                 set_message(outbuf, 10, total_sent_thistime, True);
632
633                 /* Set total params and data to be sent */
634                 SSVAL(outbuf,smb_tprcnt,paramsize);
635                 SSVAL(outbuf,smb_tdrcnt,datasize);
636
637                 /* Calculate how many parameters and data we can fit into
638                  * this packet. Parameters get precedence
639                  */
640
641                 params_sent_thistime = MIN(params_to_send,useable_space);
642                 data_sent_thistime = useable_space - params_sent_thistime;
643                 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
644
645                 SSVAL(outbuf,smb_prcnt, params_sent_thistime);
646
647                 /* smb_proff is the offset from the start of the SMB header to the
648                         parameter bytes, however the first 4 bytes of outbuf are
649                         the Netbios over TCP header. Thus use smb_base() to subtract
650                         them from the calculation */
651
652                 SSVAL(outbuf,smb_proff,((smb_buf(outbuf)+alignment_offset) - smb_base(outbuf)));
653
654                 if(params_sent_thistime == 0)
655                         SSVAL(outbuf,smb_prdisp,0);
656                 else
657                         /* Absolute displacement of param bytes sent in this packet */
658                         SSVAL(outbuf,smb_prdisp,pp - params);
659
660                 SSVAL(outbuf,smb_drcnt, data_sent_thistime);
661                 if(data_sent_thistime == 0) {
662                         SSVAL(outbuf,smb_droff,0);
663                         SSVAL(outbuf,smb_drdisp, 0);
664                 } else {
665                         /* The offset of the data bytes is the offset of the
666                                 parameter bytes plus the number of parameters being sent this time */
667                         SSVAL(outbuf,smb_droff,((smb_buf(outbuf)+alignment_offset) - 
668                                 smb_base(outbuf)) + params_sent_thistime + data_alignment_offset);
669                         SSVAL(outbuf,smb_drdisp, pd - pdata);
670                 }
671
672                 /* Copy the param bytes into the packet */
673
674                 if(params_sent_thistime)
675                         memcpy((smb_buf(outbuf)+alignment_offset),pp,params_sent_thistime);
676
677                 /* Copy in the data bytes */
678                 if(data_sent_thistime)
679                         memcpy(smb_buf(outbuf)+alignment_offset+params_sent_thistime+
680                                 data_alignment_offset,pd,data_sent_thistime);
681
682                 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
683                         params_sent_thistime, data_sent_thistime, useable_space));
684                 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
685                         params_to_send, data_to_send, paramsize, datasize));
686
687                 /* Send the packet */
688                 if (!send_smb(smbd_server_fd(),outbuf))
689                         exit_server("send_trans2_replies: send_smb failed.");
690
691                 pp += params_sent_thistime;
692                 pd += data_sent_thistime;
693
694                 params_to_send -= params_sent_thistime;
695                 data_to_send -= data_sent_thistime;
696
697                 /* Sanity check */
698                 if(params_to_send < 0 || data_to_send < 0) {
699                         DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
700                                 params_to_send, data_to_send));
701                         return -1;
702                 }
703         }
704
705         return 0;
706 }
707
708 /****************************************************************************
709  Reply to a TRANSACT2_OPEN.
710 ****************************************************************************/
711
712 static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, int bufsize,  
713                                 char **pparams, int total_params, char **ppdata, int total_data,
714                                 unsigned int max_data_bytes)
715 {
716         char *params = *pparams;
717         char *pdata = *ppdata;
718         int16 open_mode;
719         int16 open_attr;
720         BOOL oplock_request;
721 #if 0
722         BOOL return_additional_info;
723         int16 open_sattr;
724         time_t open_time;
725 #endif
726         int16 open_ofun;
727         int32 open_size;
728         char *pname;
729         pstring fname;
730         SMB_OFF_T size=0;
731         int fmode=0,mtime=0,rmode;
732         SMB_INO_T inode = 0;
733         SMB_STRUCT_STAT sbuf;
734         int smb_action = 0;
735         BOOL bad_path = False;
736         files_struct *fsp;
737         TALLOC_CTX *ctx = NULL;
738         struct ea_list *ea_list = NULL;
739         uint16 flags = 0;
740         NTSTATUS status;
741
742         /*
743          * Ensure we have enough parameters to perform the operation.
744          */
745
746         if (total_params < 29) {
747                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
748         }
749
750         flags = SVAL(params, 0);
751         open_mode = SVAL(params, 2);
752         open_attr = SVAL(params,6);
753         oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
754         if (oplock_request) {
755                 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
756         }
757
758 #if 0
759         return_additional_info = BITSETW(params,0);
760         open_sattr = SVAL(params, 4);
761         open_time = make_unix_date3(params+8);
762 #endif
763         open_ofun = SVAL(params,12);
764         open_size = IVAL(params,14);
765         pname = &params[28];
766
767         if (IS_IPC(conn))
768                 return(ERROR_DOS(ERRSRV,ERRaccess));
769
770         srvstr_get_path(inbuf, fname, pname, sizeof(fname), -1, STR_TERMINATE, &status, False);
771         if (!NT_STATUS_IS_OK(status)) {
772                 return ERROR_NT(status);
773         }
774
775         DEBUG(3,("call_trans2open %s mode=%d attr=%d ofun=%d size=%d\n",
776                 fname,open_mode, open_attr, open_ofun, open_size));
777
778         /* XXXX we need to handle passed times, sattr and flags */
779
780         unix_convert(fname,conn,0,&bad_path,&sbuf);
781         if (bad_path) {
782                 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
783         }
784     
785         if (!check_name(fname,conn)) {
786                 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
787         }
788
789         /* Strange open mode mapping. */
790         if (open_ofun == 0) {
791                 if (GET_OPEN_MODE(open_mode) == DOS_OPEN_EXEC) {
792                         open_ofun = FILE_EXISTS_FAIL | FILE_CREATE_IF_NOT_EXIST;
793                 }
794         }
795
796         /* Any data in this call is an EA list. */
797         if (total_data && !lp_ea_support(SNUM(conn))) {
798                 return ERROR_NT(NT_STATUS_EAS_NOT_SUPPORTED);
799         }
800
801         if (total_data) {
802                 if (total_data < 10) {
803                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
804                 }
805
806                 if (IVAL(pdata,0) > total_data) {
807                         DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
808                                 IVAL(pdata,0), (unsigned int)total_data));
809                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
810                 }
811
812                 ctx = talloc_init("TRANS2_OPEN_SET_EA");
813                 if (!ctx) {
814                         return ERROR_NT(NT_STATUS_NO_MEMORY);
815                 }
816                 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
817                 if (!ea_list) {
818                         talloc_destroy(ctx);
819                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
820                 }
821         }
822
823         fsp = open_file_shared(conn,fname,&sbuf,open_mode,open_ofun,(uint32)open_attr,
824                 oplock_request, &rmode,&smb_action);
825       
826         if (!fsp) {
827                 talloc_destroy(ctx);
828                 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
829                         /* We have re-scheduled this call. */
830                         return -1;
831                 }
832                 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
833         }
834
835         size = get_file_size(sbuf);
836         fmode = dos_mode(conn,fname,&sbuf);
837         mtime = sbuf.st_mtime;
838         inode = sbuf.st_ino;
839         if (fmode & aDIR) {
840                 talloc_destroy(ctx);
841                 close_file(fsp,False);
842                 return(ERROR_DOS(ERRDOS,ERRnoaccess));
843         }
844
845         if (total_data && smb_action == FILE_WAS_CREATED) {
846                 status = set_ea(conn, fsp, fname, ea_list);
847                 talloc_destroy(ctx);
848                 if (!NT_STATUS_IS_OK(status)) {
849                         close_file(fsp,False);
850                         return ERROR_NT(status);
851                 }
852         }
853
854         /* Realloc the size of parameters and data we will return */
855         params = SMB_REALLOC(*pparams, 30);
856         if( params == NULL ) {
857                 return ERROR_NT(NT_STATUS_NO_MEMORY);
858         }
859         *pparams = params;
860
861         memset((char *)params,'\0',30);
862         SSVAL(params,0,fsp->fnum);
863         SSVAL(params,2,fmode);
864         put_dos_date2(params,4, mtime);
865         SIVAL(params,8, (uint32)size);
866         SSVAL(params,12,rmode);
867
868         if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
869                 smb_action |= EXTENDED_OPLOCK_GRANTED;
870         }
871
872         SSVAL(params,18,smb_action);
873
874         /*
875          * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
876          */
877         SIVAL(params,20,inode);
878         if (flags & 8) {
879                 uint32 ea_size = estimate_ea_size(conn, fsp, fname);
880                 SIVAL(params, 26, ea_size);
881         }
882
883         /* Send the required number of replies */
884         send_trans2_replies(outbuf, bufsize, params, 30, *ppdata, 0);
885
886         return -1;
887 }
888
889 /*********************************************************
890  Routine to check if a given string matches exactly.
891  as a special case a mask of "." does NOT match. That
892  is required for correct wildcard semantics
893  Case can be significant or not.
894 **********************************************************/
895
896 static BOOL exact_match(char *str,char *mask, BOOL case_sig) 
897 {
898         if (mask[0] == '.' && mask[1] == 0)
899                 return False;
900         if (case_sig)   
901                 return strcmp(str,mask)==0;
902         if (StrCaseCmp(str,mask) != 0) {
903                 return False;
904         }
905         if (ms_has_wild(str)) {
906                 return False;
907         }
908         return True;
909 }
910
911 /****************************************************************************
912  Return the filetype for UNIX extensions.
913 ****************************************************************************/
914
915 static uint32 unix_filetype(mode_t mode)
916 {
917         if(S_ISREG(mode))
918                 return UNIX_TYPE_FILE;
919         else if(S_ISDIR(mode))
920                 return UNIX_TYPE_DIR;
921 #ifdef S_ISLNK
922         else if(S_ISLNK(mode))
923                 return UNIX_TYPE_SYMLINK;
924 #endif
925 #ifdef S_ISCHR
926         else if(S_ISCHR(mode))
927                 return UNIX_TYPE_CHARDEV;
928 #endif
929 #ifdef S_ISBLK
930         else if(S_ISBLK(mode))
931                 return UNIX_TYPE_BLKDEV;
932 #endif
933 #ifdef S_ISFIFO
934         else if(S_ISFIFO(mode))
935                 return UNIX_TYPE_FIFO;
936 #endif
937 #ifdef S_ISSOCK
938         else if(S_ISSOCK(mode))
939                 return UNIX_TYPE_SOCKET;
940 #endif
941
942         DEBUG(0,("unix_filetype: unknown filetype %u", (unsigned)mode));
943         return UNIX_TYPE_UNKNOWN;
944 }
945
946 /****************************************************************************
947  Map wire perms onto standard UNIX permissions. Obey share restrictions.
948 ****************************************************************************/
949
950 static mode_t unix_perms_from_wire( connection_struct *conn, SMB_STRUCT_STAT *pst, uint32 perms)
951 {
952         mode_t ret = 0;
953
954         if (perms == SMB_MODE_NO_CHANGE)
955                 return pst->st_mode;
956
957         ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
958         ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
959         ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
960         ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
961         ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
962         ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
963         ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
964         ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
965         ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
966 #ifdef S_ISVTX
967         ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
968 #endif
969 #ifdef S_ISGID
970         ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
971 #endif
972 #ifdef S_ISUID
973         ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
974 #endif
975
976         if (VALID_STAT(*pst) && S_ISDIR(pst->st_mode)) {
977                 ret &= lp_dir_mask(SNUM(conn));
978                 /* Add in force bits */
979                 ret |= lp_force_dir_mode(SNUM(conn));
980         } else {
981                 /* Apply mode mask */
982                 ret &= lp_create_mask(SNUM(conn));
983                 /* Add in force bits */
984                 ret |= lp_force_create_mode(SNUM(conn));
985         }
986
987         return ret;
988 }
989
990 /****************************************************************************
991  Get a level dependent lanman2 dir entry.
992 ****************************************************************************/
993
994 static BOOL get_lanman2_dir_entry(connection_struct *conn,
995                                   void *inbuf, void *outbuf,
996                                  char *path_mask,int dirtype,int info_level,
997                                  int requires_resume_key,
998                                  BOOL dont_descend,char **ppdata, 
999                                  char *base_data, int space_remaining, 
1000                                  BOOL *out_of_space, BOOL *got_exact_match,
1001                                  int *last_entry_off, struct ea_list *name_list, TALLOC_CTX *ea_ctx)
1002 {
1003         const char *dname;
1004         BOOL found = False;
1005         SMB_STRUCT_STAT sbuf;
1006         pstring mask;
1007         pstring pathreal;
1008         pstring fname;
1009         char *p, *q, *pdata = *ppdata;
1010         uint32 reskey=0;
1011         long prev_dirpos=0;
1012         int mode=0;
1013         SMB_OFF_T file_size = 0;
1014         SMB_BIG_UINT allocation_size = 0;
1015         uint32 len;
1016         time_t mdate=0, adate=0, cdate=0;
1017         char *nameptr;
1018         char *last_entry_ptr;
1019         BOOL was_8_3;
1020         int nt_extmode; /* Used for NT connections instead of mode */
1021         BOOL needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
1022
1023         *fname = 0;
1024         *out_of_space = False;
1025         *got_exact_match = False;
1026
1027         if (!conn->dirptr)
1028                 return(False);
1029
1030         p = strrchr_m(path_mask,'/');
1031         if(p != NULL) {
1032                 if(p[1] == '\0')
1033                         pstrcpy(mask,"*.*");
1034                 else
1035                         pstrcpy(mask, p+1);
1036         } else
1037                 pstrcpy(mask, path_mask);
1038
1039
1040         while (!found) {
1041                 BOOL got_match;
1042                 /* Needed if we run out of space */
1043                 long curr_dirpos = prev_dirpos = dptr_TellDir(conn->dirptr);
1044                 dname = dptr_ReadDirName(conn->dirptr,&curr_dirpos,&sbuf);
1045
1046                 /*
1047                  * Due to bugs in NT client redirectors we are not using
1048                  * resume keys any more - set them to zero.
1049                  * Check out the related comments in findfirst/findnext.
1050                  * JRA.
1051                  */
1052
1053                 reskey = 0;
1054
1055                 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %ld\n",
1056                         (long)conn->dirptr,curr_dirpos));
1057       
1058                 if (!dname) 
1059                         return(False);
1060
1061                 pstrcpy(fname,dname);      
1062
1063                 if(!(got_match = *got_exact_match = exact_match(fname, mask, conn->case_sensitive)))
1064                         got_match = mask_match(fname, mask, conn->case_sensitive);
1065
1066                 if(!got_match && !mangle_is_8_3(fname, False)) {
1067
1068                         /*
1069                          * It turns out that NT matches wildcards against
1070                          * both long *and* short names. This may explain some
1071                          * of the wildcard wierdness from old DOS clients
1072                          * that some people have been seeing.... JRA.
1073                          */
1074
1075                         pstring newname;
1076                         pstrcpy( newname, fname);
1077                         mangle_map( newname, True, False, SNUM(conn));
1078                         if(!(got_match = *got_exact_match = exact_match(newname, mask, conn->case_sensitive)))
1079                                 got_match = mask_match(newname, mask, conn->case_sensitive);
1080                 }
1081
1082                 if(got_match) {
1083                         BOOL isdots = (strequal(fname,"..") || strequal(fname,"."));
1084                         if (dont_descend && !isdots)
1085                                 continue;
1086           
1087                         pstrcpy(pathreal,conn->dirpath);
1088                         if(needslash)
1089                                 pstrcat(pathreal,"/");
1090                         pstrcat(pathreal,dname);
1091
1092                         if (INFO_LEVEL_IS_UNIX(info_level)) {
1093                                 if (SMB_VFS_LSTAT(conn,pathreal,&sbuf) != 0) {
1094                                         DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",
1095                                                 pathreal,strerror(errno)));
1096                                         continue;
1097                                 }
1098                         } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,pathreal,&sbuf) != 0) {
1099
1100                                 /* Needed to show the msdfs symlinks as 
1101                                  * directories */
1102
1103                                 if(lp_host_msdfs() && 
1104                                    lp_msdfs_root(SNUM(conn)) &&
1105                                    is_msdfs_link(conn, pathreal, NULL, NULL,
1106                                                  &sbuf)) {
1107
1108                                         DEBUG(5,("get_lanman2_dir_entry: Masquerading msdfs link %s as a directory\n", pathreal));
1109                                         sbuf.st_mode = (sbuf.st_mode & 0xFFF) | S_IFDIR;
1110
1111                                 } else {
1112
1113                                         DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
1114                                                 pathreal,strerror(errno)));
1115                                         continue;
1116                                 }
1117                         }
1118
1119                         mode = dos_mode(conn,pathreal,&sbuf);
1120
1121                         if (!dir_check_ftype(conn,mode,dirtype)) {
1122                                 DEBUG(5,("[%s] attribs didn't match %x\n",fname,dirtype));
1123                                 continue;
1124                         }
1125
1126                         file_size = get_file_size(sbuf);
1127                         allocation_size = get_allocation_size(conn,NULL,&sbuf);
1128                         mdate = sbuf.st_mtime;
1129                         adate = sbuf.st_atime;
1130                         cdate = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
1131
1132                         if (lp_dos_filetime_resolution(SNUM(conn))) {
1133                                 cdate &= ~1;
1134                                 mdate &= ~1;
1135                                 adate &= ~1;
1136                         }
1137
1138                         if(mode & aDIR) {
1139                                 /* This is necessary, as otherwise the
1140                                  * desktop.ini file in this folder is
1141                                  * ignored */
1142                                 mode |= (lp_profile_acls(SNUM(conn)) ? aRONLY : 0);
1143                                 file_size = 0;
1144                         }
1145
1146                         DEBUG(5,("get_lanman2_dir_entry found %s fname=%s\n",pathreal,fname));
1147           
1148                         found = True;
1149                 }
1150         }
1151
1152         mangle_map(fname,False,True,SNUM(conn));
1153
1154         p = pdata;
1155         last_entry_ptr = p;
1156
1157         nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
1158
1159         switch (info_level) {
1160                 case SMB_FIND_INFO_STANDARD:
1161                         DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1162                         if(requires_resume_key) {
1163                                 SIVAL(p,0,reskey);
1164                                 p += 4;
1165                         }
1166                         put_dos_date2(p,l1_fdateCreation,cdate);
1167                         put_dos_date2(p,l1_fdateLastAccess,adate);
1168                         put_dos_date2(p,l1_fdateLastWrite,mdate);
1169                         SIVAL(p,l1_cbFile,(uint32)file_size);
1170                         SIVAL(p,l1_cbFileAlloc,(uint32)allocation_size);
1171                         SSVAL(p,l1_attrFile,mode);
1172                         p += l1_achName;
1173                         nameptr = p;
1174                         p += align_string(outbuf, p, 0);
1175                         len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
1176                         if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1177                                 if (len > 2) {
1178                                         SCVAL(nameptr, -1, len - 2);
1179                                 } else {
1180                                         SCVAL(nameptr, -1, 0);
1181                                 }
1182                         } else {
1183                                 if (len > 1) {
1184                                         SCVAL(nameptr, -1, len - 1);
1185                                 } else {
1186                                         SCVAL(nameptr, -1, 0);
1187                                 }
1188                         }
1189                         p += len;
1190                         break;
1191
1192                 case SMB_FIND_EA_SIZE:
1193                         DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n"));
1194                         if(requires_resume_key) {
1195                                 SIVAL(p,0,reskey);
1196                                 p += 4;
1197                         }
1198                         put_dos_date2(p,l2_fdateCreation,cdate);
1199                         put_dos_date2(p,l2_fdateLastAccess,adate);
1200                         put_dos_date2(p,l2_fdateLastWrite,mdate);
1201                         SIVAL(p,l2_cbFile,(uint32)file_size);
1202                         SIVAL(p,l2_cbFileAlloc,(uint32)allocation_size);
1203                         SSVAL(p,l2_attrFile,mode);
1204                         {
1205                                 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1206                                 SIVAL(p,l2_cbList,ea_size); /* Extended attributes */
1207                         }
1208                         p += l2_achName;
1209                         nameptr = p - 1;
1210                         len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE | STR_NOALIGN);
1211                         if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1212                                 if (len > 2) {
1213                                         len -= 2;
1214                                 } else {
1215                                         len = 0;
1216                                 }
1217                         } else {
1218                                 if (len > 1) {
1219                                         len -= 1;
1220                                 } else {
1221                                         len = 0;
1222                                 }
1223                         }
1224                         SCVAL(nameptr,0,len);
1225                         p += len;
1226                         SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1227                         break;
1228
1229                 case SMB_FIND_EA_LIST:
1230                 {
1231                         struct ea_list *file_list = NULL;
1232                         size_t ea_len = 0;
1233
1234                         DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n"));
1235                         if (!name_list) {
1236                                 return False;
1237                         }
1238                         if(requires_resume_key) {
1239                                 SIVAL(p,0,reskey);
1240                                 p += 4;
1241                         }
1242                         put_dos_date2(p,l2_fdateCreation,cdate);
1243                         put_dos_date2(p,l2_fdateLastAccess,adate);
1244                         put_dos_date2(p,l2_fdateLastWrite,mdate);
1245                         SIVAL(p,l2_cbFile,(uint32)file_size);
1246                         SIVAL(p,l2_cbFileAlloc,(uint32)allocation_size);
1247                         SSVAL(p,l2_attrFile,mode);
1248                         p += l2_cbList; /* p now points to the EA area. */
1249
1250                         file_list = get_ea_list_from_file(ea_ctx, conn, NULL, pathreal, &ea_len);
1251                         name_list = ea_list_union(name_list, file_list, &ea_len);
1252
1253                         /* We need to determine if this entry will fit in the space available. */
1254                         /* Max string size is 255 bytes. */
1255                         if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1256                                 /* Move the dirptr back to prev_dirpos */
1257                                 dptr_SeekDir(conn->dirptr, prev_dirpos);
1258                                 *out_of_space = True;
1259                                 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1260                                 return False; /* Not finished - just out of space */
1261                         }
1262
1263                         /* Push the ea_data followed by the name. */
1264                         p += fill_ea_buffer(ea_ctx, p, space_remaining, conn, name_list);
1265                         nameptr = p;
1266                         len = srvstr_push(outbuf, p + 1, fname, -1, STR_TERMINATE | STR_NOALIGN);
1267                         if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1268                                 if (len > 2) {
1269                                         len -= 2;
1270                                 } else {
1271                                         len = 0;
1272                                 }
1273                         } else {
1274                                 if (len > 1) {
1275                                         len -= 1;
1276                                 } else {
1277                                         len = 0;
1278                                 }
1279                         }
1280                         SCVAL(nameptr,0,len);
1281                         p += len + 1;
1282                         SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1283                         break;
1284                 }
1285
1286                 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1287                         DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1288                         was_8_3 = mangle_is_8_3(fname, True);
1289                         p += 4;
1290                         SIVAL(p,0,reskey); p += 4;
1291                         put_long_date(p,cdate); p += 8;
1292                         put_long_date(p,adate); p += 8;
1293                         put_long_date(p,mdate); p += 8;
1294                         put_long_date(p,mdate); p += 8;
1295                         SOFF_T(p,0,file_size); p += 8;
1296                         SOFF_T(p,0,allocation_size); p += 8;
1297                         SIVAL(p,0,nt_extmode); p += 4;
1298                         q = p; p += 4; /* q is placeholder for name length. */
1299                         {
1300                                 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1301                                 SIVAL(p,0,ea_size); /* Extended attributes */
1302                                 p += 4;
1303                         }
1304                         /* Clear the short name buffer. This is
1305                          * IMPORTANT as not doing so will trigger
1306                          * a Win2k client bug. JRA.
1307                          */
1308                         memset(p,'\0',26);
1309                         if (!was_8_3 && lp_manglednames(SNUM(conn))) {
1310                                 pstring mangled_name;
1311                                 pstrcpy(mangled_name, fname);
1312                                 mangle_map(mangled_name,True,True,SNUM(conn));
1313                                 mangled_name[12] = 0;
1314                                 len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE);
1315                                 SSVAL(p, 0, len);
1316                         } else {
1317                                 SSVAL(p,0,0);
1318                                 *(p+2) = 0;
1319                         }
1320                         p += 2 + 24;
1321                         len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1322                         SIVAL(q,0,len);
1323                         p += len;
1324                         len = PTR_DIFF(p, pdata);
1325                         len = (len + 3) & ~3;
1326                         SIVAL(pdata,0,len);
1327                         p = pdata + len;
1328                         break;
1329
1330                 case SMB_FIND_FILE_DIRECTORY_INFO:
1331                         DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1332                         p += 4;
1333                         SIVAL(p,0,reskey); p += 4;
1334                         put_long_date(p,cdate); p += 8;
1335                         put_long_date(p,adate); p += 8;
1336                         put_long_date(p,mdate); p += 8;
1337                         put_long_date(p,mdate); p += 8;
1338                         SOFF_T(p,0,file_size); p += 8;
1339                         SOFF_T(p,0,allocation_size); p += 8;
1340                         SIVAL(p,0,nt_extmode); p += 4;
1341                         len = srvstr_push(outbuf, p + 4, fname, -1, STR_TERMINATE_ASCII);
1342                         SIVAL(p,0,len);
1343                         p += 4 + len;
1344                         len = PTR_DIFF(p, pdata);
1345                         len = (len + 3) & ~3;
1346                         SIVAL(pdata,0,len);
1347                         p = pdata + len;
1348                         break;
1349       
1350                 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1351                         DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1352                         p += 4;
1353                         SIVAL(p,0,reskey); p += 4;
1354                         put_long_date(p,cdate); p += 8;
1355                         put_long_date(p,adate); p += 8;
1356                         put_long_date(p,mdate); p += 8;
1357                         put_long_date(p,mdate); p += 8;
1358                         SOFF_T(p,0,file_size); p += 8;
1359                         SOFF_T(p,0,allocation_size); p += 8;
1360                         SIVAL(p,0,nt_extmode); p += 4;
1361                         q = p; p += 4; /* q is placeholder for name length. */
1362                         {
1363                                 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1364                                 SIVAL(p,0,ea_size); /* Extended attributes */
1365                                 p +=4;
1366                         }
1367                         len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1368                         SIVAL(q, 0, len);
1369                         p += len;
1370
1371                         len = PTR_DIFF(p, pdata);
1372                         len = (len + 3) & ~3;
1373                         SIVAL(pdata,0,len);
1374                         p = pdata + len;
1375                         break;
1376
1377                 case SMB_FIND_FILE_NAMES_INFO:
1378                         DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1379                         p += 4;
1380                         SIVAL(p,0,reskey); p += 4;
1381                         p += 4;
1382                         /* this must *not* be null terminated or w2k gets in a loop trying to set an
1383                            acl on a dir (tridge) */
1384                         len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1385                         SIVAL(p, -4, len);
1386                         p += len;
1387                         len = PTR_DIFF(p, pdata);
1388                         len = (len + 3) & ~3;
1389                         SIVAL(pdata,0,len);
1390                         p = pdata + len;
1391                         break;
1392
1393                 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1394                         DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1395                         p += 4;
1396                         SIVAL(p,0,reskey); p += 4;
1397                         put_long_date(p,cdate); p += 8;
1398                         put_long_date(p,adate); p += 8;
1399                         put_long_date(p,mdate); p += 8;
1400                         put_long_date(p,mdate); p += 8;
1401                         SOFF_T(p,0,file_size); p += 8;
1402                         SOFF_T(p,0,allocation_size); p += 8;
1403                         SIVAL(p,0,nt_extmode); p += 4;
1404                         q = p; p += 4; /* q is placeholder for name length. */
1405                         {
1406                                 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1407                                 SIVAL(p,0,ea_size); /* Extended attributes */
1408                                 p +=4;
1409                         }
1410                         SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1411                         SIVAL(p,0,sbuf.st_dev); p += 4;
1412                         SIVAL(p,0,sbuf.st_ino); p += 4;
1413                         len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1414                         SIVAL(q, 0, len);
1415                         p += len; 
1416                         len = PTR_DIFF(p, pdata);
1417                         len = (len + 3) & ~3;
1418                         SIVAL(pdata,0,len);
1419                         p = pdata + len;
1420                         break;
1421
1422                 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1423                         DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1424                         was_8_3 = mangle_is_8_3(fname, True);
1425                         p += 4;
1426                         SIVAL(p,0,reskey); p += 4;
1427                         put_long_date(p,cdate); p += 8;
1428                         put_long_date(p,adate); p += 8;
1429                         put_long_date(p,mdate); p += 8;
1430                         put_long_date(p,mdate); p += 8;
1431                         SOFF_T(p,0,file_size); p += 8;
1432                         SOFF_T(p,0,allocation_size); p += 8;
1433                         SIVAL(p,0,nt_extmode); p += 4;
1434                         q = p; p += 4; /* q is placeholder for name length */
1435                         {
1436                                 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1437                                 SIVAL(p,0,ea_size); /* Extended attributes */
1438                                 p +=4;
1439                         }
1440                         /* Clear the short name buffer. This is
1441                          * IMPORTANT as not doing so will trigger
1442                          * a Win2k client bug. JRA.
1443                          */
1444                         memset(p,'\0',26);
1445                         if (!was_8_3 && lp_manglednames(SNUM(conn))) {
1446                                 pstring mangled_name;
1447                                 pstrcpy(mangled_name, fname);
1448                                 mangle_map(mangled_name,True,True,SNUM(conn));
1449                                 mangled_name[12] = 0;
1450                                 len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE);
1451                                 SSVAL(p, 0, len);
1452                         } else {
1453                                 SSVAL(p,0,0);
1454                                 *(p+2) = 0;
1455                         }
1456                         p += 26;
1457                         SSVAL(p,0,0); p += 2; /* Reserved ? */
1458                         SIVAL(p,0,sbuf.st_dev); p += 4;
1459                         SIVAL(p,0,sbuf.st_ino); p += 4;
1460                         len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1461                         SIVAL(q,0,len);
1462                         p += len;
1463                         len = PTR_DIFF(p, pdata);
1464                         len = (len + 3) & ~3;
1465                         SIVAL(pdata,0,len);
1466                         p = pdata + len;
1467                         break;
1468
1469                 /* CIFS UNIX Extension. */
1470
1471                 case SMB_FIND_FILE_UNIX:
1472                         DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1473                         p+= 4;
1474                         SIVAL(p,0,reskey); p+= 4;    /* Used for continuing search. */
1475
1476                         /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1477                         SOFF_T(p,0,get_file_size(sbuf));             /* File size 64 Bit */
1478                         p+= 8;
1479
1480                         SOFF_T(p,0,get_allocation_size(conn,NULL,&sbuf)); /* Number of bytes used on disk - 64 Bit */
1481                         p+= 8;
1482
1483                         put_long_date(p,sbuf.st_ctime);       /* Inode change Time 64 Bit */
1484                         put_long_date(p+8,sbuf.st_atime);     /* Last access time 64 Bit */
1485                         put_long_date(p+16,sbuf.st_mtime);    /* Last modification time 64 Bit */
1486                         p+= 24;
1487
1488                         SIVAL(p,0,sbuf.st_uid);               /* user id for the owner */
1489                         SIVAL(p,4,0);
1490                         p+= 8;
1491
1492                         SIVAL(p,0,sbuf.st_gid);               /* group id of owner */
1493                         SIVAL(p,4,0);
1494                         p+= 8;
1495
1496                         SIVAL(p,0,unix_filetype(sbuf.st_mode));
1497                         p+= 4;
1498
1499                         SIVAL(p,0,unix_dev_major(sbuf.st_rdev));   /* Major device number if type is device */
1500                         SIVAL(p,4,0);
1501                         p+= 8;
1502
1503                         SIVAL(p,0,unix_dev_minor(sbuf.st_rdev));   /* Minor device number if type is device */
1504                         SIVAL(p,4,0);
1505                         p+= 8;
1506
1507                         SINO_T(p,0,(SMB_INO_T)sbuf.st_ino);   /* inode number */
1508                         p+= 8;
1509
1510                         SIVAL(p,0, unix_perms_to_wire(sbuf.st_mode));     /* Standard UNIX file permissions */
1511                         SIVAL(p,4,0);
1512                         p+= 8;
1513
1514                         SIVAL(p,0,sbuf.st_nlink);             /* number of hard links */
1515                         SIVAL(p,4,0);
1516                         p+= 8;
1517
1518                         len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
1519                         p += len;
1520
1521                         len = PTR_DIFF(p, pdata);
1522                         len = (len + 3) & ~3;
1523                         SIVAL(pdata,0,len);     /* Offset from this structure to the beginning of the next one */
1524                         p = pdata + len;
1525                         /* End of SMB_QUERY_FILE_UNIX_BASIC */
1526
1527                         break;
1528
1529                 default:      
1530                         return(False);
1531         }
1532
1533
1534         if (PTR_DIFF(p,pdata) > space_remaining) {
1535                 /* Move the dirptr back to prev_dirpos */
1536                 dptr_SeekDir(conn->dirptr, prev_dirpos);
1537                 *out_of_space = True;
1538                 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1539                 return False; /* Not finished - just out of space */
1540         }
1541
1542         /* Setup the last entry pointer, as an offset from base_data */
1543         *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
1544         /* Advance the data pointer to the next slot */
1545         *ppdata = p;
1546
1547         return(found);
1548 }
1549
1550 /****************************************************************************
1551  Reply to a TRANS2_FINDFIRST.
1552 ****************************************************************************/
1553
1554 static int call_trans2findfirst(connection_struct *conn, char *inbuf, char *outbuf, int bufsize,  
1555                                 char **pparams, int total_params, char **ppdata, int total_data,
1556                                 unsigned int max_data_bytes)
1557 {
1558         /* We must be careful here that we don't return more than the
1559                 allowed number of data bytes. If this means returning fewer than
1560                 maxentries then so be it. We assume that the redirector has
1561                 enough room for the fixed number of parameter bytes it has
1562                 requested. */
1563         char *params = *pparams;
1564         char *pdata = *ppdata;
1565         int dirtype = SVAL(params,0);
1566         int maxentries = SVAL(params,2);
1567         uint16 findfirst_flags = SVAL(params,4);
1568         BOOL close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
1569         BOOL close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1570         BOOL requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1571         int info_level = SVAL(params,6);
1572         pstring directory;
1573         pstring mask;
1574         char *p;
1575         int last_entry_off=0;
1576         int dptr_num = -1;
1577         int numentries = 0;
1578         int i;
1579         BOOL finished = False;
1580         BOOL dont_descend = False;
1581         BOOL out_of_space = False;
1582         int space_remaining;
1583         BOOL bad_path = False;
1584         SMB_STRUCT_STAT sbuf;
1585         TALLOC_CTX *ea_ctx = NULL;
1586         struct ea_list *ea_list = NULL;
1587         NTSTATUS ntstatus = NT_STATUS_OK;
1588
1589         if (total_params < 12) {
1590                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1591         }
1592
1593         *directory = *mask = 0;
1594
1595         DEBUG(3,("call_trans2findfirst: dirtype = %d, maxentries = %d, close_after_first=%d, \
1596 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
1597                 dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
1598                 info_level, max_data_bytes));
1599
1600         if (!maxentries) {
1601                 /* W2K3 seems to treat zero as 1. */
1602                 maxentries = 1;
1603         }
1604  
1605         switch (info_level) {
1606                 case SMB_FIND_INFO_STANDARD:
1607                 case SMB_FIND_EA_SIZE:
1608                 case SMB_FIND_EA_LIST:
1609                 case SMB_FIND_FILE_DIRECTORY_INFO:
1610                 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1611                 case SMB_FIND_FILE_NAMES_INFO:
1612                 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1613                 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1614                 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1615                         break;
1616                 case SMB_FIND_FILE_UNIX:
1617                         if (!lp_unix_extensions())
1618                                 return(ERROR_DOS(ERRDOS,ERRunknownlevel));
1619                         break;
1620                 default:
1621                         return(ERROR_DOS(ERRDOS,ERRunknownlevel));
1622         }
1623
1624         srvstr_get_path(inbuf, directory, params+12, sizeof(directory), -1, STR_TERMINATE, &ntstatus, True);
1625         if (!NT_STATUS_IS_OK(ntstatus)) {
1626                 return ERROR_NT(ntstatus);
1627         }
1628
1629         RESOLVE_DFSPATH_WCARD(directory, conn, inbuf, outbuf);
1630
1631         unix_convert(directory,conn,0,&bad_path,&sbuf);
1632         if (bad_path) {
1633                 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
1634         }
1635         if(!check_name(directory,conn)) {
1636                 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
1637         }
1638
1639         p = strrchr_m(directory,'/');
1640         if(p == NULL) {
1641                 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
1642                 if((directory[0] == '.') && (directory[1] == '\0'))
1643                         pstrcpy(mask,"*");
1644                 else
1645                         pstrcpy(mask,directory);
1646                 pstrcpy(directory,"./");
1647         } else {
1648                 pstrcpy(mask,p+1);
1649                 *p = 0;
1650         }
1651
1652         DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
1653
1654         if (info_level == SMB_FIND_EA_LIST) {
1655                 uint32 ea_size;
1656
1657                 if (total_data < 4) {
1658                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1659                 }
1660
1661                 ea_size = IVAL(pdata,0);
1662                 if (ea_size != total_data) {
1663                         DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
1664 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
1665                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1666                 }
1667
1668                 if (!lp_ea_support(SNUM(conn))) {
1669                         return ERROR_DOS(ERRDOS,ERReasnotsupported);
1670                 }
1671                                                                                                                                                         
1672                 if ((ea_ctx = talloc_init("findnext_ea_list")) == NULL) {
1673                         return ERROR_NT(NT_STATUS_NO_MEMORY);
1674                 }
1675                                                                                                                                                         
1676                 /* Pull out the list of names. */
1677                 ea_list = read_ea_name_list(ea_ctx, pdata + 4, ea_size - 4);
1678                 if (!ea_list) {
1679                         talloc_destroy(ea_ctx);
1680                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1681                 }
1682         }
1683
1684         pdata = SMB_REALLOC(*ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1685         if( pdata == NULL ) {
1686                 talloc_destroy(ea_ctx);
1687                 return ERROR_NT(NT_STATUS_NO_MEMORY);
1688         }
1689
1690         *ppdata = pdata;
1691         memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1692
1693         /* Realloc the params space */
1694         params = SMB_REALLOC(*pparams, 10);
1695         if (params == NULL) {
1696                 talloc_destroy(ea_ctx);
1697                 return ERROR_NT(NT_STATUS_NO_MEMORY);
1698         }
1699         *pparams = params;
1700
1701         dptr_num = dptr_create(conn,directory, False, True ,SVAL(inbuf,smb_pid));
1702         if (dptr_num < 0) {
1703                 talloc_destroy(ea_ctx);
1704                 return(UNIXERROR(ERRDOS,ERRbadfile));
1705         }
1706
1707         /* Save the wildcard match and attribs we are using on this directory - 
1708                 needed as lanman2 assumes these are being saved between calls */
1709
1710         if (!dptr_set_wcard_and_attributes(dptr_num, mask, dirtype)) {
1711                 dptr_close(&dptr_num);
1712                 talloc_destroy(ea_ctx);
1713                 return ERROR_NT(NT_STATUS_NO_MEMORY);
1714         }
1715
1716         DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n",dptr_num, mask, dirtype));
1717
1718         /* We don't need to check for VOL here as this is returned by 
1719                 a different TRANS2 call. */
1720   
1721         DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
1722         if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
1723                 dont_descend = True;
1724     
1725         p = pdata;
1726         space_remaining = max_data_bytes;
1727         out_of_space = False;
1728
1729         for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
1730                 BOOL got_exact_match = False;
1731
1732                 /* this is a heuristic to avoid seeking the dirptr except when 
1733                         absolutely necessary. It allows for a filename of about 40 chars */
1734                 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
1735                         out_of_space = True;
1736                         finished = False;
1737                 } else {
1738                         finished = !get_lanman2_dir_entry(conn,
1739                                         inbuf, outbuf,
1740                                         mask,dirtype,info_level,
1741                                         requires_resume_key,dont_descend,
1742                                         &p,pdata,space_remaining, &out_of_space, &got_exact_match,
1743                                         &last_entry_off, ea_list, ea_ctx);
1744                 }
1745
1746                 if (finished && out_of_space)
1747                         finished = False;
1748
1749                 if (!finished && !out_of_space)
1750                         numentries++;
1751
1752                 /*
1753                  * As an optimisation if we know we aren't looking
1754                  * for a wildcard name (ie. the name matches the wildcard exactly)
1755                  * then we can finish on any (first) match.
1756                  * This speeds up large directory searches. JRA.
1757                  */
1758
1759                 if(got_exact_match)
1760                         finished = True;
1761
1762                 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
1763         }
1764   
1765         talloc_destroy(ea_ctx);
1766
1767         /* Check if we can close the dirptr */
1768         if(close_after_first || (finished && close_if_end)) {
1769                 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
1770                 dptr_close(&dptr_num);
1771         }
1772
1773         /* 
1774          * If there are no matching entries we must return ERRDOS/ERRbadfile - 
1775          * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
1776          * the protocol level is less than NT1. Tested with smbclient. JRA.
1777          * This should fix the OS/2 client bug #2335.
1778          */
1779
1780         if(numentries == 0) {
1781                 dptr_close(&dptr_num);
1782                 if (Protocol < PROTOCOL_NT1) {
1783                         return ERROR_DOS(ERRDOS,ERRnofiles);
1784                 } else {
1785                         return ERROR_BOTH(NT_STATUS_NO_SUCH_FILE,ERRDOS,ERRbadfile);
1786                 }
1787         }
1788
1789         /* At this point pdata points to numentries directory entries. */
1790
1791         /* Set up the return parameter block */
1792         SSVAL(params,0,dptr_num);
1793         SSVAL(params,2,numentries);
1794         SSVAL(params,4,finished);
1795         SSVAL(params,6,0); /* Never an EA error */
1796         SSVAL(params,8,last_entry_off);
1797
1798         send_trans2_replies( outbuf, bufsize, params, 10, pdata, PTR_DIFF(p,pdata));
1799
1800         if ((! *directory) && dptr_path(dptr_num))
1801                 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1802
1803         DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
1804                 smb_fn_name(CVAL(inbuf,smb_com)), 
1805                 mask, directory, dirtype, numentries ) );
1806
1807         /* 
1808          * Force a name mangle here to ensure that the
1809          * mask as an 8.3 name is top of the mangled cache.
1810          * The reasons for this are subtle. Don't remove
1811          * this code unless you know what you are doing
1812          * (see PR#13758). JRA.
1813          */
1814
1815         if(!mangle_is_8_3_wildcards( mask, False))
1816                 mangle_map(mask, True, True, SNUM(conn));
1817
1818         return(-1);
1819 }
1820
1821 /****************************************************************************
1822  Reply to a TRANS2_FINDNEXT.
1823 ****************************************************************************/
1824
1825 static int call_trans2findnext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
1826                                         char **pparams, int total_params, char **ppdata, int total_data,
1827                                         unsigned int max_data_bytes)
1828 {
1829         /* We must be careful here that we don't return more than the
1830                 allowed number of data bytes. If this means returning fewer than
1831                 maxentries then so be it. We assume that the redirector has
1832                 enough room for the fixed number of parameter bytes it has
1833                 requested. */
1834         char *params = *pparams;
1835         char *pdata = *ppdata;
1836         int dptr_num = SVAL(params,0);
1837         int maxentries = SVAL(params,2);
1838         uint16 info_level = SVAL(params,4);
1839         uint32 resume_key = IVAL(params,6);
1840         uint16 findnext_flags = SVAL(params,10);
1841         BOOL close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
1842         BOOL close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1843         BOOL requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1844         BOOL continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
1845         pstring resume_name;
1846         pstring mask;
1847         pstring directory;
1848         char *p;
1849         uint16 dirtype;
1850         int numentries = 0;
1851         int i, last_entry_off=0;
1852         BOOL finished = False;
1853         BOOL dont_descend = False;
1854         BOOL out_of_space = False;
1855         int space_remaining;
1856         TALLOC_CTX *ea_ctx = NULL;
1857         struct ea_list *ea_list = NULL;
1858         NTSTATUS ntstatus = NT_STATUS_OK;
1859
1860         if (total_params < 12) {
1861                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1862         }
1863
1864         *mask = *directory = *resume_name = 0;
1865
1866         srvstr_get_path(inbuf, resume_name, params+12, sizeof(resume_name), -1, STR_TERMINATE, &ntstatus, True);
1867         if (!NT_STATUS_IS_OK(ntstatus)) {
1868                 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
1869                    complain (it thinks we're asking for the directory above the shared
1870                    path or an invalid name). Catch this as the resume name is only compared, never used in
1871                    a file access. JRA. */
1872                 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_OBJECT_PATH_SYNTAX_BAD)) {
1873                         pstrcpy(resume_name, "..");
1874                 } else if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_OBJECT_NAME_INVALID)) {
1875                         pstrcpy(resume_name, ".");
1876                 } else {
1877                         return ERROR_NT(ntstatus);
1878                 }
1879         }
1880
1881         DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
1882 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
1883 resume_key = %d resume name = %s continue=%d level = %d\n",
1884                 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end, 
1885                 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
1886
1887         if (!maxentries) {
1888                 /* W2K3 seems to treat zero as 1. */
1889                 maxentries = 1;
1890         }
1891
1892         switch (info_level) {
1893                 case SMB_FIND_INFO_STANDARD:
1894                 case SMB_FIND_EA_SIZE:
1895                 case SMB_FIND_EA_LIST:
1896                 case SMB_FIND_FILE_DIRECTORY_INFO:
1897                 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1898                 case SMB_FIND_FILE_NAMES_INFO:
1899                 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1900                         break;
1901                 case SMB_FIND_FILE_UNIX:
1902                         if (!lp_unix_extensions())
1903                                 return(ERROR_DOS(ERRDOS,ERRunknownlevel));
1904                         break;
1905                 default:
1906                         return ERROR_DOS(ERRDOS,ERRunknownlevel);
1907         }
1908
1909         if (info_level == SMB_FIND_EA_LIST) {
1910                 uint32 ea_size;
1911
1912                 if (total_data < 4) {
1913                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1914                 }
1915
1916                 ea_size = IVAL(pdata,0);
1917                 if (ea_size != total_data) {
1918                         DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
1919 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
1920                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1921                 }
1922                                                                                                                                                      
1923                 if (!lp_ea_support(SNUM(conn))) {
1924                         return ERROR_DOS(ERRDOS,ERReasnotsupported);
1925                 }
1926                                                                                                                                                      
1927                 if ((ea_ctx = talloc_init("findnext_ea_list")) == NULL) {
1928                         return ERROR_NT(NT_STATUS_NO_MEMORY);
1929                 }
1930
1931                 /* Pull out the list of names. */
1932                 ea_list = read_ea_name_list(ea_ctx, pdata + 4, ea_size - 4);
1933                 if (!ea_list) {
1934                         talloc_destroy(ea_ctx);
1935                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1936                 }
1937         }
1938
1939         pdata = SMB_REALLOC( *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1940         if(pdata == NULL) {
1941                 talloc_destroy(ea_ctx);
1942                 return ERROR_NT(NT_STATUS_NO_MEMORY);
1943         }
1944
1945         *ppdata = pdata;
1946         memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1947
1948         /* Realloc the params space */
1949         params = SMB_REALLOC(*pparams, 6*SIZEOFWORD);
1950         if( params == NULL ) {
1951                 talloc_destroy(ea_ctx);
1952                 return ERROR_NT(NT_STATUS_NO_MEMORY);
1953         }
1954
1955         *pparams = params;
1956
1957         /* Check that the dptr is valid */
1958         if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num))) {
1959                 talloc_destroy(ea_ctx);
1960                 return ERROR_DOS(ERRDOS,ERRnofiles);
1961         }
1962
1963         string_set(&conn->dirpath,dptr_path(dptr_num));
1964
1965         /* Get the wildcard mask from the dptr */
1966         if((p = dptr_wcard(dptr_num))== NULL) {
1967                 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
1968                 talloc_destroy(ea_ctx);
1969                 return ERROR_DOS(ERRDOS,ERRnofiles);
1970         }
1971
1972         pstrcpy(mask, p);
1973         pstrcpy(directory,conn->dirpath);
1974
1975         /* Get the attr mask from the dptr */
1976         dirtype = dptr_attr(dptr_num);
1977
1978         DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
1979                 dptr_num, mask, dirtype, 
1980                 (long)conn->dirptr,
1981                 dptr_TellDir(conn->dirptr)));
1982
1983         /* We don't need to check for VOL here as this is returned by 
1984                 a different TRANS2 call. */
1985
1986         DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
1987         if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
1988                 dont_descend = True;
1989     
1990         p = pdata;
1991         space_remaining = max_data_bytes;
1992         out_of_space = False;
1993
1994         /* 
1995          * Seek to the correct position. We no longer use the resume key but
1996          * depend on the last file name instead.
1997          */
1998
1999         if(*resume_name && !continue_bit) {
2000                 SMB_STRUCT_STAT st;
2001
2002                 long current_pos = 0;
2003                 /*
2004                  * Remember, mangle_map is called by
2005                  * get_lanman2_dir_entry(), so the resume name
2006                  * could be mangled. Ensure we check the unmangled name.
2007                  */
2008
2009                 if (mangle_is_mangled(resume_name)) {
2010                         mangle_check_cache(resume_name, sizeof(resume_name)-1);
2011                 }
2012
2013                 /*
2014                  * Fix for NT redirector problem triggered by resume key indexes
2015                  * changing between directory scans. We now return a resume key of 0
2016                  * and instead look for the filename to continue from (also given
2017                  * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2018                  * findfirst/findnext (as is usual) then the directory pointer
2019                  * should already be at the correct place.
2020                  */
2021
2022                 finished = !dptr_SearchDir(conn->dirptr, resume_name, &current_pos, &st);
2023         } /* end if resume_name && !continue_bit */
2024
2025         for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2026                 BOOL got_exact_match = False;
2027
2028                 /* this is a heuristic to avoid seeking the dirptr except when 
2029                         absolutely necessary. It allows for a filename of about 40 chars */
2030                 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2031                         out_of_space = True;
2032                         finished = False;
2033                 } else {
2034                         finished = !get_lanman2_dir_entry(conn,
2035                                                 inbuf, outbuf,
2036                                                 mask,dirtype,info_level,
2037                                                 requires_resume_key,dont_descend,
2038                                                 &p,pdata,space_remaining, &out_of_space, &got_exact_match,
2039                                                 &last_entry_off, ea_list, ea_ctx);
2040                 }
2041
2042                 if (finished && out_of_space)
2043                         finished = False;
2044
2045                 if (!finished && !out_of_space)
2046                         numentries++;
2047
2048                 /*
2049                  * As an optimisation if we know we aren't looking
2050                  * for a wildcard name (ie. the name matches the wildcard exactly)
2051                  * then we can finish on any (first) match.
2052                  * This speeds up large directory searches. JRA.
2053                  */
2054
2055                 if(got_exact_match)
2056                         finished = True;
2057
2058                 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2059         }
2060   
2061         talloc_destroy(ea_ctx);
2062
2063         /* Check if we can close the dirptr */
2064         if(close_after_request || (finished && close_if_end)) {
2065                 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2066                 dptr_close(&dptr_num); /* This frees up the saved mask */
2067         }
2068
2069         /* Set up the return parameter block */
2070         SSVAL(params,0,numentries);
2071         SSVAL(params,2,finished);
2072         SSVAL(params,4,0); /* Never an EA error */
2073         SSVAL(params,6,last_entry_off);
2074
2075         send_trans2_replies( outbuf, bufsize, params, 8, pdata, PTR_DIFF(p,pdata));
2076
2077         if ((! *directory) && dptr_path(dptr_num))
2078                 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
2079
2080         DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2081                 smb_fn_name(CVAL(inbuf,smb_com)), 
2082                 mask, directory, dirtype, numentries ) );
2083
2084         return(-1);
2085 }
2086
2087 /****************************************************************************
2088  Reply to a TRANS2_QFSINFO (query filesystem info).
2089 ****************************************************************************/
2090
2091 static int call_trans2qfsinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2092                                         char **pparams, int total_params, char **ppdata, int total_data,
2093                                         unsigned int max_data_bytes)
2094 {
2095         char *pdata = *ppdata;
2096         char *params = *pparams;
2097         uint16 info_level = SVAL(params,0);
2098         int data_len, len;
2099         SMB_STRUCT_STAT st;
2100         char *vname = volume_label(SNUM(conn));
2101         int snum = SNUM(conn);
2102         char *fstype = lp_fstype(SNUM(conn));
2103         int quota_flag = 0;
2104
2105         DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
2106
2107         if(SMB_VFS_STAT(conn,".",&st)!=0) {
2108                 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
2109                 return ERROR_DOS(ERRSRV,ERRinvdevice);
2110         }
2111
2112         pdata = SMB_REALLOC(*ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2113         if ( pdata == NULL ) {
2114                 return ERROR_NT(NT_STATUS_NO_MEMORY);
2115         }
2116
2117         *ppdata = pdata;
2118         memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2119
2120         switch (info_level) {
2121                 case SMB_INFO_ALLOCATION:
2122                 {
2123                         SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2124                         data_len = 18;
2125                         if (SMB_VFS_DISK_FREE(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2126                                 return(UNIXERROR(ERRHRD,ERRgeneral));
2127                         }
2128
2129                         block_size = lp_block_size(snum);
2130                         if (bsize < block_size) {
2131                                 SMB_BIG_UINT factor = block_size/bsize;
2132                                 bsize = block_size;
2133                                 dsize /= factor;
2134                                 dfree /= factor;
2135                         }
2136                         if (bsize > block_size) {
2137                                 SMB_BIG_UINT factor = bsize/block_size;
2138                                 bsize = block_size;
2139                                 dsize *= factor;
2140                                 dfree *= factor;
2141                         }
2142                         bytes_per_sector = 512;
2143                         sectors_per_unit = bsize/bytes_per_sector;
2144
2145                         DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2146 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2147                                 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2148
2149                         SIVAL(pdata,l1_idFileSystem,st.st_dev);
2150                         SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2151                         SIVAL(pdata,l1_cUnit,dsize);
2152                         SIVAL(pdata,l1_cUnitAvail,dfree);
2153                         SSVAL(pdata,l1_cbSector,bytes_per_sector);
2154                         break;
2155                 }
2156
2157                 case SMB_INFO_VOLUME:
2158                         /* Return volume name */
2159                         /* 
2160                          * Add volume serial number - hash of a combination of
2161                          * the called hostname and the service name.
2162                          */
2163                         SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2164                         /*
2165                          * Win2k3 and previous mess this up by sending a name length
2166                          * one byte short. I believe only older clients (OS/2 Win9x) use
2167                          * this call so try fixing this by adding a terminating null to
2168                          * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2169                          */
2170                         len = srvstr_push(outbuf, pdata+l2_vol_szVolLabel, vname, -1, STR_NOALIGN|STR_TERMINATE);
2171                         SCVAL(pdata,l2_vol_cch,len);
2172                         data_len = l2_vol_szVolLabel + len;
2173                         DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
2174                                 (unsigned)st.st_ctime, len, vname));
2175                         break;
2176
2177                 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2178                 case SMB_FS_ATTRIBUTE_INFORMATION:
2179
2180
2181 #if defined(HAVE_SYS_QUOTAS)
2182                         quota_flag = FILE_VOLUME_QUOTAS;
2183 #endif
2184
2185                         SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2186                                 (lp_nt_acl_support(SNUM(conn)) ? FILE_PERSISTENT_ACLS : 0)|
2187                                 quota_flag); /* FS ATTRIBUTES */
2188
2189                         SIVAL(pdata,4,255); /* Max filename component length */
2190                         /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2191                                 and will think we can't do long filenames */
2192                         len = srvstr_push(outbuf, pdata+12, fstype, -1, STR_UNICODE);
2193                         SIVAL(pdata,8,len);
2194                         data_len = 12 + len;
2195                         break;
2196
2197                 case SMB_QUERY_FS_LABEL_INFO:
2198                 case SMB_FS_LABEL_INFORMATION:
2199                         len = srvstr_push(outbuf, pdata+4, vname, -1, 0);
2200                         data_len = 4 + len;
2201                         SIVAL(pdata,0,len);
2202                         break;
2203
2204                 case SMB_QUERY_FS_VOLUME_INFO:      
2205                 case SMB_FS_VOLUME_INFORMATION:
2206
2207                         /* 
2208                          * Add volume serial number - hash of a combination of
2209                          * the called hostname and the service name.
2210                          */
2211                         SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^ 
2212                                 (str_checksum(get_local_machine_name())<<16));
2213
2214                         len = srvstr_push(outbuf, pdata+18, vname, -1, STR_UNICODE);
2215                         SIVAL(pdata,12,len);
2216                         data_len = 18+len;
2217                         DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n", 
2218                                 (int)strlen(vname),vname, lp_servicename(snum)));
2219                         break;
2220
2221                 case SMB_QUERY_FS_SIZE_INFO:
2222                 case SMB_FS_SIZE_INFORMATION:
2223                 {
2224                         SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2225                         data_len = 24;
2226                         if (SMB_VFS_DISK_FREE(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2227                                 return(UNIXERROR(ERRHRD,ERRgeneral));
2228                         }
2229                         block_size = lp_block_size(snum);
2230                         if (bsize < block_size) {
2231                                 SMB_BIG_UINT factor = block_size/bsize;
2232                                 bsize = block_size;
2233                                 dsize /= factor;
2234                                 dfree /= factor;
2235                         }
2236                         if (bsize > block_size) {
2237                                 SMB_BIG_UINT factor = bsize/block_size;
2238                                 bsize = block_size;
2239                                 dsize *= factor;
2240                                 dfree *= factor;
2241                         }
2242                         bytes_per_sector = 512;
2243                         sectors_per_unit = bsize/bytes_per_sector;
2244                         DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2245 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2246                                 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2247                         SBIG_UINT(pdata,0,dsize);
2248                         SBIG_UINT(pdata,8,dfree);
2249                         SIVAL(pdata,16,sectors_per_unit);
2250                         SIVAL(pdata,20,bytes_per_sector);
2251                         break;
2252                 }
2253
2254                 case SMB_FS_FULL_SIZE_INFORMATION:
2255                 {
2256                         SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2257                         data_len = 32;
2258                         if (SMB_VFS_DISK_FREE(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2259                                 return(UNIXERROR(ERRHRD,ERRgeneral));
2260                         }
2261                         block_size = lp_block_size(snum);
2262                         if (bsize < block_size) {
2263                                 SMB_BIG_UINT factor = block_size/bsize;
2264                                 bsize = block_size;
2265                                 dsize /= factor;
2266                                 dfree /= factor;
2267                         }
2268                         if (bsize > block_size) {
2269                                 SMB_BIG_UINT factor = bsize/block_size;
2270                                 bsize = block_size;
2271                                 dsize *= factor;
2272                                 dfree *= factor;
2273                         }
2274                         bytes_per_sector = 512;
2275                         sectors_per_unit = bsize/bytes_per_sector;
2276                         DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2277 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2278                                 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2279                         SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2280                         SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2281                         SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2282                         SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2283                         SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2284                         break;
2285                 }
2286
2287                 case SMB_QUERY_FS_DEVICE_INFO:
2288                 case SMB_FS_DEVICE_INFORMATION:
2289                         data_len = 8;
2290                         SIVAL(pdata,0,0); /* dev type */
2291                         SIVAL(pdata,4,0); /* characteristics */
2292                         break;
2293
2294 #ifdef HAVE_SYS_QUOTAS
2295                 case SMB_FS_QUOTA_INFORMATION:
2296                 /* 
2297                  * what we have to send --metze:
2298                  *
2299                  * Unknown1:            24 NULL bytes
2300                  * Soft Quota Treshold: 8 bytes seems like SMB_BIG_UINT or so
2301                  * Hard Quota Limit:    8 bytes seems like SMB_BIG_UINT or so
2302                  * Quota Flags:         2 byte :
2303                  * Unknown3:            6 NULL bytes
2304                  *
2305                  * 48 bytes total
2306                  * 
2307                  * details for Quota Flags:
2308                  * 
2309                  * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2310                  * 0x0010 Log Warn:  log if the user exceeds his Soft Quota
2311                  * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2312                  * 0x0001 Enable Quotas: enable quota for this fs
2313                  *
2314                  */
2315                 {
2316                         /* we need to fake up a fsp here,
2317                          * because its not send in this call
2318                          */
2319                         files_struct fsp;
2320                         SMB_NTQUOTA_STRUCT quotas;
2321                         
2322                         ZERO_STRUCT(fsp);
2323                         ZERO_STRUCT(quotas);
2324                         
2325                         fsp.conn = conn;
2326                         fsp.fnum = -1;
2327                         fsp.fd = -1;
2328                         
2329                         /* access check */
2330                         if (current_user.uid != 0) {
2331                                 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2332                                         lp_servicename(SNUM(conn)),conn->user));
2333                                 return ERROR_DOS(ERRDOS,ERRnoaccess);
2334                         }
2335                         
2336                         if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
2337                                 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2338                                 return ERROR_DOS(ERRSRV,ERRerror);
2339                         }
2340
2341                         data_len = 48;
2342
2343                         DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn))));          
2344                 
2345                         /* Unknown1 24 NULL bytes*/
2346                         SBIG_UINT(pdata,0,(SMB_BIG_UINT)0);
2347                         SBIG_UINT(pdata,8,(SMB_BIG_UINT)0);
2348                         SBIG_UINT(pdata,16,(SMB_BIG_UINT)0);
2349                 
2350                         /* Default Soft Quota 8 bytes */
2351                         SBIG_UINT(pdata,24,quotas.softlim);
2352
2353                         /* Default Hard Quota 8 bytes */
2354                         SBIG_UINT(pdata,32,quotas.hardlim);
2355         
2356                         /* Quota flag 2 bytes */
2357                         SSVAL(pdata,40,quotas.qflags);
2358                 
2359                         /* Unknown3 6 NULL bytes */
2360                         SSVAL(pdata,42,0);
2361                         SIVAL(pdata,44,0);
2362                         
2363                         break;
2364                 }
2365 #endif /* HAVE_SYS_QUOTAS */
2366                 case SMB_FS_OBJECTID_INFORMATION:
2367                         data_len = 64;
2368                         break;
2369
2370                 /*
2371                  * Query the version and capabilities of the CIFS UNIX extensions
2372                  * in use.
2373                  */
2374
2375                 case SMB_QUERY_CIFS_UNIX_INFO:
2376                         if (!lp_unix_extensions())
2377                                 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2378                         data_len = 12;
2379                         SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2380                         SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2381                         SBIG_UINT(pdata,4,((SMB_BIG_UINT)CIFS_UNIX_POSIX_ACLS_CAP)); /* We have POSIX ACLs. */
2382                         break;
2383
2384                 case SMB_MAC_QUERY_FS_INFO:
2385                         /*
2386                          * Thursby MAC extension... ONLY on NTFS filesystems
2387                          * once we do streams then we don't need this
2388                          */
2389                         if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
2390                                 data_len = 88;
2391                                 SIVAL(pdata,84,0x100); /* Don't support mac... */
2392                                 break;
2393                         }
2394                         /* drop through */
2395                 default:
2396                         return ERROR_DOS(ERRDOS,ERRunknownlevel);
2397         }
2398
2399
2400         send_trans2_replies( outbuf, bufsize, params, 0, pdata, data_len);
2401
2402         DEBUG( 4, ( "%s info_level = %d\n", smb_fn_name(CVAL(inbuf,smb_com)), info_level) );
2403
2404         return -1;
2405 }
2406
2407 #ifdef HAVE_SYS_QUOTAS
2408 /****************************************************************************
2409  Reply to a TRANS2_SETFSINFO (set filesystem info).
2410 ****************************************************************************/
2411
2412 static int call_trans2setfsinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2413                                         char **pparams, int total_params, char **ppdata, int total_data,
2414                                         unsigned int max_data_bytes)
2415 {
2416         char *pdata = *ppdata;
2417         char *params = *pparams;
2418         files_struct *fsp = NULL;
2419         uint16 info_level;
2420         int outsize;
2421         SMB_NTQUOTA_STRUCT quotas;
2422         
2423         ZERO_STRUCT(quotas);
2424
2425         DEBUG(10,("call_trans2setfsinfo: SET_FS_QUOTA: for service [%s]\n",lp_servicename(SNUM(conn))));
2426
2427         /* access check */
2428         if ((current_user.uid != 0)||!CAN_WRITE(conn)) {
2429                 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2430                         lp_servicename(SNUM(conn)),conn->user));
2431                 return ERROR_DOS(ERRSRV,ERRaccess);
2432         }
2433
2434         /*  */
2435         if (total_params < 4) {
2436                 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
2437                         total_params));
2438                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2439         }
2440
2441         fsp = file_fsp(params,0);
2442
2443         if (!CHECK_NTQUOTA_HANDLE_OK(fsp,conn)) {
2444                 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
2445                 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
2446         }
2447
2448         info_level = SVAL(params,2);
2449
2450         switch(info_level) {
2451                 case SMB_FS_QUOTA_INFORMATION:
2452                         /* note: normaly there're 48 bytes,
2453                          * but we didn't use the last 6 bytes for now 
2454                          * --metze 
2455                          */
2456                         if (total_data < 42) {
2457                                 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
2458                                         total_data));
2459                                 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2460                         }
2461                         
2462                         /* unknown_1 24 NULL bytes in pdata*/
2463                 
2464                         /* the soft quotas 8 bytes (SMB_BIG_UINT)*/
2465                         quotas.softlim = (SMB_BIG_UINT)IVAL(pdata,24);
2466 #ifdef LARGE_SMB_OFF_T
2467                         quotas.softlim |= (((SMB_BIG_UINT)IVAL(pdata,28)) << 32);
2468 #else /* LARGE_SMB_OFF_T */
2469                         if ((IVAL(pdata,28) != 0)&&
2470                                 ((quotas.softlim != 0xFFFFFFFF)||
2471                                 (IVAL(pdata,28)!=0xFFFFFFFF))) {
2472                                 /* more than 32 bits? */
2473                                 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2474                         }
2475 #endif /* LARGE_SMB_OFF_T */
2476                 
2477                         /* the hard quotas 8 bytes (SMB_BIG_UINT)*/
2478                         quotas.hardlim = (SMB_BIG_UINT)IVAL(pdata,32);
2479 #ifdef LARGE_SMB_OFF_T
2480                         quotas.hardlim |= (((SMB_BIG_UINT)IVAL(pdata,36)) << 32);
2481 #else /* LARGE_SMB_OFF_T */
2482                         if ((IVAL(pdata,36) != 0)&&
2483                                 ((quotas.hardlim != 0xFFFFFFFF)||
2484                                 (IVAL(pdata,36)!=0xFFFFFFFF))) {
2485                                 /* more than 32 bits? */
2486                                 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2487                         }
2488 #endif /* LARGE_SMB_OFF_T */
2489                 
2490                         /* quota_flags 2 bytes **/
2491                         quotas.qflags = SVAL(pdata,40);
2492                 
2493                         /* unknown_2 6 NULL bytes follow*/
2494                 
2495                         /* now set the quotas */
2496                         if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
2497                                 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2498                                 return ERROR_DOS(ERRSRV,ERRerror);
2499                         }
2500                         
2501                         break;
2502                 default:
2503                         DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
2504                                 info_level));
2505                         return ERROR_DOS(ERRDOS,ERRunknownlevel);
2506                         break;
2507         }
2508
2509         /* 
2510          * sending this reply works fine, 
2511          * but I'm not sure it's the same 
2512          * like windows do...
2513          * --metze
2514          */ 
2515         outsize = set_message(outbuf,10,0,True);
2516
2517         return outsize;
2518 }
2519 #endif /* HAVE_SYS_QUOTAS */
2520
2521 /****************************************************************************
2522  Utility function to set bad path error.
2523 ****************************************************************************/
2524
2525 int set_bad_path_error(int err, BOOL bad_path, char *outbuf, int def_class, uint32 def_code)
2526 {
2527         DEBUG(10,("set_bad_path_error: err = %d bad_path = %d\n",
2528                         err, (int)bad_path ));
2529
2530         if(err == ENOENT) {
2531                 if (bad_path) {
2532                         return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
2533                 } else {
2534                         return ERROR_NT(NT_STATUS_OBJECT_NAME_NOT_FOUND);
2535                 }
2536         }
2537         return UNIXERROR(def_class,def_code);
2538 }
2539
2540 #if defined(HAVE_POSIX_ACLS)
2541 /****************************************************************************
2542  Utility function to count the number of entries in a POSIX acl.
2543 ****************************************************************************/
2544
2545 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
2546 {
2547         unsigned int ace_count = 0;
2548         int entry_id = SMB_ACL_FIRST_ENTRY;
2549         SMB_ACL_ENTRY_T entry;
2550
2551         while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
2552                 /* get_next... */
2553                 if (entry_id == SMB_ACL_FIRST_ENTRY) {
2554                         entry_id = SMB_ACL_NEXT_ENTRY;
2555                 }
2556                 ace_count++;
2557         }
2558         return ace_count;
2559 }
2560
2561 /****************************************************************************
2562  Utility function to marshall a POSIX acl into wire format.
2563 ****************************************************************************/
2564
2565 static BOOL marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
2566 {
2567         int entry_id = SMB_ACL_FIRST_ENTRY;
2568         SMB_ACL_ENTRY_T entry;
2569
2570         while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
2571                 SMB_ACL_TAG_T tagtype;
2572                 SMB_ACL_PERMSET_T permset;
2573                 unsigned char perms = 0;
2574                 unsigned int own_grp;
2575
2576                 /* get_next... */
2577                 if (entry_id == SMB_ACL_FIRST_ENTRY) {
2578                         entry_id = SMB_ACL_NEXT_ENTRY;
2579                 }
2580
2581                 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
2582                         DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
2583                         return False;
2584                 }
2585
2586                 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
2587                         DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
2588                         return False;
2589                 }
2590
2591                 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
2592                 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
2593                 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
2594
2595                 SCVAL(pdata,1,perms);
2596
2597                 switch (tagtype) {
2598                         case SMB_ACL_USER_OBJ:
2599                                 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
2600                                 own_grp = (unsigned int)pst->st_uid;
2601                                 SIVAL(pdata,2,own_grp);
2602                                 SIVAL(pdata,6,0);
2603                                 break;
2604                         case SMB_ACL_USER:
2605                                 {
2606                                         uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
2607                                         if (!puid) {
2608                                                 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
2609                                         }
2610                                         own_grp = (unsigned int)*puid;
2611                                         SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
2612                                         SCVAL(pdata,0,SMB_POSIX_ACL_USER);
2613                                         SIVAL(pdata,2,own_grp);
2614                                         SIVAL(pdata,6,0);
2615                                         break;
2616                                 }
2617                         case SMB_ACL_GROUP_OBJ:
2618                                 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
2619                                 own_grp = (unsigned int)pst->st_gid;
2620                                 SIVAL(pdata,2,own_grp);
2621                                 SIVAL(pdata,6,0);
2622                                 break;
2623                         case SMB_ACL_GROUP:
2624                                 {
2625                                         gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
2626                                         if (!pgid) {
2627                                                 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
2628                                         }
2629                                         own_grp = (unsigned int)*pgid;
2630                                         SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
2631                                         SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
2632                                         SIVAL(pdata,2,own_grp);
2633                                         SIVAL(pdata,6,0);
2634                                         break;
2635                                 }
2636                         case SMB_ACL_MASK:
2637                                 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
2638                                 SIVAL(pdata,2,0xFFFFFFFF);
2639                                 SIVAL(pdata,6,0xFFFFFFFF);
2640                                 break;
2641                         case SMB_ACL_OTHER:
2642                                 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
2643                                 SIVAL(pdata,2,0xFFFFFFFF);
2644                                 SIVAL(pdata,6,0xFFFFFFFF);
2645                                 break;
2646                         default:
2647                                 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
2648                                 return False;
2649                 }
2650                 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
2651         }
2652
2653         return True;
2654 }
2655 #endif
2656
2657 /****************************************************************************
2658  Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
2659  file name or file id).
2660 ****************************************************************************/
2661
2662 static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2663                                         char **pparams, int total_params, char **ppdata, int total_data,
2664                                         unsigned int max_data_bytes)
2665 {
2666         char *params = *pparams;
2667         char *pdata = *ppdata;
2668         uint16 tran_call = SVAL(inbuf, smb_setup0);
2669         uint16 info_level;
2670         int mode=0;
2671         SMB_OFF_T file_size=0;
2672         SMB_BIG_UINT allocation_size=0;
2673         unsigned int data_size = 0;
2674         unsigned int param_size = 2;
2675         SMB_STRUCT_STAT sbuf;
2676         pstring fname, dos_fname;
2677         char *fullpathname;
2678         char *base_name;
2679         char *p;
2680         SMB_OFF_T pos = 0;
2681         BOOL bad_path = False;
2682         BOOL delete_pending = False;
2683         int len;
2684         time_t c_time;
2685         files_struct *fsp = NULL;
2686         TALLOC_CTX *ea_ctx = NULL;
2687         struct ea_list *ea_list = NULL;
2688         uint32 desired_access = 0x12019F; /* Default - GENERIC_EXECUTE mapping from Windows */
2689
2690         if (!params)
2691                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2692
2693         ZERO_STRUCT(sbuf);
2694
2695         if (tran_call == TRANSACT2_QFILEINFO) {
2696                 if (total_params < 4) {
2697                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2698                 }
2699
2700                 fsp = file_fsp(params,0);
2701                 info_level = SVAL(params,2);
2702
2703                 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
2704
2705                 if(fsp && (fsp->fake_file_handle)) {
2706                         /*
2707                          * This is actually for the QUOTA_FAKE_FILE --metze
2708                          */
2709                                                 
2710                         pstrcpy(fname, fsp->fsp_name);
2711                         /* We know this name is ok, it's already passed the checks. */
2712                         
2713                 } else if(fsp && (fsp->is_directory || fsp->fd == -1)) {
2714                         /*
2715                          * This is actually a QFILEINFO on a directory
2716                          * handle (returned from an NT SMB). NT5.0 seems
2717                          * to do this call. JRA.
2718                          */
2719                         /* We know this name is ok, it's already passed the checks. */
2720                         pstrcpy(fname, fsp->fsp_name);
2721                   
2722                         if (INFO_LEVEL_IS_UNIX(info_level)) {
2723                                 /* Always do lstat for UNIX calls. */
2724                                 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
2725                                         DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
2726                                         return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2727                                 }
2728                         } else if (SMB_VFS_STAT(conn,fname,&sbuf)) {
2729                                 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
2730                                 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2731                         }
2732
2733                         delete_pending = fsp->is_directory ? fsp->directory_delete_on_close : 0;
2734                 } else {
2735                         /*
2736                          * Original code - this is an open file.
2737                          */
2738                         CHECK_FSP(fsp,conn);
2739
2740                         pstrcpy(fname, fsp->fsp_name);
2741                         if (SMB_VFS_FSTAT(fsp,fsp->fd,&sbuf) != 0) {
2742                                 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
2743                                 return(UNIXERROR(ERRDOS,ERRbadfid));
2744                         }
2745                         pos = fsp->position_information;
2746                         delete_pending = fsp->delete_on_close;
2747                         desired_access = fsp->desired_access;
2748                 }
2749         } else {
2750                 NTSTATUS status = NT_STATUS_OK;
2751
2752                 /* qpathinfo */
2753                 if (total_params < 6) {
2754                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2755                 }
2756
2757                 info_level = SVAL(params,0);
2758
2759                 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
2760
2761                 srvstr_get_path(inbuf, fname, &params[6], sizeof(fname), -1, STR_TERMINATE, &status, False);
2762                 if (!NT_STATUS_IS_OK(status)) {
2763                         return ERROR_NT(status);
2764                 }
2765
2766                 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
2767
2768                 unix_convert(fname,conn,0,&bad_path,&sbuf);
2769                 if (bad_path) {
2770                         return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
2771                 }
2772                 if (!check_name(fname,conn)) {
2773                         DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
2774                         return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2775                 }
2776
2777                 if (INFO_LEVEL_IS_UNIX(info_level)) {
2778                         /* Always do lstat for UNIX calls. */
2779                         if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
2780                                 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
2781                                 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2782                         }
2783                 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) {
2784                         DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
2785                         return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2786                 }
2787         }
2788
2789         if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions())
2790                 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2791
2792         DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
2793                 fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
2794
2795         p = strrchr_m(fname,'/'); 
2796         if (!p)
2797                 base_name = fname;
2798         else
2799                 base_name = p+1;
2800
2801         mode = dos_mode(conn,fname,&sbuf);
2802         if (!mode)
2803                 mode = FILE_ATTRIBUTE_NORMAL;
2804
2805         fullpathname = fname;
2806         file_size = get_file_size(sbuf);
2807         if (mode & aDIR) {
2808                 /* This is necessary, as otherwise the desktop.ini file in
2809                  * this folder is ignored */
2810                 mode |= (lp_profile_acls(SNUM(conn)) ? aRONLY : 0);
2811                 file_size = 0;
2812         }
2813
2814         /* Pull any EA list from the data portion. */
2815         if (info_level == SMB_INFO_QUERY_EAS_FROM_LIST) {
2816                 uint32 ea_size;
2817
2818                 if (total_data < 4) {
2819                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2820                 }
2821                 ea_size = IVAL(pdata,0);
2822
2823                 if (total_data > 0 && ea_size != total_data) {
2824                         DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
2825 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2826                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2827                 }
2828
2829                 if (!lp_ea_support(SNUM(conn))) {
2830                         return ERROR_DOS(ERRDOS,ERReasnotsupported);
2831                 }
2832
2833                 if ((ea_ctx = talloc_init("ea_list")) == NULL) {
2834                         return ERROR_NT(NT_STATUS_NO_MEMORY);
2835                 }
2836
2837                 /* Pull out the list of names. */
2838                 ea_list = read_ea_name_list(ea_ctx, pdata + 4, ea_size - 4);
2839                 if (!ea_list) {
2840                         talloc_destroy(ea_ctx);
2841                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2842                 }
2843         }
2844
2845         params = SMB_REALLOC(*pparams,2);
2846         if (params == NULL) {
2847                 talloc_destroy(ea_ctx);
2848                 return ERROR_NT(NT_STATUS_NO_MEMORY);
2849         }
2850         *pparams = params;
2851         memset((char *)params,'\0',2);
2852         data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
2853         pdata = SMB_REALLOC(*ppdata, data_size); 
2854         if ( pdata == NULL ) {
2855                 talloc_destroy(ea_ctx);
2856                 return ERROR_NT(NT_STATUS_NO_MEMORY);
2857         }
2858         *ppdata = pdata;
2859
2860         memset((char *)pdata,'\0',data_size);
2861
2862         c_time = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
2863
2864         allocation_size = get_allocation_size(conn,fsp,&sbuf);
2865
2866         if (fsp) {
2867                 if (fsp->pending_modtime) {
2868                         /* the pending modtime overrides the current modtime */
2869                         sbuf.st_mtime = fsp->pending_modtime;
2870                 }
2871         } else {
2872                 /* Do we have this path open ? */
2873                 files_struct *fsp1 = file_find_di_first(sbuf.st_dev, sbuf.st_ino);
2874                 if (fsp1 && fsp1->pending_modtime) {
2875                         /* the pending modtime overrides the current modtime */
2876                         sbuf.st_mtime = fsp1->pending_modtime;
2877                 }
2878                 if (fsp1 && fsp1->initial_allocation_size) {
2879                         allocation_size = get_allocation_size(conn, fsp1, &sbuf);
2880                 }
2881         }
2882
2883         if (lp_dos_filetime_resolution(SNUM(conn))) {
2884                 c_time &= ~1;
2885                 sbuf.st_atime &= ~1;
2886                 sbuf.st_ctime &= ~1;
2887                 sbuf.st_mtime &= ~1;
2888         }
2889
2890         /* NT expects the name to be in an exact form of the *full*
2891            filename. See the trans2 torture test */
2892         if (strequal(base_name,".")) {
2893                 pstrcpy(dos_fname, "\\");
2894         } else {
2895                 pstr_sprintf(dos_fname, "\\%s", fname);
2896                 string_replace(dos_fname, '/', '\\');
2897         }
2898
2899         switch (info_level) {
2900                 case SMB_INFO_STANDARD:
2901                         DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
2902                         data_size = 22;
2903                         put_dos_date2(pdata,l1_fdateCreation,c_time);
2904                         put_dos_date2(pdata,l1_fdateLastAccess,sbuf.st_atime);
2905                         put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime); /* write time */
2906                         SIVAL(pdata,l1_cbFile,(uint32)file_size);
2907                         SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
2908                         SSVAL(pdata,l1_attrFile,mode);
2909                         break;
2910
2911                 case SMB_INFO_QUERY_EA_SIZE:
2912                 {
2913                         unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
2914                         DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
2915                         data_size = 26;
2916                         put_dos_date2(pdata,l1_fdateCreation,c_time);
2917                         put_dos_date2(pdata,l1_fdateLastAccess,sbuf.st_atime);
2918                         put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime); /* write time */
2919                         SIVAL(pdata,l1_cbFile,(uint32)file_size);
2920                         SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
2921                         SSVAL(pdata,l1_attrFile,mode);
2922                         SIVAL(pdata,l1_attrFile+2,ea_size);
2923                         break;
2924                 }
2925
2926                 case SMB_INFO_IS_NAME_VALID:
2927                         DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
2928                         if (tran_call == TRANSACT2_QFILEINFO) {
2929                                 /* os/2 needs this ? really ?*/      
2930                                 return ERROR_DOS(ERRDOS,ERRbadfunc); 
2931                         }
2932                         data_size = 0;
2933                         param_size = 0;
2934                         break;
2935                         
2936                 case SMB_INFO_QUERY_EAS_FROM_LIST:
2937                 {
2938                         size_t total_ea_len = 0;
2939                         struct ea_list *ea_file_list = NULL;
2940
2941                         DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
2942
2943                         ea_file_list = get_ea_list_from_file(ea_ctx, conn, fsp, fname, &total_ea_len);
2944                         ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
2945
2946                         if (!ea_list || (total_ea_len > data_size)) {
2947                                 talloc_destroy(ea_ctx);
2948                                 data_size = 4;
2949                                 SIVAL(pdata,0,4);   /* EA List Length must be set to 4 if no EA's. */
2950                                 break;
2951                         }
2952
2953                         data_size = fill_ea_buffer(ea_ctx, pdata, data_size, conn, ea_list);
2954                         talloc_destroy(ea_ctx);
2955                         break;
2956                 }
2957
2958                 case SMB_INFO_QUERY_ALL_EAS:
2959                 {
2960                         /* We have data_size bytes to put EA's into. */
2961                         size_t total_ea_len = 0;
2962
2963                         DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
2964
2965                         ea_ctx = talloc_init("ea_ctx");
2966                         if (!ea_ctx) {
2967                                 return ERROR_NT(NT_STATUS_NO_MEMORY);
2968                         }
2969
2970                         ea_list = get_ea_list_from_file(ea_ctx, conn, fsp, fname, &total_ea_len);
2971                         if (!ea_list || (total_ea_len > data_size)) {
2972                                 talloc_destroy(ea_ctx);
2973                                 data_size = 4;
2974                                 SIVAL(pdata,0,4);   /* EA List Length must be set to 4 if no EA's. */
2975                                 break;
2976                         }
2977
2978                         data_size = fill_ea_buffer(ea_ctx, pdata, data_size, conn, ea_list);
2979                         talloc_destroy(ea_ctx);
2980                         break;
2981                 }
2982
2983                 case SMB_FILE_BASIC_INFORMATION:
2984                 case SMB_QUERY_FILE_BASIC_INFO:
2985
2986                         if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
2987                                 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
2988                                 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
2989                         } else {
2990                                 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
2991                                 data_size = 40;
2992                                 SIVAL(pdata,36,0);
2993                         }
2994                         put_long_date(pdata,c_time);
2995                         put_long_date(pdata+8,sbuf.st_atime);
2996                         put_long_date(pdata+16,sbuf.st_mtime); /* write time */
2997                         put_long_date(pdata+24,sbuf.st_mtime); /* change time */
2998                         SIVAL(pdata,32,mode);
2999
3000                         DEBUG(5,("SMB_QFBI - "));
3001                         {
3002                                 time_t create_time = c_time;
3003                                 DEBUG(5,("create: %s ", ctime(&create_time)));
3004                         }
3005                         DEBUG(5,("access: %s ", ctime(&sbuf.st_atime)));
3006                         DEBUG(5,("write: %s ", ctime(&sbuf.st_mtime)));
3007                         DEBUG(5,("change: %s ", ctime(&sbuf.st_mtime)));
3008                         DEBUG(5,("mode: %x\n", mode));
3009
3010                         break;
3011
3012                 case SMB_FILE_STANDARD_INFORMATION:
3013                 case SMB_QUERY_FILE_STANDARD_INFO:
3014
3015                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
3016                         data_size = 24;
3017                         SOFF_T(pdata,0,allocation_size);
3018                         SOFF_T(pdata,8,file_size);
3019                         if (delete_pending & sbuf.st_nlink)
3020                                 SIVAL(pdata,16,sbuf.st_nlink - 1);
3021                         else
3022                                 SIVAL(pdata,16,sbuf.st_nlink);
3023                         SCVAL(pdata,20,0);
3024                         SCVAL(pdata,21,(mode&aDIR)?1:0);
3025                         break;
3026
3027                 case SMB_FILE_EA_INFORMATION:
3028                 case SMB_QUERY_FILE_EA_INFO:
3029                 {
3030                         unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3031                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
3032                         data_size = 4;
3033                         SIVAL(pdata,0,ea_size);
3034                         break;
3035                 }
3036
3037                 /* Get the 8.3 name - used if NT SMB was negotiated. */
3038                 case SMB_QUERY_FILE_ALT_NAME_INFO:
3039                 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
3040                 {
3041                         pstring short_name;
3042
3043                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
3044                         pstrcpy(short_name,base_name);
3045                         /* Mangle if not already 8.3 */
3046                         if(!mangle_is_8_3(short_name, True)) {
3047                                 mangle_map(short_name,True,True,SNUM(conn));
3048                         }
3049                         len = srvstr_push(outbuf, pdata+4, short_name, -1, STR_UNICODE);
3050                         data_size = 4 + len;
3051                         SIVAL(pdata,0,len);
3052                         break;
3053                 }
3054
3055                 case SMB_QUERY_FILE_NAME_INFO:
3056                         /*
3057                           this must be *exactly* right for ACLs on mapped drives to work
3058                          */
3059                         len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
3060                         DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
3061                         data_size = 4 + len;
3062                         SIVAL(pdata,0,len);
3063                         break;
3064
3065                 case SMB_FILE_ALLOCATION_INFORMATION:
3066                 case SMB_QUERY_FILE_ALLOCATION_INFO:
3067                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
3068                         data_size = 8;
3069                         SOFF_T(pdata,0,allocation_size);
3070                         break;
3071
3072                 case SMB_FILE_END_OF_FILE_INFORMATION:
3073                 case SMB_QUERY_FILE_END_OF_FILEINFO:
3074                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
3075                         data_size = 8;
3076                         SOFF_T(pdata,0,file_size);
3077                         break;
3078
3079                 case SMB_QUERY_FILE_ALL_INFO:
3080                 case SMB_FILE_ALL_INFORMATION:
3081                 {
3082                         unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3083                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
3084                         put_long_date(pdata,c_time);
3085                         put_long_date(pdata+8,sbuf.st_atime);
3086                         put_long_date(pdata+16,sbuf.st_mtime); /* write time */
3087                         put_long_date(pdata+24,sbuf.st_mtime); /* change time */
3088                         SIVAL(pdata,32,mode);
3089                         pdata += 40;
3090                         SOFF_T(pdata,0,allocation_size);
3091                         SOFF_T(pdata,8,file_size);
3092                         if (delete_pending && sbuf.st_nlink)
3093                                 SIVAL(pdata,16,sbuf.st_nlink - 1);
3094                         else
3095                                 SIVAL(pdata,16,sbuf.st_nlink);
3096                         SCVAL(pdata,20,delete_pending);
3097                         SCVAL(pdata,21,(mode&aDIR)?1:0);
3098                         pdata += 24;
3099                         SIVAL(pdata,0,ea_size);
3100                         pdata += 4; /* EA info */
3101                         len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
3102                         SIVAL(pdata,0,len);
3103                         pdata += 4 + len;
3104                         data_size = PTR_DIFF(pdata,(*ppdata));
3105                         break;
3106                 }
3107                 case SMB_FILE_INTERNAL_INFORMATION:
3108                         /* This should be an index number - looks like
3109                            dev/ino to me :-) 
3110
3111                            I think this causes us to fail the IFSKIT
3112                            BasicFileInformationTest. -tpot */
3113
3114                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
3115                         SIVAL(pdata,0,sbuf.st_dev);
3116                         SIVAL(pdata,4,sbuf.st_ino);
3117                         data_size = 8;
3118                         break;
3119
3120                 case SMB_FILE_ACCESS_INFORMATION:
3121                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
3122                         SIVAL(pdata,0,desired_access);
3123                         data_size = 4;
3124                         break;
3125
3126                 case SMB_FILE_NAME_INFORMATION:
3127                         /* Pathname with leading '\'. */
3128                         {
3129                                 size_t byte_len;
3130                                 byte_len = dos_PutUniCode(pdata+4,dos_fname,max_data_bytes,False);
3131                                 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
3132                                 SIVAL(pdata,0,byte_len);
3133                                 data_size = 4 + byte_len;
3134                                 break;
3135                         }
3136
3137                 case SMB_FILE_DISPOSITION_INFORMATION:
3138                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
3139                         data_size = 1;
3140                         SCVAL(pdata,0,delete_pending);
3141                         break;
3142
3143                 case SMB_FILE_POSITION_INFORMATION:
3144                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
3145                         data_size = 8;
3146                         SOFF_T(pdata,0,pos);
3147                         break;
3148
3149                 case SMB_FILE_MODE_INFORMATION:
3150                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
3151                         SIVAL(pdata,0,mode);
3152                         data_size = 4;
3153                         break;
3154
3155                 case SMB_FILE_ALIGNMENT_INFORMATION:
3156                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
3157                         SIVAL(pdata,0,0); /* No alignment needed. */
3158                         data_size = 4;
3159                         break;
3160
3161 #if 0
3162                 /*
3163                  * NT4 server just returns "invalid query" to this - if we try to answer
3164                  * it then NTws gets a BSOD! (tridge).
3165                  * W2K seems to want this. JRA.
3166                  */
3167                 case SMB_QUERY_FILE_STREAM_INFO:
3168 #endif
3169                 case SMB_FILE_STREAM_INFORMATION:
3170                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STREAM_INFORMATION\n"));
3171                         if (mode & aDIR) {
3172                                 data_size = 0;
3173                         } else {
3174                                 size_t byte_len = dos_PutUniCode(pdata+24,"::$DATA", 0xE, False);
3175                                 SIVAL(pdata,0,0); /* ??? */
3176                                 SIVAL(pdata,4,byte_len); /* Byte length of unicode string ::$DATA */
3177                                 SOFF_T(pdata,8,file_size);
3178                                 SIVAL(pdata,16,allocation_size);
3179                                 SIVAL(pdata,20,0); /* ??? */
3180                                 data_size = 24 + byte_len;
3181                         }
3182                         break;
3183
3184                 case SMB_QUERY_COMPRESSION_INFO:
3185                 case SMB_FILE_COMPRESSION_INFORMATION:
3186                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
3187                         SOFF_T(pdata,0,file_size);
3188                         SIVAL(pdata,8,0); /* ??? */
3189                         SIVAL(pdata,12,0); /* ??? */
3190                         data_size = 16;
3191                         break;
3192
3193                 case SMB_FILE_NETWORK_OPEN_INFORMATION:
3194                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
3195                         put_long_date(pdata,c_time);
3196                         put_long_date(pdata+8,sbuf.st_atime);
3197                         put_long_date(pdata+16,sbuf.st_mtime); /* write time */
3198                         put_long_date(pdata+24,sbuf.st_mtime); /* change time */
3199                         SIVAL(pdata,32,allocation_size);
3200                         SOFF_T(pdata,40,file_size);
3201                         SIVAL(pdata,48,mode);
3202                         SIVAL(pdata,52,0); /* ??? */
3203                         data_size = 56;
3204                         break;
3205
3206                 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
3207                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
3208                         SIVAL(pdata,0,mode);
3209                         SIVAL(pdata,4,0);
3210                         data_size = 8;
3211                         break;
3212
3213                 /*
3214                  * CIFS UNIX Extensions.
3215                  */
3216
3217                 case SMB_QUERY_FILE_UNIX_BASIC:
3218
3219                         DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC\n"));
3220                         DEBUG(4,("call_trans2qfilepathinfo: st_mode=%o\n",(int)sbuf.st_mode));
3221
3222                         SOFF_T(pdata,0,get_file_size(sbuf));             /* File size 64 Bit */
3223                         pdata += 8;
3224
3225                         SOFF_T(pdata,0,get_allocation_size(conn,fsp,&sbuf)); /* Number of bytes used on disk - 64 Bit */
3226                         pdata += 8;
3227
3228                         put_long_date(pdata,sbuf.st_ctime);       /* Creation Time 64 Bit */
3229                         put_long_date(pdata+8,sbuf.st_atime);     /* Last access time 64 Bit */
3230                         put_long_date(pdata+16,sbuf.st_mtime);    /* Last modification time 64 Bit */
3231                         pdata += 24;
3232
3233                         SIVAL(pdata,0,sbuf.st_uid);               /* user id for the owner */
3234                         SIVAL(pdata,4,0);
3235                         pdata += 8;
3236
3237                         SIVAL(pdata,0,sbuf.st_gid);               /* group id of owner */
3238                         SIVAL(pdata,4,0);
3239                         pdata += 8;
3240
3241                         SIVAL(pdata,0,unix_filetype(sbuf.st_mode));
3242                         pdata += 4;
3243
3244                         SIVAL(pdata,0,unix_dev_major(sbuf.st_rdev));   /* Major device number if type is device */
3245                         SIVAL(pdata,4,0);
3246                         pdata += 8;
3247
3248                         SIVAL(pdata,0,unix_dev_minor(sbuf.st_rdev));   /* Minor device number if type is device */
3249                         SIVAL(pdata,4,0);
3250                         pdata += 8;
3251
3252                         SINO_T(pdata,0,(SMB_INO_T)sbuf.st_ino);   /* inode number */
3253                         pdata += 8;
3254                                 
3255                         SIVAL(pdata,0, unix_perms_to_wire(sbuf.st_mode));     /* Standard UNIX file permissions */
3256                         SIVAL(pdata,4,0);
3257                         pdata += 8;
3258
3259                         SIVAL(pdata,0,sbuf.st_nlink);             /* number of hard links */
3260                         SIVAL(pdata,4,0);
3261                         pdata += 8+1;
3262                         data_size = PTR_DIFF(pdata,(*ppdata));
3263
3264                         {
3265                                 int i;
3266                                 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC"));
3267
3268                                 for (i=0; i<100; i++)
3269                                         DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
3270                                 DEBUG(4,("\n"));
3271                         }
3272
3273                         break;
3274
3275                 case SMB_QUERY_FILE_UNIX_LINK:
3276                         {
3277                                 pstring buffer;
3278
3279                                 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
3280 #ifdef S_ISLNK
3281                                 if(!S_ISLNK(sbuf.st_mode))
3282                                         return(UNIXERROR(ERRSRV,ERRbadlink));
3283 #else
3284                                 return(UNIXERROR(ERRDOS,ERRbadlink));
3285 #endif
3286                                 len = SMB_VFS_READLINK(conn,fullpathname, buffer, sizeof(pstring)-1);     /* read link */
3287                                 if (len == -1)
3288                                         return(UNIXERROR(ERRDOS,ERRnoaccess));
3289                                 buffer[len] = 0;
3290                                 len = srvstr_push(outbuf, pdata, buffer, -1, STR_TERMINATE);
3291                                 pdata += len;
3292                                 data_size = PTR_DIFF(pdata,(*ppdata));
3293
3294                                 break;
3295                         }
3296
3297 #if defined(HAVE_POSIX_ACLS)
3298                 case SMB_QUERY_POSIX_ACL:
3299                         {
3300                                 SMB_ACL_T file_acl = NULL;
3301                                 SMB_ACL_T def_acl = NULL;
3302                                 uint16 num_file_acls = 0;
3303                                 uint16 num_def_acls = 0;
3304
3305                                 if (fsp && !fsp->is_directory && (fsp->fd != -1)) {
3306                                         file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp, fsp->fd);
3307                                 } else {
3308                                         file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
3309                                 }
3310
3311                                 if (file_acl == NULL && no_acl_syscall_error(errno)) {
3312                                         DEBUG(5,("call_trans2qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
3313                                                 fname ));
3314                                         return ERROR_NT(NT_STATUS_NOT_IMPLEMENTED);
3315                                 }
3316
3317                                 if (S_ISDIR(sbuf.st_mode)) {
3318                                         if (fsp && fsp->is_directory) {
3319                                                 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT);
3320                                         } else {
3321                                                 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT);
3322                                         }
3323                                         def_acl = free_empty_sys_acl(conn, def_acl);
3324                                 }
3325
3326                                 num_file_acls = count_acl_entries(conn, file_acl);
3327                                 num_def_acls = count_acl_entries(conn, def_acl);
3328
3329                                 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
3330                                         DEBUG(5,("call_trans2qfilepathinfo: data_size too small (%u) need %u\n",
3331                                                 data_size,
3332                                                 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
3333                                                         SMB_POSIX_ACL_HEADER_SIZE) ));
3334                                         if (file_acl) {
3335                                                 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3336                                         }
3337                                         if (def_acl) {
3338                                                 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3339                                         }
3340                                         return ERROR_NT(NT_STATUS_BUFFER_TOO_SMALL);
3341                                 }
3342
3343                                 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
3344                                 SSVAL(pdata,2,num_file_acls);
3345                                 SSVAL(pdata,4,num_def_acls);
3346                                 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
3347                                         if (file_acl) {
3348                                                 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3349                                         }
3350                                         if (def_acl) {
3351                                                 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3352                                         }
3353                                         return ERROR_NT(NT_STATUS_INTERNAL_ERROR);
3354                                 }
3355                                 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
3356                                         if (file_acl) {
3357                                                 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3358                                         }
3359                                         if (def_acl) {
3360                                                 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3361                                         }
3362                                         return ERROR_NT(NT_STATUS_INTERNAL_ERROR);
3363                                 }
3364
3365                                 if (file_acl) {
3366                                         SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3367                                 }
3368                                 if (def_acl) {
3369                                         SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3370                                 }
3371                                 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
3372                                 break;
3373                         }
3374 #endif
3375
3376                 default:
3377                         return ERROR_DOS(ERRDOS,ERRunknownlevel);
3378         }
3379
3380         send_trans2_replies(outbuf, bufsize, params, param_size, *ppdata, data_size);
3381
3382         return(-1);
3383 }
3384
3385 /****************************************************************************
3386  Deal with the internal needs of setting the delete on close flag. Note that
3387  as the tdb locking is recursive, it is safe to call this from within 
3388  open_file_shared. JRA.
3389 ****************************************************************************/
3390
3391 NTSTATUS set_delete_on_close_internal(files_struct *fsp, BOOL delete_on_close, uint32 dosmode)
3392 {
3393         if (delete_on_close) {
3394                 /*
3395                  * Only allow delete on close for writable files.
3396                  */
3397
3398                 if (!lp_delete_readonly(SNUM(fsp->conn))) {
3399                         if (dosmode & aRONLY) {
3400                                 DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but file attribute is readonly.\n",
3401                                         fsp->fsp_name ));
3402                                 return NT_STATUS_CANNOT_DELETE;
3403                         }
3404                 }
3405
3406                 /*
3407                  * Only allow delete on close for writable shares.
3408                  */
3409
3410                 if (!CAN_WRITE(fsp->conn)) {
3411                         DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but write access denied on share.\n",
3412                                 fsp->fsp_name ));
3413                         return NT_STATUS_ACCESS_DENIED;
3414                 }
3415
3416                 /*
3417                  * Only allow delete on close for files/directories opened with delete intent.
3418                  */
3419
3420                 if (!(fsp->desired_access & DELETE_ACCESS)) {
3421                         DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but delete access denied.\n",
3422                                 fsp->fsp_name ));
3423                         return NT_STATUS_ACCESS_DENIED;
3424                 }
3425         }
3426
3427         if(fsp->is_directory) {
3428                 fsp->directory_delete_on_close = delete_on_close;
3429                 DEBUG(10, ("set_delete_on_close_internal: %s delete on close flag for fnum = %d, directory %s\n",
3430                         delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name ));
3431         } else {
3432                 fsp->delete_on_close = delete_on_close;
3433                 DEBUG(10, ("set_delete_on_close_internal: %s delete on close flag for fnum = %d, file %s\n",
3434                         delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name ));
3435         }
3436
3437         return NT_STATUS_OK;
3438 }
3439
3440 /****************************************************************************
3441  Sets the delete on close flag over all share modes on this file.
3442  Modify the share mode entry for all files open
3443  on this device and inode to tell other smbds we have
3444  changed the delete on close flag. This will be noticed
3445  in the close code, the last closer will delete the file
3446  if flag is set.
3447 ****************************************************************************/
3448
3449 NTSTATUS set_delete_on_close_over_all(files_struct *fsp, BOOL delete_on_close)
3450 {
3451         DEBUG(10,("set_delete_on_close_over_all: %s delete on close flag for fnum = %d, file %s\n",
3452                 delete_on_close ? "Adding" : "Removing", fsp->fnum, fsp->fsp_name ));
3453
3454         if (fsp->is_directory || fsp->is_stat)
3455                 return NT_STATUS_OK;
3456
3457         if (lock_share_entry_fsp(fsp) == False)
3458                 return NT_STATUS_ACCESS_DENIED;
3459
3460         if (!modify_delete_flag(fsp->dev, fsp->inode, delete_on_close)) {
3461                 DEBUG(0,("set_delete_on_close_over_all: failed to change delete on close flag for file %s\n",
3462                         fsp->fsp_name ));
3463                 unlock_share_entry_fsp(fsp);
3464                 return NT_STATUS_ACCESS_DENIED;
3465         }
3466
3467         unlock_share_entry_fsp(fsp);
3468         return NT_STATUS_OK;
3469 }
3470
3471 /****************************************************************************
3472  Set a hard link (called by UNIX extensions and by NT rename with HARD link
3473  code.
3474 ****************************************************************************/
3475
3476 NTSTATUS hardlink_internals(connection_struct *conn, char *oldname, char *newname)
3477 {
3478         BOOL bad_path_oldname = False;
3479         BOOL bad_path_newname = False;
3480         SMB_STRUCT_STAT sbuf1, sbuf2;
3481         pstring last_component_oldname;
3482         pstring last_component_newname;
3483         NTSTATUS status = NT_STATUS_OK;
3484
3485         ZERO_STRUCT(sbuf1);
3486         ZERO_STRUCT(sbuf2);
3487
3488         /* No wildcards. */
3489         if (ms_has_wild(newname) || ms_has_wild(oldname)) {
3490                 return NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
3491         }
3492
3493         unix_convert(oldname,conn,last_component_oldname,&bad_path_oldname,&sbuf1);
3494         if (bad_path_oldname) {
3495                 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3496         }
3497
3498         /* Quick check for "." and ".." */
3499         if (last_component_oldname[0] == '.') {
3500                 if (!last_component_oldname[1] || (last_component_oldname[1] == '.' && !last_component_oldname[2])) {
3501                         return NT_STATUS_OBJECT_NAME_INVALID;
3502                 }
3503         }
3504
3505         /* source must already exist. */
3506         if (!VALID_STAT(sbuf1)) {
3507                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3508         }
3509
3510         if (!check_name(oldname,conn)) {
3511                 return NT_STATUS_ACCESS_DENIED;
3512         }
3513
3514         unix_convert(newname,conn,last_component_newname,&bad_path_newname,&sbuf2);
3515         if (bad_path_newname) {
3516                 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3517         }
3518
3519         /* Quick check for "." and ".." */
3520         if (last_component_newname[0] == '.') {
3521                 if (!last_component_newname[1] || (last_component_newname[1] == '.' && !last_component_newname[2])) {
3522                         return NT_STATUS_OBJECT_NAME_INVALID;
3523                 }
3524         }
3525
3526         /* Disallow if newname already exists. */
3527         if (VALID_STAT(sbuf2)) {
3528                 return NT_STATUS_OBJECT_NAME_COLLISION;
3529         }
3530
3531         if (!check_name(newname,conn)) {
3532                 return NT_STATUS_ACCESS_DENIED;
3533         }
3534
3535         /* No links from a directory. */
3536         if (S_ISDIR(sbuf1.st_mode)) {
3537                 return NT_STATUS_FILE_IS_A_DIRECTORY;
3538         }
3539
3540         /* Ensure this is within the share. */
3541         if (!reduce_name(conn, oldname) != 0)
3542                 return NT_STATUS_ACCESS_DENIED;
3543
3544         DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
3545
3546         if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
3547                 status = map_nt_error_from_unix(errno);
3548                 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
3549                                 nt_errstr(status), newname, oldname));
3550         }
3551
3552         return status;
3553 }
3554
3555 /****************************************************************************
3556  Reply to a TRANS2_SETFILEINFO (set file info by fileid).
3557 ****************************************************************************/
3558
3559 static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
3560                                         char **pparams, int total_params, char **ppdata, int total_data,
3561                                         unsigned int max_data_bytes)
3562 {
3563         char *params = *pparams;
3564         char *pdata = *ppdata;
3565         uint16 tran_call = SVAL(inbuf, smb_setup0);
3566         uint16 info_level;
3567         int dosmode=0;
3568         SMB_OFF_T size=0;
3569         struct utimbuf tvs;
3570         SMB_STRUCT_STAT sbuf;
3571         pstring fname;
3572         int fd = -1;
3573         BOOL bad_path = False;
3574         files_struct *fsp = NULL;
3575         uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
3576         gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
3577         mode_t unixmode = 0;
3578         NTSTATUS status = NT_STATUS_OK;
3579
3580         if (!params)
3581                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3582
3583         ZERO_STRUCT(sbuf);
3584
3585         if (tran_call == TRANSACT2_SETFILEINFO) {
3586                 if (total_params < 4) {
3587                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3588                 }
3589
3590                 fsp = file_fsp(params,0);
3591                 info_level = SVAL(params,2);    
3592
3593                 if(fsp && (fsp->is_directory || fsp->fd == -1)) {
3594                         /*
3595                          * This is actually a SETFILEINFO on a directory
3596                          * handle (returned from an NT SMB). NT5.0 seems
3597                          * to do this call. JRA.
3598                          */
3599                         pstrcpy(fname, fsp->fsp_name);
3600                         if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
3601                                 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
3602                                 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
3603                         }
3604                 } else if (fsp && fsp->print_file) {
3605                         /*
3606                          * Doing a DELETE_ON_CLOSE should cancel a print job.
3607                          */
3608                         if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
3609                                 fsp->share_mode = FILE_DELETE_ON_CLOSE;
3610
3611                                 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
3612         
3613                                 SSVAL(params,0,0);
3614                                 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3615                                 return(-1);
3616                         } else
3617                                 return (UNIXERROR(ERRDOS,ERRbadpath));
3618             } else {
3619                         /*
3620                          * Original code - this is an open file.
3621                          */
3622                         CHECK_FSP(fsp,conn);
3623
3624                         pstrcpy(fname, fsp->fsp_name);
3625                         fd = fsp->fd;
3626
3627                         if (SMB_VFS_FSTAT(fsp,fd,&sbuf) != 0) {
3628                                 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
3629                                 return(UNIXERROR(ERRDOS,ERRbadfid));
3630                         }
3631                 }
3632         } else {
3633                 /* set path info */
3634                 if (total_params < 6) {
3635                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3636                 }
3637
3638                 info_level = SVAL(params,0);    
3639                 srvstr_get_path(inbuf, fname, &params[6], sizeof(fname), -1, STR_TERMINATE, &status, False);
3640                 if (!NT_STATUS_IS_OK(status)) {
3641                         return ERROR_NT(status);
3642                 }
3643                 unix_convert(fname,conn,0,&bad_path,&sbuf);
3644                 if (bad_path) {
3645                         return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
3646                 }
3647
3648                 /*
3649                  * For CIFS UNIX extensions the target name may not exist.
3650                  */
3651
3652                 if(!VALID_STAT(sbuf) && !INFO_LEVEL_IS_UNIX(info_level)) {
3653                         DEBUG(3,("call_trans2setfilepathinfo: stat of %s failed (%s)\n", fname, strerror(errno)));
3654                         return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
3655                 }    
3656
3657                 if(!check_name(fname, conn)) {
3658                         return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
3659                 }
3660
3661         }
3662
3663         if (!CAN_WRITE(conn))
3664                 return ERROR_DOS(ERRSRV,ERRaccess);
3665
3666         if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions())
3667                 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3668
3669         if (VALID_STAT(sbuf))
3670                 unixmode = sbuf.st_mode;
3671
3672         DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
3673                 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
3674
3675         /* Realloc the parameter size */
3676         params = SMB_REALLOC(*pparams,2);
3677         if(params == NULL) {
3678                 return ERROR_NT(NT_STATUS_NO_MEMORY);
3679         }
3680         *pparams = params;
3681
3682         SSVAL(params,0,0);
3683
3684         if (fsp && fsp->pending_modtime) {
3685                 /* the pending modtime overrides the current modtime */
3686                 sbuf.st_mtime = fsp->pending_modtime;
3687         }
3688
3689         size = get_file_size(sbuf);
3690         tvs.modtime = sbuf.st_mtime;
3691         tvs.actime = sbuf.st_atime;
3692         dosmode = dos_mode(conn,fname,&sbuf);
3693         unixmode = sbuf.st_mode;
3694
3695         set_owner = VALID_STAT(sbuf) ? sbuf.st_uid : (uid_t)SMB_UID_NO_CHANGE;
3696         set_grp = VALID_STAT(sbuf) ? sbuf.st_gid : (gid_t)SMB_GID_NO_CHANGE;
3697
3698         switch (info_level) {
3699                 case SMB_INFO_STANDARD:
3700                 {
3701                         if (total_data < 12) {
3702                                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3703                         }
3704
3705                         /* access time */
3706                         tvs.actime = make_unix_date2(pdata+l1_fdateLastAccess);
3707                         /* write time */
3708                         tvs.modtime = make_unix_date2(pdata+l1_fdateLastWrite);
3709                         break;
3710                 }
3711
3712                 case SMB_INFO_SET_EA:
3713                 {
3714                         struct ea_list *ea_list = NULL;
3715                         TALLOC_CTX *ctx = NULL;
3716
3717                         if (total_data < 10) {
3718                                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3719                         }
3720
3721                         if (IVAL(pdata,0) > total_data) {
3722                                 DEBUG(10,("call_trans2setfilepathinfo: bad total data size (%u) > %u\n",
3723                                         IVAL(pdata,0), (unsigned int)total_data));
3724                                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3725                         }
3726
3727                         ctx = talloc_init("SMB_INFO_SET_EA");
3728                         if (!ctx) {
3729                                 return ERROR_NT(NT_STATUS_NO_MEMORY);
3730                         }
3731                         ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
3732                         if (!ea_list) {
3733                                 talloc_destroy(ctx);
3734                                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3735                         }
3736                         status = set_ea(conn, fsp, fname, ea_list);
3737                         talloc_destroy(ctx);
3738
3739                         if (!NT_STATUS_IS_OK(status)) {
3740                                 return ERROR_NT(status);
3741                         }
3742                         break;
3743                 }
3744
3745 #if 0
3746                 /* The following 2 info levels are only valid on query, not set. Remove them. JRA. */
3747                 /* XXXX um, i don't think this is right.
3748                         it's also not in the cifs6.txt spec.
3749                 */
3750                 case SMB_INFO_QUERY_EAS_FROM_LIST:
3751                         if (total_data < 28)
3752                                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3753
3754                         tvs.actime = make_unix_date2(pdata+8);
3755                         tvs.modtime = make_unix_date2(pdata+12);
3756                         size = IVAL(pdata,16);
3757                         dosmode = IVAL(pdata,24);
3758                         break;
3759
3760                 /* XXXX nor this.  not in cifs6.txt, either. */
3761                 case SMB_INFO_QUERY_ALL_EAS:
3762                         if (total_data < 28)
3763                                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3764
3765                         tvs.actime = make_unix_date2(pdata+8);
3766                         tvs.modtime = make_unix_date2(pdata+12);
3767                         size = IVAL(pdata,16);
3768                         dosmode = IVAL(pdata,24);
3769                         break;
3770 #endif
3771
3772                 case SMB_SET_FILE_BASIC_INFO:
3773                 case SMB_FILE_BASIC_INFORMATION:
3774                 {
3775                         /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
3776                         time_t write_time;
3777                         time_t changed_time;
3778
3779                         if (total_data < 36) {
3780                                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3781                         }
3782
3783                         /* Ignore create time at offset pdata. */
3784
3785                         /* access time */
3786                         tvs.actime = interpret_long_date(pdata+8);
3787
3788                         write_time = interpret_long_date(pdata+16);
3789                         changed_time = interpret_long_date(pdata+24);
3790
3791                         tvs.modtime = MIN(write_time, changed_time);
3792
3793                         if (write_time > tvs.modtime && write_time != (time_t)-1) {
3794                                 tvs.modtime = write_time;
3795                         }
3796                         /* Prefer a defined time to an undefined one. */
3797                         if (null_mtime(tvs.modtime)) {
3798                                 tvs.modtime = null_mtime(write_time) ? changed_time : write_time;
3799                         }
3800
3801                         /* attributes */
3802                         dosmode = IVAL(pdata,32);
3803                         break;
3804                 }
3805
3806                 case SMB_FILE_ALLOCATION_INFORMATION:
3807                 case SMB_SET_FILE_ALLOCATION_INFO:
3808                 {
3809                         int ret = -1;
3810                         SMB_BIG_UINT allocation_size;
3811
3812                         if (total_data < 8) {
3813                                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3814                         }
3815
3816                         allocation_size = (SMB_BIG_UINT)IVAL(pdata,0);
3817 #ifdef LARGE_SMB_OFF_T
3818                         allocation_size |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
3819 #else /* LARGE_SMB_OFF_T */
3820                         if (IVAL(pdata,4) != 0) /* more than 32 bits? */
3821                                 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3822 #endif /* LARGE_SMB_OFF_T */
3823                         DEBUG(10,("call_trans2setfilepathinfo: Set file allocation info for file %s to %.0f\n",
3824                                         fname, (double)allocation_size ));
3825
3826                         if (allocation_size) {
3827                                 allocation_size = smb_roundup(conn, allocation_size);
3828                         }
3829
3830                         if(allocation_size != get_file_size(sbuf)) {
3831                                 SMB_STRUCT_STAT new_sbuf;
3832  
3833                                 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new allocation size to %.0f\n",
3834                                         fname, (double)allocation_size ));
3835  
3836                                 if (fd == -1) {
3837                                         files_struct *new_fsp = NULL;
3838                                         int access_mode = 0;
3839                                         int action = 0;
3840  
3841                                         if(global_oplock_break) {
3842                                                 /* Queue this file modify as we are the process of an oplock break.  */
3843  
3844                                                 DEBUG(2,("call_trans2setfilepathinfo: queueing message due to being "));
3845                                                 DEBUGADD(2,( "in oplock break state.\n"));
3846  
3847                                                 push_oplock_pending_smb_message(inbuf, length);
3848                                                 return -1;
3849                                         }
3850  
3851                                         new_fsp = open_file_shared1(conn, fname, &sbuf,FILE_WRITE_DATA,
3852                                                                         SET_OPEN_MODE(DOS_OPEN_RDWR),
3853                                                                         (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
3854                                                                         FILE_ATTRIBUTE_NORMAL,
3855                                                                         INTERNAL_OPEN_ONLY, &access_mode, &action);
3856  
3857                                         if (new_fsp == NULL)
3858                                                 return(UNIXERROR(ERRDOS,ERRbadpath));
3859                                         ret = vfs_allocate_file_space(new_fsp, allocation_size);
3860                                         if (SMB_VFS_FSTAT(new_fsp,new_fsp->fd,&new_sbuf) != 0) {
3861                                                 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",
3862                                                                         new_fsp->fnum, strerror(errno)));
3863                                                 ret = -1;
3864                                         }
3865                                         close_file(new_fsp,True);
3866                                 } else {
3867                                         ret = vfs_allocate_file_space(fsp, allocation_size);
3868                                         if (SMB_VFS_FSTAT(fsp,fd,&new_sbuf) != 0) {
3869                                                 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",
3870                                                                         fsp->fnum, strerror(errno)));
3871                                                 ret = -1;
3872                                         }
3873                                 }
3874                                 if (ret == -1)
3875                                         return ERROR_NT(NT_STATUS_DISK_FULL);
3876
3877                                 /* Allocate can truncate size... */
3878                                 size = get_file_size(new_sbuf);
3879                         }
3880
3881                         break;
3882                 }
3883
3884                 case SMB_FILE_END_OF_FILE_INFORMATION:
3885                 case SMB_SET_FILE_END_OF_FILE_INFO:
3886                 {
3887                         if (total_data < 8) {
3888                                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3889                         }
3890
3891                         size = IVAL(pdata,0);
3892 #ifdef LARGE_SMB_OFF_T
3893                         size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
3894 #else /* LARGE_SMB_OFF_T */
3895                         if (IVAL(pdata,4) != 0) /* more than 32 bits? */
3896                                 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3897 #endif /* LARGE_SMB_OFF_T */
3898                         DEBUG(10,("call_trans2setfilepathinfo: Set end of file info for file %s to %.0f\n", fname, (double)size ));
3899                         break;
3900                 }
3901
3902                 case SMB_FILE_DISPOSITION_INFORMATION:
3903                 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
3904                 {
3905                         BOOL delete_on_close;
3906
3907                         if (total_data < 1) {
3908                                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3909                         }
3910
3911                         delete_on_close = (CVAL(pdata,0) ? True : False);
3912
3913                         /* Just ignore this set on a path. */
3914                         if (tran_call != TRANSACT2_SETFILEINFO)
3915                                 break;
3916
3917                         if (fsp == NULL)
3918                                 return(UNIXERROR(ERRDOS,ERRbadfid));
3919
3920                         status = set_delete_on_close_internal(fsp, delete_on_close, dosmode);
3921  
3922                         if (!NT_STATUS_IS_OK(status)) {
3923                                 return ERROR_NT(status);
3924                         }
3925
3926                         /* The set is across all open files on this dev/inode pair. */
3927                         status =set_delete_on_close_over_all(fsp, delete_on_close);
3928                         if (!NT_STATUS_IS_OK(status)) {
3929                                 return ERROR_NT(status);
3930                         }
3931
3932                         break;
3933                 }
3934
3935                 case SMB_FILE_POSITION_INFORMATION:
3936                 {
3937                         SMB_BIG_UINT position_information;
3938
3939                         if (total_data < 8) {
3940                                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3941                         }
3942
3943                         position_information = (SMB_BIG_UINT)IVAL(pdata,0);
3944 #ifdef LARGE_SMB_OFF_T
3945                         position_information |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
3946 #else /* LARGE_SMB_OFF_T */
3947                         if (IVAL(pdata,4) != 0) /* more than 32 bits? */
3948                                 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3949 #endif /* LARGE_SMB_OFF_T */
3950                         DEBUG(10,("call_trans2setfilepathinfo: Set file position information for file %s to %.0f\n",
3951                                         fname, (double)position_information ));
3952                         if (fsp)
3953                                 fsp->position_information = position_information;
3954                         break;
3955                 }
3956
3957                 /* From tridge Samba4 : 
3958                  * MODE_INFORMATION in setfileinfo (I have no
3959                  * idea what "mode information" on a file is - it takes a value of 0,
3960                  * 2, 4 or 6. What could it be?).
3961                  */
3962
3963                 case SMB_FILE_MODE_INFORMATION:
3964                 {
3965                         uint32 mode;
3966
3967                         if (total_data < 4) {
3968                                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3969                         }
3970                         mode = IVAL(pdata,0);
3971                         if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
3972                                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3973                         }
3974                         break;
3975                 }
3976
3977                 /*
3978                  * CIFS UNIX extensions.
3979                  */
3980
3981                 case SMB_SET_FILE_UNIX_BASIC:
3982                 {
3983                         uint32 raw_unixmode;
3984
3985                         if (total_data < 100) {
3986                                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3987                         }
3988
3989                         if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
3990                            IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
3991                                 size=IVAL(pdata,0); /* first 8 Bytes are size */
3992 #ifdef LARGE_SMB_OFF_T
3993                                 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
3994 #else /* LARGE_SMB_OFF_T */
3995                                 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
3996                                         return ERROR_DOS(ERRDOS,ERRunknownlevel);
3997 #endif /* LARGE_SMB_OFF_T */
3998                         }
3999                         pdata+=24;          /* ctime & st_blocks are not changed */
4000                         tvs.actime = interpret_long_date(pdata); /* access_time */
4001                         tvs.modtime = interpret_long_date(pdata+8); /* modification_time */
4002                         pdata+=16;
4003                         set_owner = (uid_t)IVAL(pdata,0);
4004                         pdata += 8;
4005                         set_grp = (gid_t)IVAL(pdata,0);
4006                         pdata += 8;
4007                         raw_unixmode = IVAL(pdata,28);
4008                         unixmode = unix_perms_from_wire(conn, &sbuf, raw_unixmode);
4009                         dosmode = 0; /* Ensure dos mode change doesn't override this. */
4010
4011                         DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC: name = %s \
4012 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
4013                                 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
4014
4015                         if (!VALID_STAT(sbuf)) {
4016
4017                                 /*
4018                                  * The only valid use of this is to create character and block
4019                                  * devices, and named pipes. This is deprecated (IMHO) and 
4020                                  * a new info level should be used for mknod. JRA.
4021                                  */
4022
4023                                 uint32 file_type = IVAL(pdata,0);
4024 #if defined(HAVE_MAKEDEV)
4025                                 uint32 dev_major = IVAL(pdata,4);
4026                                 uint32 dev_minor = IVAL(pdata,12);
4027 #endif
4028
4029                                 uid_t myuid = geteuid();
4030                                 gid_t mygid = getegid();
4031                                 SMB_DEV_T dev = (SMB_DEV_T)0;
4032
4033                                 if (tran_call == TRANSACT2_SETFILEINFO)
4034                                         return(ERROR_DOS(ERRDOS,ERRnoaccess));
4035
4036                                 if (raw_unixmode == SMB_MODE_NO_CHANGE) {
4037                                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4038                                 }
4039
4040 #if defined(HAVE_MAKEDEV)
4041                                 dev = makedev(dev_major, dev_minor);
4042 #endif
4043
4044                                 /* We can only create as the owner/group we are. */
4045
4046                                 if ((set_owner != myuid) && (set_owner != (uid_t)SMB_UID_NO_CHANGE))
4047                                         return(ERROR_DOS(ERRDOS,ERRnoaccess));
4048                                 if ((set_grp != mygid) && (set_grp != (gid_t)SMB_GID_NO_CHANGE))
4049                                         return(ERROR_DOS(ERRDOS,ERRnoaccess));
4050
4051                                 switch (file_type) {
4052 #if defined(S_IFIFO)
4053                                         case UNIX_TYPE_FIFO:
4054                                                 unixmode |= S_IFIFO;
4055                                                 break;
4056 #endif
4057 #if defined(S_IFSOCK)
4058                                         case UNIX_TYPE_SOCKET:
4059                                                 unixmode |= S_IFSOCK;
4060                                                 break;
4061 #endif
4062 #if defined(S_IFCHR)
4063                                         case UNIX_TYPE_CHARDEV:
4064                                                 unixmode |= S_IFCHR;
4065                                                 break;
4066 #endif
4067 #if defined(S_IFBLK)
4068                                         case UNIX_TYPE_BLKDEV:
4069                                                 unixmode |= S_IFBLK;
4070                                                 break;
4071 #endif
4072                                         default:
4073                                                 return(ERROR_DOS(ERRDOS,ERRnoaccess));
4074                                 }
4075
4076                                 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
4077 0%o for file %s\n", (double)dev, unixmode, fname ));
4078
4079                                 /* Ok - do the mknod. */
4080                                 if (SMB_VFS_MKNOD(conn,fname, unixmode, dev) != 0)
4081                                         return(UNIXERROR(ERRDOS,ERRnoaccess));
4082
4083                                 inherit_access_acl(conn, fname, unixmode);
4084
4085                                 SSVAL(params,0,0);
4086                                 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4087                                 return(-1);
4088                         }
4089
4090                         /*
4091                          * Deal with the UNIX specific mode set.
4092                          */
4093
4094                         if (raw_unixmode != SMB_MODE_NO_CHANGE) {
4095                                 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
4096                                         (unsigned int)unixmode, fname ));
4097                                 if (SMB_VFS_CHMOD(conn,fname,unixmode) != 0)
4098                                         return(UNIXERROR(ERRDOS,ERRnoaccess));
4099                         }
4100
4101                         /*
4102                          * Deal with the UNIX specific uid set.
4103                          */
4104
4105                         if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (sbuf.st_uid != set_owner)) {
4106                                 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing owner %u for file %s\n",
4107                                         (unsigned int)set_owner, fname ));
4108                                 if (SMB_VFS_CHOWN(conn,fname,set_owner, (gid_t)-1) != 0)
4109                                         return(UNIXERROR(ERRDOS,ERRnoaccess));
4110                         }
4111
4112                         /*
4113                          * Deal with the UNIX specific gid set.
4114                          */
4115
4116                         if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (sbuf.st_gid != set_grp)) {
4117                                 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
4118                                         (unsigned int)set_owner, fname ));
4119                                 if (SMB_VFS_CHOWN(conn,fname,(uid_t)-1, set_grp) != 0)
4120                                         return(UNIXERROR(ERRDOS,ERRnoaccess));
4121                         }
4122                         break;
4123                 }
4124
4125                 case SMB_SET_FILE_UNIX_LINK:
4126                 {
4127                         pstring link_target;
4128                         char *newname = fname;
4129
4130                         /* Set a symbolic link. */
4131                         /* Don't allow this if follow links is false. */
4132
4133                         if (!lp_symlinks(SNUM(conn)))
4134                                 return(ERROR_DOS(ERRDOS,ERRnoaccess));
4135
4136                         srvstr_pull(inbuf, link_target, pdata, sizeof(link_target), -1, STR_TERMINATE);
4137
4138                         /* !widelinks forces the target path to be within the share. */
4139                         /* This means we can interpret the target as a pathname. */
4140                         if (!lp_widelinks(SNUM(conn))) {
4141                                 pstring rel_name;
4142                                 char *last_dirp = NULL;
4143
4144                                 unix_format(link_target);
4145                                 if (*link_target == '/') {
4146                                         /* No absolute paths allowed. */
4147                                         return(UNIXERROR(ERRDOS,ERRnoaccess));
4148                                 }
4149                                 pstrcpy(rel_name, newname);
4150                                 last_dirp = strrchr_m(rel_name, '/');
4151                                 if (last_dirp) {
4152                                         last_dirp[1] = '\0';
4153                                 } else {
4154                                         pstrcpy(rel_name, "./");
4155                                 }
4156                                 pstrcat(rel_name, link_target);
4157
4158                                 if (!check_name(rel_name, conn)) {
4159                                         return(UNIXERROR(ERRDOS,ERRnoaccess));
4160                                 }
4161                         }
4162
4163                         DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
4164                                 fname, link_target ));
4165
4166                         if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0)
4167                                 return(UNIXERROR(ERRDOS,ERRnoaccess));
4168                         SSVAL(params,0,0);
4169                         send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4170                         return(-1);
4171                 }
4172
4173                 case SMB_SET_FILE_UNIX_HLINK:
4174                 {
4175                         pstring oldname;
4176                         char *newname = fname;
4177
4178                         /* Set a hard link. */
4179                         srvstr_get_path(inbuf, oldname, pdata, sizeof(oldname), -1, STR_TERMINATE, &status, False);
4180                         if (!NT_STATUS_IS_OK(status)) {
4181                                 return ERROR_NT(status);
4182                         }
4183
4184                         DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
4185                                 fname, oldname));
4186
4187                         status = hardlink_internals(conn, oldname, newname);
4188                         if (!NT_STATUS_IS_OK(status)) {
4189                                 return ERROR_NT(status);
4190                         }
4191
4192                         SSVAL(params,0,0);
4193                         send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4194                         return(-1);
4195                 }
4196
4197                 case SMB_FILE_RENAME_INFORMATION:
4198                 {
4199                         BOOL overwrite;
4200                         uint32 root_fid;
4201                         uint32 len;
4202                         pstring newname;
4203                         pstring base_name;
4204                         char *p;
4205
4206                         if (total_data < 12) {
4207                                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4208                         }
4209
4210                         overwrite = (CVAL(pdata,0) ? True : False);
4211                         root_fid = IVAL(pdata,4);
4212                         len = IVAL(pdata,8);
4213                         srvstr_get_path(inbuf, newname, &pdata[12], sizeof(newname), len, 0, &status, False);
4214                         if (!NT_STATUS_IS_OK(status)) {
4215                                 return ERROR_NT(status);
4216                         }
4217
4218                         /* Check the new name has no '/' characters. */
4219                         if (strchr_m(newname, '/'))
4220                                 return ERROR_NT(NT_STATUS_NOT_SUPPORTED);
4221
4222                         RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
4223
4224                         /* Create the base directory. */
4225                         pstrcpy(base_name, fname);
4226                         p = strrchr_m(base_name, '/');
4227                         if (p)
4228                                 *p = '\0';
4229                         /* Append the new name. */
4230                         pstrcat(base_name, "/");
4231                         pstrcat(base_name, newname);
4232
4233                         if (fsp) {
4234                                 DEBUG(10,("call_trans2setfilepathinfo: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
4235                                         fsp->fnum, fsp->fsp_name, base_name ));
4236                                 status = rename_internals_fsp(conn, fsp, base_name, 0, overwrite);
4237                         } else {
4238                                 DEBUG(10,("call_trans2setfilepathinfo: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
4239                                         fname, newname ));
4240                                 status = rename_internals(conn, fname, base_name, 0, overwrite);
4241                         }
4242                         if (!NT_STATUS_IS_OK(status)) {
4243                                 return ERROR_NT(status);
4244                         }
4245                         process_pending_change_notify_queue((time_t)0);
4246                         SSVAL(params,0,0);
4247                         send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4248                         return(-1);
4249                 }
4250
4251 #if defined(HAVE_POSIX_ACLS)
4252                 case SMB_SET_POSIX_ACL:
4253                 {
4254                         uint16 posix_acl_version;
4255                         uint16 num_file_acls;
4256                         uint16 num_def_acls;
4257                         BOOL valid_file_acls = True;
4258                         BOOL valid_def_acls = True;
4259
4260                         if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
4261                                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4262                         }
4263                         posix_acl_version = SVAL(pdata,0);
4264                         num_file_acls = SVAL(pdata,2);
4265                         num_def_acls = SVAL(pdata,4);
4266
4267                         if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
4268                                 valid_file_acls = False;
4269                                 num_file_acls = 0;
4270                         }
4271
4272                         if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
4273                                 valid_def_acls = False;
4274                                 num_def_acls = 0;
4275                         }
4276
4277                         if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
4278                                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4279                         }
4280
4281                         if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
4282                                         (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
4283                                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4284                         }
4285
4286                         if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
4287                                         pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
4288                                 return(UNIXERROR(ERRDOS,ERRnoaccess));
4289                         }
4290
4291                         if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, &sbuf, num_def_acls,
4292                                         pdata + SMB_POSIX_ACL_HEADER_SIZE +
4293                                         (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
4294                                 return(UNIXERROR(ERRDOS,ERRnoaccess));
4295                         }
4296
4297                         SSVAL(params,0,0);
4298                         send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4299                         return(-1);
4300                 }
4301 #endif
4302
4303                 default:
4304                         return ERROR_DOS(ERRDOS,ERRunknownlevel);
4305         }
4306
4307         /* get some defaults (no modifications) if any info is zero or -1. */
4308         if (null_mtime(tvs.actime)) {
4309                 tvs.actime = sbuf.st_atime;
4310         }
4311
4312         if (null_mtime(tvs.modtime)) {
4313                 tvs.modtime = sbuf.st_mtime;
4314         }
4315
4316         DEBUG(6,("actime: %s " , ctime(&tvs.actime)));
4317         DEBUG(6,("modtime: %s ", ctime(&tvs.modtime)));
4318         DEBUG(6,("size: %.0f ", (double)size));
4319
4320         if (dosmode) {
4321                 if (S_ISDIR(sbuf.st_mode))
4322                         dosmode |= aDIR;
4323                 else
4324                         dosmode &= ~aDIR;
4325         }
4326
4327         DEBUG(6,("dosmode: %x\n"  , dosmode));
4328
4329         if(!((info_level == SMB_SET_FILE_END_OF_FILE_INFO) ||
4330                 (info_level == SMB_SET_FILE_ALLOCATION_INFO) ||
4331                 (info_level == SMB_FILE_ALLOCATION_INFORMATION) ||
4332                 (info_level == SMB_FILE_END_OF_FILE_INFORMATION))) {
4333
4334                 /*
4335                  * Only do this test if we are not explicitly
4336                  * changing the size of a file.
4337                  */
4338                 if (!size)
4339                         size = get_file_size(sbuf);
4340         }
4341
4342         /*
4343          * Try and set the times, size and mode of this file -
4344          * if they are different from the current values
4345          */
4346
4347         /* check the mode isn't different, before changing it */
4348         if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, &sbuf))) {
4349
4350                 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting dos mode %x\n", fname, dosmode ));
4351
4352                 if(file_set_dosmode(conn, fname, dosmode, &sbuf, False)) {
4353                         DEBUG(2,("file_set_dosmode of %s failed (%s)\n", fname, strerror(errno)));
4354                         return(UNIXERROR(ERRDOS,ERRnoaccess));
4355                 }
4356         }
4357
4358         /* Now the size. */
4359         if (size != get_file_size(sbuf)) {
4360
4361                 int ret;
4362
4363                 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new size to %.0f\n",
4364                         fname, (double)size ));
4365
4366                 if (fd == -1) {
4367                         files_struct *new_fsp = NULL;
4368                         int access_mode = 0;
4369                         int action = 0;
4370
4371                         if(global_oplock_break) {
4372                                 /* Queue this file modify as we are the process of an oplock break.  */
4373
4374                                 DEBUG(2,("call_trans2setfilepathinfo: queueing message due to being "));
4375                                 DEBUGADD(2,( "in oplock break state.\n"));
4376
4377                                 push_oplock_pending_smb_message(inbuf, length);
4378                                 return -1;
4379                         }
4380
4381                         new_fsp = open_file_shared(conn, fname, &sbuf,
4382                                                 SET_OPEN_MODE(DOS_OPEN_RDWR),
4383                                                 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
4384                                                 FILE_ATTRIBUTE_NORMAL,
4385                                                 INTERNAL_OPEN_ONLY, &access_mode, &action);
4386         
4387                         if (new_fsp == NULL)
4388                                 return(UNIXERROR(ERRDOS,ERRbadpath));
4389                         ret = vfs_set_filelen(new_fsp, size);
4390                         close_file(new_fsp,True);
4391                 } else {
4392                         ret = vfs_set_filelen(fsp, size);
4393                 }
4394
4395                 if (ret == -1)
4396                         return (UNIXERROR(ERRHRD,ERRdiskfull));
4397         }
4398
4399         /*
4400          * Finally the times.
4401          */
4402         if (sbuf.st_mtime != tvs.modtime || sbuf.st_atime != tvs.actime) {
4403                 if(fsp != NULL) {
4404                         /*
4405                          * This was a setfileinfo on an open file.
4406                          * NT does this a lot. We also need to 
4407                          * set the time here, as it can be read by 
4408                          * FindFirst/FindNext and with the patch for bug #2045
4409                          * in smbd/fileio.c it ensures that this timestamp is
4410                          * kept sticky even after a write. We save the request
4411                          * away and will set it on file close and after a write. JRA.
4412                          */
4413
4414                         if (tvs.modtime != (time_t)0 && tvs.modtime != (time_t)-1) {
4415                                 DEBUG(10,("call_trans2setfilepathinfo: setting pending modtime to %s\n", ctime(&tvs.modtime) ));
4416                                 fsp_set_pending_modtime(fsp, tvs.modtime);
4417                         }
4418
4419                 }
4420                 DEBUG(10,("call_trans2setfilepathinfo: setting utimes to modified values.\n"));
4421
4422                 if(file_utime(conn, fname, &tvs)!=0) {
4423                         return(UNIXERROR(ERRDOS,ERRnoaccess));
4424                 }
4425         }
4426
4427         SSVAL(params,0,0);
4428         send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4429   
4430         return(-1);
4431 }
4432
4433 /****************************************************************************
4434  Reply to a TRANS2_MKDIR (make directory with extended attributes).
4435 ****************************************************************************/
4436
4437 static int call_trans2mkdir(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
4438                                         char **pparams, int total_params, char **ppdata, int total_data,
4439                                         unsigned int max_data_bytes)
4440 {
4441         char *params = *pparams;
4442         char *pdata = *ppdata;
4443         pstring directory;
4444         int ret = -1;
4445         SMB_STRUCT_STAT sbuf;
4446         BOOL bad_path = False;
4447         NTSTATUS status = NT_STATUS_OK;
4448         TALLOC_CTX *ctx = NULL;
4449         struct ea_list *ea_list = NULL;
4450
4451         if (!CAN_WRITE(conn))
4452                 return ERROR_DOS(ERRSRV,ERRaccess);
4453
4454         if (total_params < 4) {
4455                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4456         }
4457
4458         srvstr_get_path(inbuf, directory, &params[4], sizeof(directory), -1, STR_TERMINATE, &status, False);
4459         if (!NT_STATUS_IS_OK(status)) {
4460                 return ERROR_NT(status);
4461         }
4462
4463         DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
4464
4465         unix_convert(directory,conn,0,&bad_path,&sbuf);
4466         if (bad_path) {
4467                 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
4468         }
4469
4470         /* Any data in this call is an EA list. */
4471         if (total_data && !lp_ea_support(SNUM(conn))) {
4472                 return ERROR_NT(NT_STATUS_EAS_NOT_SUPPORTED);
4473         }
4474
4475         if (total_data) {
4476                 if (total_data < 10) {
4477                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4478                 }
4479
4480                 if (IVAL(pdata,0) > total_data) {
4481                         DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
4482                                 IVAL(pdata,0), (unsigned int)total_data));
4483                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4484                 }
4485
4486                 ctx = talloc_init("TRANS2_MKDIR_SET_EA");
4487                 if (!ctx) {
4488                         return ERROR_NT(NT_STATUS_NO_MEMORY);
4489                 }
4490                 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
4491                 if (!ea_list) {
4492                         talloc_destroy(ctx);
4493                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4494                 }
4495         }
4496
4497         if (check_name(directory,conn)) {
4498                 ret = vfs_MkDir(conn,directory,unix_mode(conn,aDIR,directory,True));
4499         }
4500   
4501         if(ret < 0) {
4502                 talloc_destroy(ctx);
4503                 DEBUG(5,("call_trans2mkdir error (%s)\n", strerror(errno)));
4504                 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
4505         }
4506
4507         /* Try and set any given EA. */
4508         if (total_data) {
4509                 status = set_ea(conn, NULL, directory, ea_list);
4510                 talloc_destroy(ctx);
4511                 if (!NT_STATUS_IS_OK(status)) {
4512                         return ERROR_NT(status);
4513                 }
4514         }
4515
4516         /* Realloc the parameter and data sizes */
4517         params = SMB_REALLOC(*pparams,2);
4518         if(params == NULL) {
4519                 return ERROR_NT(NT_STATUS_NO_MEMORY);
4520         }
4521         *pparams = params;
4522
4523         SSVAL(params,0,0);
4524
4525         send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4526   
4527         return(-1);
4528 }
4529
4530 /****************************************************************************
4531  Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
4532  We don't actually do this - we just send a null response.
4533 ****************************************************************************/
4534
4535 static int call_trans2findnotifyfirst(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
4536                                         char **pparams, int total_params, char **ppdata, int total_data,
4537                                         unsigned int max_data_bytes)
4538 {
4539         static uint16 fnf_handle = 257;
4540         char *params = *pparams;
4541         uint16 info_level;
4542
4543         if (total_params < 6) {
4544                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4545         }
4546
4547         info_level = SVAL(params,4);
4548         DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
4549
4550         switch (info_level) {
4551                 case 1:
4552                 case 2:
4553                         break;
4554                 default:
4555                         return ERROR_DOS(ERRDOS,ERRunknownlevel);
4556         }
4557
4558         /* Realloc the parameter and data sizes */
4559         params = SMB_REALLOC(*pparams,6);
4560         if(params == NULL) {
4561                 return ERROR_NT(NT_STATUS_NO_MEMORY);
4562         }
4563         *pparams = params;
4564
4565         SSVAL(params,0,fnf_handle);
4566         SSVAL(params,2,0); /* No changes */
4567         SSVAL(params,4,0); /* No EA errors */
4568
4569         fnf_handle++;
4570
4571         if(fnf_handle == 0)
4572                 fnf_handle = 257;
4573
4574         send_trans2_replies(outbuf, bufsize, params, 6, *ppdata, 0);
4575   
4576         return(-1);
4577 }
4578
4579 /****************************************************************************
4580  Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for 
4581  changes). Currently this does nothing.
4582 ****************************************************************************/
4583
4584 static int call_trans2findnotifynext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
4585                                         char **pparams, int total_params, char **ppdata, int total_data,
4586                                         unsigned int max_data_bytes)
4587 {
4588         char *params = *pparams;
4589
4590         DEBUG(3,("call_trans2findnotifynext\n"));
4591
4592         /* Realloc the parameter and data sizes */
4593         params = SMB_REALLOC(*pparams,4);
4594         if(params == NULL) {
4595                 return ERROR_NT(NT_STATUS_NO_MEMORY);
4596         }
4597         *pparams = params;
4598
4599         SSVAL(params,0,0); /* No changes */
4600         SSVAL(params,2,0); /* No EA errors */
4601
4602         send_trans2_replies(outbuf, bufsize, params, 4, *ppdata, 0);
4603   
4604         return(-1);
4605 }
4606
4607 /****************************************************************************
4608  Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
4609 ****************************************************************************/
4610
4611 static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
4612                                         char **pparams, int total_params, char **ppdata, int total_data,
4613                                         unsigned int max_data_bytes)
4614 {
4615         char *params = *pparams;
4616         pstring pathname;
4617         int reply_size = 0;
4618         int max_referral_level;
4619
4620         DEBUG(10,("call_trans2getdfsreferral\n"));
4621
4622         if (total_params < 2) {
4623                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4624         }
4625
4626         max_referral_level = SVAL(params,0);
4627
4628         if(!lp_host_msdfs())
4629                 return ERROR_DOS(ERRDOS,ERRbadfunc);
4630
4631         srvstr_pull(inbuf, pathname, &params[2], sizeof(pathname), -1, STR_TERMINATE);
4632         if((reply_size = setup_dfs_referral(conn, pathname,max_referral_level,ppdata)) < 0)
4633                 return UNIXERROR(ERRDOS,ERRbadfile);
4634     
4635         SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
4636         send_trans2_replies(outbuf,bufsize,0,0,*ppdata,reply_size);
4637
4638         return(-1);
4639 }
4640
4641 #define LMCAT_SPL       0x53
4642 #define LMFUNC_GETJOBID 0x60
4643
4644 /****************************************************************************
4645  Reply to a TRANS2_IOCTL - used for OS/2 printing.
4646 ****************************************************************************/
4647
4648 static int call_trans2ioctl(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
4649                                         char **pparams, int total_params, char **ppdata, int total_data,
4650                                         unsigned int max_data_bytes)
4651 {
4652         char *pdata = *ppdata;
4653         files_struct *fsp = file_fsp(inbuf,smb_vwv15);
4654
4655         /* check for an invalid fid before proceeding */
4656         
4657         if (!fsp)                                
4658                 return(ERROR_DOS(ERRDOS,ERRbadfid));  
4659
4660         if ((SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
4661                         (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
4662                 pdata = SMB_REALLOC(*ppdata, 32);
4663                 if(pdata == NULL) {
4664                         return ERROR_NT(NT_STATUS_NO_MEMORY);
4665                 }
4666                 *ppdata = pdata;
4667
4668                 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
4669                         CAN ACCEPT THIS IN UNICODE. JRA. */
4670
4671                 SSVAL(pdata,0,fsp->rap_print_jobid);                     /* Job number */
4672                 srvstr_push( outbuf, pdata + 2, global_myname(), 15, STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
4673                 srvstr_push( outbuf, pdata+18, lp_servicename(SNUM(conn)), 13, STR_ASCII|STR_TERMINATE); /* Service name */
4674                 send_trans2_replies(outbuf,bufsize,*pparams,0,*ppdata,32);
4675                 return(-1);
4676         } else {
4677                 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
4678                 return ERROR_DOS(ERRSRV,ERRerror);
4679         }
4680 }
4681
4682 /****************************************************************************
4683  Reply to a SMBfindclose (stop trans2 directory search).
4684 ****************************************************************************/
4685
4686 int reply_findclose(connection_struct *conn,
4687                     char *inbuf,char *outbuf,int length,int bufsize)
4688 {
4689         int outsize = 0;
4690         int dptr_num=SVALS(inbuf,smb_vwv0);
4691         START_PROFILE(SMBfindclose);
4692
4693         DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
4694
4695         dptr_close(&dptr_num);
4696
4697         outsize = set_message(outbuf,0,0,True);
4698
4699         DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
4700
4701         END_PROFILE(SMBfindclose);
4702         return(outsize);
4703 }
4704
4705 /****************************************************************************
4706  Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
4707 ****************************************************************************/
4708
4709 int reply_findnclose(connection_struct *conn, 
4710                      char *inbuf,char *outbuf,int length,int bufsize)
4711 {
4712         int outsize = 0;
4713         int dptr_num= -1;
4714         START_PROFILE(SMBfindnclose);
4715         
4716         dptr_num = SVAL(inbuf,smb_vwv0);
4717
4718         DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
4719
4720         /* We never give out valid handles for a 
4721            findnotifyfirst - so any dptr_num is ok here. 
4722            Just ignore it. */
4723
4724         outsize = set_message(outbuf,0,0,True);
4725
4726         DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
4727
4728         END_PROFILE(SMBfindnclose);
4729         return(outsize);
4730 }
4731
4732 /****************************************************************************
4733  Reply to a SMBtranss2 - just ignore it!
4734 ****************************************************************************/
4735
4736 int reply_transs2(connection_struct *conn,
4737                   char *inbuf,char *outbuf,int length,int bufsize)
4738 {
4739         START_PROFILE(SMBtranss2);
4740         DEBUG(4,("Ignoring transs2 of length %d\n",length));
4741         END_PROFILE(SMBtranss2);
4742         return(-1);
4743 }
4744
4745 /****************************************************************************
4746  Reply to a SMBtrans2.
4747 ****************************************************************************/
4748
4749 int reply_trans2(connection_struct *conn,
4750                  char *inbuf,char *outbuf,int length,int bufsize)
4751 {
4752         int outsize = 0;
4753         unsigned int total_params = SVAL(inbuf, smb_tpscnt);
4754         unsigned int total_data =SVAL(inbuf, smb_tdscnt);
4755         unsigned int max_data_bytes = SVAL(inbuf, smb_mdrcnt);
4756 #if 0
4757         unsigned int max_param_reply = SVAL(inbuf, smb_mprcnt);
4758         unsigned int max_setup_fields = SVAL(inbuf, smb_msrcnt);
4759         BOOL close_tid = BITSETW(inbuf+smb_flags,0);
4760         BOOL no_final_response = BITSETW(inbuf+smb_flags,1);
4761         int32 timeout = IVALS(inbuf,smb_timeout);
4762 #endif
4763         unsigned int suwcnt = SVAL(inbuf, smb_suwcnt);
4764         unsigned int tran_call = SVAL(inbuf, smb_setup0);
4765         char *params = NULL, *data = NULL;
4766         unsigned int num_params, num_params_sofar, num_data, num_data_sofar;
4767         START_PROFILE(SMBtrans2);
4768
4769         if(global_oplock_break && (tran_call == TRANSACT2_OPEN)) {
4770                 /* Queue this open message as we are the process of an
4771                  * oplock break.  */
4772
4773                 DEBUG(2,("reply_trans2: queueing message trans2open due to being "));
4774                 DEBUGADD(2,( "in oplock break state.\n"));
4775
4776                 push_oplock_pending_smb_message(inbuf, length);
4777                 END_PROFILE(SMBtrans2);
4778                 return -1;
4779         }
4780         
4781         if (IS_IPC(conn) && (tran_call != TRANSACT2_OPEN)
4782             && (tran_call != TRANSACT2_GET_DFS_REFERRAL)) {
4783                 END_PROFILE(SMBtrans2);
4784                 return ERROR_DOS(ERRSRV,ERRaccess);
4785         }
4786
4787         outsize = set_message(outbuf,0,0,True);
4788
4789         /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
4790            is so as a sanity check */
4791         if (suwcnt != 1) {
4792                 /*
4793                  * Need to have rc=0 for ioctl to get job id for OS/2.
4794                  *  Network printing will fail if function is not successful.
4795                  *  Similar function in reply.c will be used if protocol
4796                  *  is LANMAN1.0 instead of LM1.2X002.
4797                  *  Until DosPrintSetJobInfo with PRJINFO3 is supported,
4798                  *  outbuf doesn't have to be set(only job id is used).
4799                  */
4800                 if ( (suwcnt == 4) && (tran_call == TRANSACT2_IOCTL) &&
4801                                 (SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
4802                                 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
4803                         DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
4804                 } else {
4805                         DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",suwcnt));
4806                         DEBUG(2,("Transaction is %d\n",tran_call));
4807                         END_PROFILE(SMBtrans2);
4808                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4809                 }
4810         }
4811     
4812         /* Allocate the space for the maximum needed parameters and data */
4813         if (total_params > 0)
4814                 params = (char *)SMB_MALLOC(total_params);
4815         if (total_data > 0)
4816                 data = (char *)SMB_MALLOC(total_data);
4817   
4818         if ((total_params && !params)  || (total_data && !data)) {
4819                 DEBUG(2,("Out of memory in reply_trans2\n"));
4820                 SAFE_FREE(params);
4821                 SAFE_FREE(data); 
4822                 END_PROFILE(SMBtrans2);
4823                 return ERROR_NT(NT_STATUS_NO_MEMORY);
4824         }
4825
4826         /* Copy the param and data bytes sent with this request into
4827            the params buffer */
4828         num_params = num_params_sofar = SVAL(inbuf,smb_pscnt);
4829         num_data = num_data_sofar = SVAL(inbuf, smb_dscnt);
4830
4831         if (num_params > total_params || num_data > total_data)
4832                 exit_server("invalid params in reply_trans2");
4833
4834         if(params) {
4835                 unsigned int psoff = SVAL(inbuf, smb_psoff);
4836                 if ((psoff + num_params < psoff) || (psoff + num_params < num_params))
4837                         goto bad_param;
4838                 if ((smb_base(inbuf) + psoff + num_params > inbuf + length) ||
4839                                 (smb_base(inbuf) + psoff + num_params < smb_base(inbuf)))
4840                         goto bad_param;
4841                 memcpy( params, smb_base(inbuf) + psoff, num_params);
4842         }
4843         if(data) {
4844                 unsigned int dsoff = SVAL(inbuf, smb_dsoff);
4845                 if ((dsoff + num_data < dsoff) || (dsoff + num_data < num_data))
4846                         goto bad_param;
4847                 if ((smb_base(inbuf) + dsoff + num_data > inbuf + length) ||
4848                                 (smb_base(inbuf) + dsoff + num_data < smb_base(inbuf)))
4849                         goto bad_param;
4850                 memcpy( data, smb_base(inbuf) + dsoff, num_data);
4851         }
4852
4853         srv_signing_trans_start(SVAL(inbuf,smb_mid));
4854
4855         if(num_data_sofar < total_data || num_params_sofar < total_params)  {
4856                 /* We need to send an interim response then receive the rest
4857                    of the parameter/data bytes */
4858                 outsize = set_message(outbuf,0,0,True);
4859                 srv_signing_trans_stop();
4860                 if (!send_smb(smbd_server_fd(),outbuf))
4861                         exit_server("reply_trans2: send_smb failed.");
4862
4863                 while (num_data_sofar < total_data || 
4864                        num_params_sofar < total_params) {
4865                         BOOL ret;
4866                         unsigned int param_disp;
4867                         unsigned int param_off;
4868                         unsigned int data_disp;
4869                         unsigned int data_off;
4870
4871                         ret = receive_next_smb(inbuf,bufsize,SMB_SECONDARY_WAIT);
4872                         
4873                         /*
4874                          * The sequence number for the trans reply is always
4875                          * based on the last secondary received.
4876                          */
4877
4878                         srv_signing_trans_start(SVAL(inbuf,smb_mid));
4879
4880                         if ((ret && 
4881                              (CVAL(inbuf, smb_com) != SMBtranss2)) || !ret) {
4882                                 outsize = set_message(outbuf,0,0,True);
4883                                 if(ret)
4884                                         DEBUG(0,("reply_trans2: Invalid secondary trans2 packet\n"));
4885                                 else
4886                                         DEBUG(0,("reply_trans2: %s in getting secondary trans2 response.\n",
4887                                                  (smb_read_error == READ_ERROR) ? "error" : "timeout" ));
4888                                 goto bad_param;
4889                         }
4890       
4891                         /* Revise total_params and total_data in case
4892                            they have changed downwards */
4893                         if (SVAL(inbuf, smb_tpscnt) < total_params)
4894                                 total_params = SVAL(inbuf, smb_tpscnt);
4895                         if (SVAL(inbuf, smb_tdscnt) < total_data)
4896                                 total_data = SVAL(inbuf, smb_tdscnt);
4897
4898                         num_params = SVAL(inbuf,smb_spscnt);
4899                         param_off = SVAL(inbuf, smb_spsoff);
4900                         param_disp = SVAL(inbuf, smb_spsdisp);
4901                         num_params_sofar += num_params;
4902
4903                         num_data = SVAL(inbuf, smb_sdscnt);
4904                         data_off = SVAL(inbuf, smb_sdsoff);
4905                         data_disp = SVAL(inbuf, smb_sdsdisp);
4906                         num_data_sofar += num_data;
4907
4908                         if (num_params_sofar > total_params || num_data_sofar > total_data)
4909                                 goto bad_param;
4910                         
4911                         if (num_params) {
4912                                 if (param_disp + num_params > total_params)
4913                                         goto bad_param;
4914                                 if ((param_disp + num_params < param_disp) ||
4915                                                 (param_disp + num_params < num_params))
4916                                         goto bad_param;
4917                                 if (param_disp > total_params)
4918                                         goto bad_param;
4919                                 if ((smb_base(inbuf) + param_off + num_params >= inbuf + bufsize) ||
4920                                                 (smb_base(inbuf) + param_off + num_params < smb_base(inbuf)))
4921                                         goto bad_param;
4922                                 if (params + param_disp < params)
4923                                         goto bad_param;
4924
4925                                 memcpy( &params[param_disp], smb_base(inbuf) + param_off, num_params);
4926                         }
4927                         if (num_data) {
4928                                 if (data_disp + num_data > total_data)
4929                                         goto bad_param;
4930                                 if ((data_disp + num_data < data_disp) ||
4931                                                 (data_disp + num_data < num_data))
4932                                         goto bad_param;
4933                                 if (data_disp > total_data)
4934                                         goto bad_param;
4935                                 if ((smb_base(inbuf) + data_off + num_data >= inbuf + bufsize) ||
4936                                                 (smb_base(inbuf) + data_off + num_data < smb_base(inbuf)))
4937                                         goto bad_param;
4938                                 if (data + data_disp < data)
4939                                         goto bad_param;
4940
4941                                 memcpy( &data[data_disp], smb_base(inbuf) + data_off, num_data);
4942                         }
4943                 }
4944         }
4945         
4946         if (Protocol >= PROTOCOL_NT1) {
4947                 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | 0x40); /* IS_LONG_NAME */
4948         }
4949
4950         /* Now we must call the relevant TRANS2 function */
4951         switch(tran_call)  {
4952         case TRANSACT2_OPEN:
4953                 START_PROFILE_NESTED(Trans2_open);
4954                 outsize = call_trans2open(conn, inbuf, outbuf, bufsize, 
4955                                           &params, total_params, &data, total_data, max_data_bytes);
4956                 END_PROFILE_NESTED(Trans2_open);
4957                 break;
4958
4959         case TRANSACT2_FINDFIRST:
4960                 START_PROFILE_NESTED(Trans2_findfirst);
4961                 outsize = call_trans2findfirst(conn, inbuf, outbuf, bufsize,
4962                                           &params, total_params, &data, total_data, max_data_bytes);
4963                 END_PROFILE_NESTED(Trans2_findfirst);
4964                 break;
4965
4966         case TRANSACT2_FINDNEXT:
4967                 START_PROFILE_NESTED(Trans2_findnext);
4968                 outsize = call_trans2findnext(conn, inbuf, outbuf, length, bufsize, 
4969                                           &params, total_params, &data, total_data, max_data_bytes);
4970                 END_PROFILE_NESTED(Trans2_findnext);
4971                 break;
4972
4973         case TRANSACT2_QFSINFO:
4974                 START_PROFILE_NESTED(Trans2_qfsinfo);
4975                 outsize = call_trans2qfsinfo(conn, inbuf, outbuf, length, bufsize,
4976                                           &params, total_params, &data, total_data, max_data_bytes);
4977                 END_PROFILE_NESTED(Trans2_qfsinfo);
4978             break;
4979
4980 #ifdef HAVE_SYS_QUOTAS
4981         case TRANSACT2_SETFSINFO:
4982                 START_PROFILE_NESTED(Trans2_setfsinfo);
4983                 outsize = call_trans2setfsinfo(conn, inbuf, outbuf, length, bufsize, 
4984                                           &params, total_params, &data, total_data, max_data_bytes);
4985                 END_PROFILE_NESTED(Trans2_setfsinfo);
4986                 break;
4987 #endif
4988         case TRANSACT2_QPATHINFO:
4989         case TRANSACT2_QFILEINFO:
4990                 START_PROFILE_NESTED(Trans2_qpathinfo);
4991                 outsize = call_trans2qfilepathinfo(conn, inbuf, outbuf, length, bufsize, 
4992                                           &params, total_params, &data, total_data, max_data_bytes);
4993                 END_PROFILE_NESTED(Trans2_qpathinfo);
4994                 break;
4995         case TRANSACT2_SETPATHINFO:
4996         case TRANSACT2_SETFILEINFO:
4997                 START_PROFILE_NESTED(Trans2_setpathinfo);
4998                 outsize = call_trans2setfilepathinfo(conn, inbuf, outbuf, length, bufsize, 
4999                                           &params, total_params, &data, total_data, max_data_bytes);
5000                 END_PROFILE_NESTED(Trans2_setpathinfo);
5001                 break;
5002
5003         case TRANSACT2_FINDNOTIFYFIRST:
5004                 START_PROFILE_NESTED(Trans2_findnotifyfirst);
5005                 outsize = call_trans2findnotifyfirst(conn, inbuf, outbuf, length, bufsize, 
5006                                           &params, total_params, &data, total_data, max_data_bytes);
5007                 END_PROFILE_NESTED(Trans2_findnotifyfirst);
5008                 break;
5009
5010         case TRANSACT2_FINDNOTIFYNEXT:
5011                 START_PROFILE_NESTED(Trans2_findnotifynext);
5012                 outsize = call_trans2findnotifynext(conn, inbuf, outbuf, length, bufsize, 
5013                                           &params, total_params, &data, total_data, max_data_bytes);
5014                 END_PROFILE_NESTED(Trans2_findnotifynext);
5015                 break;
5016         case TRANSACT2_MKDIR:
5017                 START_PROFILE_NESTED(Trans2_mkdir);
5018                 outsize = call_trans2mkdir(conn, inbuf, outbuf, length, bufsize,
5019                                           &params, total_params, &data, total_data, max_data_bytes);
5020                 END_PROFILE_NESTED(Trans2_mkdir);
5021                 break;
5022
5023         case TRANSACT2_GET_DFS_REFERRAL:
5024                 START_PROFILE_NESTED(Trans2_get_dfs_referral);
5025                 outsize = call_trans2getdfsreferral(conn,inbuf,outbuf,length, bufsize,
5026                                           &params, total_params, &data, total_data, max_data_bytes);
5027                 END_PROFILE_NESTED(Trans2_get_dfs_referral);
5028                 break;
5029         case TRANSACT2_IOCTL:
5030                 START_PROFILE_NESTED(Trans2_ioctl);
5031                 outsize = call_trans2ioctl(conn,inbuf,outbuf,length, bufsize,
5032                                           &params, total_params, &data, total_data, max_data_bytes);
5033                 END_PROFILE_NESTED(Trans2_ioctl);
5034                 break;
5035         default:
5036                 /* Error in request */
5037                 DEBUG(2,("Unknown request %d in trans2 call\n", tran_call));
5038                 SAFE_FREE(params);
5039                 SAFE_FREE(data);
5040                 END_PROFILE(SMBtrans2);
5041                 srv_signing_trans_stop();
5042                 return ERROR_DOS(ERRSRV,ERRerror);
5043         }
5044         
5045         /* As we do not know how many data packets will need to be
5046            returned here the various call_trans2xxxx calls
5047            must send their own. Thus a call_trans2xxx routine only
5048            returns a value other than -1 when it wants to send
5049            an error packet. 
5050         */
5051         
5052         srv_signing_trans_stop();
5053
5054         SAFE_FREE(params);
5055         SAFE_FREE(data);
5056         END_PROFILE(SMBtrans2);
5057         return outsize; /* If a correct response was needed the
5058                            call_trans2xxx calls have already sent
5059                            it. If outsize != -1 then it is returning */
5060
5061   bad_param:
5062
5063         srv_signing_trans_stop();
5064         SAFE_FREE(params);
5065         SAFE_FREE(data);
5066         END_PROFILE(SMBtrans2);
5067         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5068 }