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