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