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