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