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