4f5039e86c332e0f97e00929342cbd4ae951d705
[sfrench/samba-autobuild/.git] / source / smbd / trans2.c
1 /* 
2    Unix SMB/CIFS implementation.
3    SMB transaction2 handling
4    Copyright (C) Jeremy Allison                 1994-2003
5    Copyright (C) Stefan (metze) Metzmacher      2003
6    Copyright (C) Volker Lendecke                2005
7    Copyright (C) Steve French                   2005
8
9    Extensively modified by Andrew Tridgell, 1995
10
11    This program is free software; you can redistribute it and/or modify
12    it under the terms of the GNU General Public License as published by
13    the Free Software Foundation; either version 2 of the License, or
14    (at your option) any later version.
15    
16    This program is distributed in the hope that it will be useful,
17    but WITHOUT ANY WARRANTY; without even the implied warranty of
18    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19    GNU General Public License for more details.
20    
21    You should have received a copy of the GNU General Public License
22    along with this program; if not, write to the Free Software
23    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 */
25
26 #include "includes.h"
27
28 extern int max_send;
29 extern enum protocol_types Protocol;
30 extern int smb_read_error;
31 extern uint32 global_client_caps;
32 extern struct current_user current_user;
33
34 #define get_file_size(sbuf) ((sbuf).st_size)
35 #define DIR_ENTRY_SAFETY_MARGIN 4096
36
37 /********************************************************************
38  Roundup a value to the nearest allocation roundup size boundary.
39  Only do this for Windows clients.
40 ********************************************************************/
41
42 SMB_BIG_UINT smb_roundup(connection_struct *conn, SMB_BIG_UINT val)
43 {
44         SMB_BIG_UINT rval = lp_allocation_roundup_size(SNUM(conn));
45
46         /* Only roundup for Windows clients. */
47         enum remote_arch_types ra_type = get_remote_arch();
48         if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
49                 val = SMB_ROUNDUP(val,rval);
50         }
51         return val;
52 }
53
54 /********************************************************************
55  Given a stat buffer return the allocated size on disk, taking into
56  account sparse files.
57 ********************************************************************/
58
59 SMB_BIG_UINT get_allocation_size(connection_struct *conn, files_struct *fsp, SMB_STRUCT_STAT *sbuf)
60 {
61         SMB_BIG_UINT ret;
62
63         if(S_ISDIR(sbuf->st_mode)) {
64                 return 0;
65         }
66
67 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
68         ret = (SMB_BIG_UINT)STAT_ST_BLOCKSIZE * (SMB_BIG_UINT)sbuf->st_blocks;
69 #else
70         ret = (SMB_BIG_UINT)get_file_size(*sbuf);
71 #endif
72
73         if (fsp && fsp->initial_allocation_size)
74                 ret = MAX(ret,fsp->initial_allocation_size);
75
76         return smb_roundup(conn, ret);
77 }
78
79 /****************************************************************************
80  Utility functions for dealing with extended attributes.
81 ****************************************************************************/
82
83 static const char *prohibited_ea_names[] = {
84         SAMBA_POSIX_INHERITANCE_EA_NAME,
85         SAMBA_XATTR_DOS_ATTRIB,
86         NULL
87 };
88
89 /****************************************************************************
90  Refuse to allow clients to overwrite our private xattrs.
91 ****************************************************************************/
92
93 static BOOL samba_private_attr_name(const char *unix_ea_name)
94 {
95         int i;
96
97         for (i = 0; prohibited_ea_names[i]; i++) {
98                 if (strequal( prohibited_ea_names[i], unix_ea_name))
99                         return True;
100         }
101         return False;
102 }
103
104 /****************************************************************************
105  Get one EA value. Fill in a struct ea_struct.
106 ****************************************************************************/
107
108 static BOOL get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
109                                 const char *fname, char *ea_name, struct ea_struct *pea)
110 {
111         /* Get the value of this xattr. Max size is 64k. */
112         size_t attr_size = 256;
113         char *val = NULL;
114         ssize_t sizeret;
115
116  again:
117
118         val = TALLOC_REALLOC_ARRAY(mem_ctx, val, char, attr_size);
119         if (!val) {
120                 return False;
121         }
122
123         if (fsp && fsp->fh->fd != -1) {
124                 sizeret = SMB_VFS_FGETXATTR(fsp, fsp->fh->fd, ea_name, val, attr_size);
125         } else {
126                 sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
127         }
128
129         if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
130                 attr_size = 65536;
131                 goto again;
132         }
133
134         if (sizeret == -1) {
135                 return False;
136         }
137
138         DEBUG(10,("get_ea_value: EA %s is of length %u: ", ea_name, (unsigned int)sizeret));
139         dump_data(10, val, sizeret);
140
141         pea->flags = 0;
142         if (strnequal(ea_name, "user.", 5)) {
143                 pea->name = &ea_name[5];
144         } else {
145                 pea->name = ea_name;
146         }
147         pea->value.data = (unsigned char *)val;
148         pea->value.length = (size_t)sizeret;
149         return True;
150 }
151
152 /****************************************************************************
153  Return a linked list of the total EA's. Plus the total size
154 ****************************************************************************/
155
156 static struct ea_list *get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
157                                         const char *fname, size_t *pea_total_len)
158 {
159         /* Get a list of all xattrs. Max namesize is 64k. */
160         size_t ea_namelist_size = 1024;
161         char *ea_namelist;
162         char *p;
163         ssize_t sizeret;
164         int i;
165         struct ea_list *ea_list_head = NULL;
166
167         *pea_total_len = 0;
168
169         if (!lp_ea_support(SNUM(conn))) {
170                 return NULL;
171         }
172
173         for (i = 0, ea_namelist = TALLOC(mem_ctx, ea_namelist_size); i < 6;
174                         ea_namelist = TALLOC_REALLOC_ARRAY(mem_ctx, ea_namelist, char, ea_namelist_size), i++) {
175                 if (fsp && fsp->fh->fd != -1) {
176                         sizeret = SMB_VFS_FLISTXATTR(fsp, fsp->fh->fd, ea_namelist, ea_namelist_size);
177                 } else {
178                         sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist, ea_namelist_size);
179                 }
180
181                 if (sizeret == -1 && errno == ERANGE) {
182                         ea_namelist_size *= 2;
183                 } else {
184                         break;
185                 }
186         }
187
188         if (sizeret == -1)
189                 return NULL;
190
191         DEBUG(10,("get_ea_list_from_file: ea_namelist size = %u\n", (unsigned int)sizeret ));
192
193         if (sizeret) {
194                 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p) + 1) {
195                         struct ea_list *listp, *tmp;
196
197                         if (strnequal(p, "system.", 7) || samba_private_attr_name(p))
198                                 continue;
199                 
200                         listp = TALLOC_P(mem_ctx, struct ea_list);
201                         if (!listp)
202                                 return NULL;
203
204                         if (!get_ea_value(mem_ctx, conn, fsp, fname, p, &listp->ea)) {
205                                 return NULL;
206                         }
207
208                         {
209                                 fstring dos_ea_name;
210                                 push_ascii_fstring(dos_ea_name, listp->ea.name);
211                                 *pea_total_len += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
212                                 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len = %u\n",
213                                         (unsigned int)*pea_total_len, dos_ea_name,
214                                         (unsigned int)listp->ea.value.length ));
215                         }
216                         DLIST_ADD_END(ea_list_head, listp, tmp);
217                 }
218                 /* Add on 4 for total length. */
219                 if (*pea_total_len) {
220                         *pea_total_len += 4;
221                 }
222         }
223
224         DEBUG(10,("get_ea_list_from_file: total_len = %u\n", (unsigned int)*pea_total_len));
225         return ea_list_head;
226 }
227
228 /****************************************************************************
229  Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
230  that was filled.
231 ****************************************************************************/
232
233 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
234         connection_struct *conn, struct ea_list *ea_list)
235 {
236         unsigned int ret_data_size = 4;
237         char *p = pdata;
238
239         SMB_ASSERT(total_data_size >= 4);
240
241         if (!lp_ea_support(SNUM(conn))) {
242                 SIVAL(pdata,4,0);
243                 return 4;
244         }
245
246         for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
247                 size_t dos_namelen;
248                 fstring dos_ea_name;
249                 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
250                 dos_namelen = strlen(dos_ea_name);
251                 if (dos_namelen > 255 || dos_namelen == 0) {
252                         break;
253                 }
254                 if (ea_list->ea.value.length > 65535) {
255                         break;
256                 }
257                 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
258                         break;
259                 }
260
261                 /* We know we have room. */
262                 SCVAL(p,0,ea_list->ea.flags);
263                 SCVAL(p,1,dos_namelen);
264                 SSVAL(p,2,ea_list->ea.value.length);
265                 fstrcpy(p+4, dos_ea_name);
266                 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
267
268                 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
269                 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
270         }
271
272         ret_data_size = PTR_DIFF(p, pdata);
273         DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
274         SIVAL(pdata,0,ret_data_size);
275         return ret_data_size;
276 }
277
278 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const char *fname)
279 {
280         size_t total_ea_len = 0;
281         TALLOC_CTX *mem_ctx = NULL;
282
283         if (!lp_ea_support(SNUM(conn))) {
284                 return 0;
285         }
286         mem_ctx = talloc_init("estimate_ea_size");
287         (void)get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
288         talloc_destroy(mem_ctx);
289         return total_ea_len;
290 }
291
292 /****************************************************************************
293  Ensure the EA name is case insensitive by matching any existing EA name.
294 ****************************************************************************/
295
296 static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
297 {
298         size_t total_ea_len;
299         TALLOC_CTX *mem_ctx = talloc_init("canonicalize_ea_name");
300         struct ea_list *ea_list = get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
301
302         for (; ea_list; ea_list = ea_list->next) {
303                 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
304                         DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
305                                 &unix_ea_name[5], ea_list->ea.name));
306                         safe_strcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-6);
307                         break;
308                 }
309         }
310         talloc_destroy(mem_ctx);
311 }
312
313 /****************************************************************************
314  Set or delete an extended attribute.
315 ****************************************************************************/
316
317 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp, const char *fname, struct ea_list *ea_list)
318 {
319         if (!lp_ea_support(SNUM(conn))) {
320                 return NT_STATUS_EAS_NOT_SUPPORTED;
321         }
322
323         for (;ea_list; ea_list = ea_list->next) {
324                 int ret;
325                 fstring unix_ea_name;
326
327                 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
328                 fstrcat(unix_ea_name, ea_list->ea.name);
329
330                 canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
331
332                 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
333
334                 if (samba_private_attr_name(unix_ea_name)) {
335                         DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
336                         return NT_STATUS_ACCESS_DENIED;
337                 }
338
339                 if (ea_list->ea.value.length == 0) {
340                         /* Remove the attribute. */
341                         if (fsp && (fsp->fh->fd != -1)) {
342                                 DEBUG(10,("set_ea: deleting ea name %s on file %s by file descriptor.\n",
343                                         unix_ea_name, fsp->fsp_name));
344                                 ret = SMB_VFS_FREMOVEXATTR(fsp, fsp->fh->fd, unix_ea_name);
345                         } else {
346                                 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
347                                         unix_ea_name, fname));
348                                 ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
349                         }
350 #ifdef ENOATTR
351                         /* Removing a non existent attribute always succeeds. */
352                         if (ret == -1 && errno == ENOATTR) {
353                                 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
354                                                 unix_ea_name));
355                                 ret = 0;
356                         }
357 #endif
358                 } else {
359                         if (fsp && (fsp->fh->fd != -1)) {
360                                 DEBUG(10,("set_ea: setting ea name %s on file %s by file descriptor.\n",
361                                         unix_ea_name, fsp->fsp_name));
362                                 ret = SMB_VFS_FSETXATTR(fsp, fsp->fh->fd, unix_ea_name,
363                                                         ea_list->ea.value.data, ea_list->ea.value.length, 0);
364                         } else {
365                                 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
366                                         unix_ea_name, fname));
367                                 ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name,
368                                                         ea_list->ea.value.data, ea_list->ea.value.length, 0);
369                         }
370                 }
371
372                 if (ret == -1) {
373 #ifdef ENOTSUP
374                         if (errno == ENOTSUP) {
375                                 return NT_STATUS_EAS_NOT_SUPPORTED;
376                         }
377 #endif
378                         return map_nt_error_from_unix(errno);
379                 }
380
381         }
382         return NT_STATUS_OK;
383 }
384 /****************************************************************************
385  Read a list of EA names from an incoming data buffer. Create an ea_list with them.
386 ****************************************************************************/
387
388 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
389 {
390         struct ea_list *ea_list_head = NULL;
391         size_t offset = 0;
392
393         while (offset + 2 < data_size) {
394                 struct ea_list *tmp;
395                 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
396                 unsigned int namelen = CVAL(pdata,offset);
397
398                 offset++; /* Go past the namelen byte. */
399
400                 /* integer wrap paranioa. */
401                 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
402                                 (offset > data_size) || (namelen > data_size) ||
403                                 (offset + namelen >= data_size)) {
404                         break;
405                 }
406                 /* Ensure the name is null terminated. */
407                 if (pdata[offset + namelen] != '\0') {
408                         return NULL;
409                 }
410                 pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset]);
411                 if (!eal->ea.name) {
412                         return NULL;
413                 }
414
415                 offset += (namelen + 1); /* Go past the name + terminating zero. */
416                 DLIST_ADD_END(ea_list_head, eal, tmp);
417                 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
418         }
419
420         return ea_list_head;
421 }
422
423 /****************************************************************************
424  Read one EA list entry from the buffer.
425 ****************************************************************************/
426
427 struct ea_list *read_ea_list_entry(TALLOC_CTX *ctx, const char *pdata, size_t data_size, size_t *pbytes_used)
428 {
429         struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
430         uint16 val_len;
431         unsigned int namelen;
432
433         if (!eal) {
434                 return NULL;
435         }
436
437         if (data_size < 6) {
438                 return NULL;
439         }
440
441         eal->ea.flags = CVAL(pdata,0);
442         namelen = CVAL(pdata,1);
443         val_len = SVAL(pdata,2);
444
445         if (4 + namelen + 1 + val_len > data_size) {
446                 return NULL;
447         }
448
449         /* Ensure the name is null terminated. */
450         if (pdata[namelen + 4] != '\0') {
451                 return NULL;
452         }
453         pull_ascii_talloc(ctx, &eal->ea.name, pdata + 4);
454         if (!eal->ea.name) {
455                 return NULL;
456         }
457
458         eal->ea.value = data_blob(NULL, (size_t)val_len + 1);
459         if (!eal->ea.value.data) {
460                 return NULL;
461         }
462
463         memcpy(eal->ea.value.data, pdata + 4 + namelen + 1, val_len);
464
465         /* Ensure we're null terminated just in case we print the value. */
466         eal->ea.value.data[val_len] = '\0';
467         /* But don't count the null. */
468         eal->ea.value.length--;
469
470         if (pbytes_used) {
471                 *pbytes_used = 4 + namelen + 1 + val_len;
472         }
473
474         DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal->ea.name));
475         dump_data(10, (const char *)eal->ea.value.data, eal->ea.value.length);
476
477         return eal;
478 }
479
480 /****************************************************************************
481  Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
482 ****************************************************************************/
483
484 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
485 {
486         struct ea_list *ea_list_head = NULL;
487         size_t offset = 0;
488         size_t bytes_used = 0;
489
490         while (offset < data_size) {
491                 struct ea_list *tmp;
492                 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
493
494                 if (!eal) {
495                         return NULL;
496                 }
497
498                 DLIST_ADD_END(ea_list_head, eal, tmp);
499                 offset += bytes_used;
500         }
501
502         return ea_list_head;
503 }
504
505 /****************************************************************************
506  Count the total EA size needed.
507 ****************************************************************************/
508
509 static size_t ea_list_size(struct ea_list *ealist)
510 {
511         fstring dos_ea_name;
512         struct ea_list *listp;
513         size_t ret = 0;
514
515         for (listp = ealist; listp; listp = listp->next) {
516                 push_ascii_fstring(dos_ea_name, listp->ea.name);
517                 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
518         }
519         /* Add on 4 for total length. */
520         if (ret) {
521                 ret += 4;
522         }
523
524         return ret;
525 }
526
527 /****************************************************************************
528  Return a union of EA's from a file list and a list of names.
529  The TALLOC context for the two lists *MUST* be identical as we steal
530  memory from one list to add to another. JRA.
531 ****************************************************************************/
532
533 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
534 {
535         struct ea_list *nlistp, *flistp;
536
537         for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
538                 for (flistp = file_list; flistp; flistp = flistp->next) {
539                         if (strequal(nlistp->ea.name, flistp->ea.name)) {
540                                 break;
541                         }
542                 }
543
544                 if (flistp) {
545                         /* Copy the data from this entry. */
546                         nlistp->ea.flags = flistp->ea.flags;
547                         nlistp->ea.value = flistp->ea.value;
548                 } else {
549                         /* Null entry. */
550                         nlistp->ea.flags = 0;
551                         ZERO_STRUCT(nlistp->ea.value);
552                 }
553         }
554
555         *total_ea_len = ea_list_size(name_list);
556         return name_list;
557 }
558
559 /****************************************************************************
560   Send the required number of replies back.
561   We assume all fields other than the data fields are
562   set correctly for the type of call.
563   HACK ! Always assumes smb_setup field is zero.
564 ****************************************************************************/
565
566 static int send_trans2_replies(char *outbuf,
567                         int bufsize,
568                         char *params, 
569                         int paramsize,
570                         char *pdata,
571                         int datasize)
572 {
573         /* As we are using a protocol > LANMAN1 then the max_send
574          variable must have been set in the sessetupX call.
575          This takes precedence over the max_xmit field in the
576          global struct. These different max_xmit variables should
577          be merged as this is now too confusing */
578
579         int data_to_send = datasize;
580         int params_to_send = paramsize;
581         int useable_space;
582         char *pp = params;
583         char *pd = pdata;
584         int params_sent_thistime, data_sent_thistime, total_sent_thistime;
585         int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
586         int data_alignment_offset = 0;
587
588         /* Initially set the wcnt area to be 10 - this is true for all trans2 replies */
589         
590         set_message(outbuf,10,0,True);
591
592         /* If there genuinely are no parameters or data to send just send the empty packet */
593
594         if(params_to_send == 0 && data_to_send == 0) {
595                 show_msg(outbuf);
596                 if (!send_smb(smbd_server_fd(),outbuf))
597                         exit_server("send_trans2_replies: send_smb failed.");
598                 return 0;
599         }
600
601         /* When sending params and data ensure that both are nicely aligned */
602         /* Only do this alignment when there is also data to send - else
603                 can cause NT redirector problems. */
604
605         if (((params_to_send % 4) != 0) && (data_to_send != 0))
606                 data_alignment_offset = 4 - (params_to_send % 4);
607
608         /* Space is bufsize minus Netbios over TCP header minus SMB header */
609         /* The alignment_offset is to align the param bytes on an even byte
610                 boundary. NT 4.0 Beta needs this to work correctly. */
611
612         useable_space = bufsize - ((smb_buf(outbuf)+ alignment_offset+data_alignment_offset) - outbuf);
613
614         /* useable_space can never be more than max_send minus the alignment offset. */
615
616         useable_space = MIN(useable_space, max_send - (alignment_offset+data_alignment_offset));
617
618         while (params_to_send || data_to_send) {
619                 /* Calculate whether we will totally or partially fill this packet */
620
621                 total_sent_thistime = params_to_send + data_to_send + alignment_offset + data_alignment_offset;
622
623                 /* We can never send more than useable_space */
624                 /*
625                  * Note that 'useable_space' does not include the alignment offsets,
626                  * but we must include the alignment offsets in the calculation of
627                  * the length of the data we send over the wire, as the alignment offsets
628                  * are sent here. Fix from Marc_Jacobsen@hp.com.
629                  */
630
631                 total_sent_thistime = MIN(total_sent_thistime, useable_space+ alignment_offset + data_alignment_offset);
632
633                 set_message(outbuf, 10, total_sent_thistime, True);
634
635                 /* Set total params and data to be sent */
636                 SSVAL(outbuf,smb_tprcnt,paramsize);
637                 SSVAL(outbuf,smb_tdrcnt,datasize);
638
639                 /* Calculate how many parameters and data we can fit into
640                  * this packet. Parameters get precedence
641                  */
642
643                 params_sent_thistime = MIN(params_to_send,useable_space);
644                 data_sent_thistime = useable_space - params_sent_thistime;
645                 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
646
647                 SSVAL(outbuf,smb_prcnt, params_sent_thistime);
648
649                 /* smb_proff is the offset from the start of the SMB header to the
650                         parameter bytes, however the first 4 bytes of outbuf are
651                         the Netbios over TCP header. Thus use smb_base() to subtract
652                         them from the calculation */
653
654                 SSVAL(outbuf,smb_proff,((smb_buf(outbuf)+alignment_offset) - smb_base(outbuf)));
655
656                 if(params_sent_thistime == 0)
657                         SSVAL(outbuf,smb_prdisp,0);
658                 else
659                         /* Absolute displacement of param bytes sent in this packet */
660                         SSVAL(outbuf,smb_prdisp,pp - params);
661
662                 SSVAL(outbuf,smb_drcnt, data_sent_thistime);
663                 if(data_sent_thistime == 0) {
664                         SSVAL(outbuf,smb_droff,0);
665                         SSVAL(outbuf,smb_drdisp, 0);
666                 } else {
667                         /* The offset of the data bytes is the offset of the
668                                 parameter bytes plus the number of parameters being sent this time */
669                         SSVAL(outbuf,smb_droff,((smb_buf(outbuf)+alignment_offset) - 
670                                 smb_base(outbuf)) + params_sent_thistime + data_alignment_offset);
671                         SSVAL(outbuf,smb_drdisp, pd - pdata);
672                 }
673
674                 /* Copy the param bytes into the packet */
675
676                 if(params_sent_thistime)
677                         memcpy((smb_buf(outbuf)+alignment_offset),pp,params_sent_thistime);
678
679                 /* Copy in the data bytes */
680                 if(data_sent_thistime)
681                         memcpy(smb_buf(outbuf)+alignment_offset+params_sent_thistime+
682                                 data_alignment_offset,pd,data_sent_thistime);
683
684                 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
685                         params_sent_thistime, data_sent_thistime, useable_space));
686                 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
687                         params_to_send, data_to_send, paramsize, datasize));
688
689                 /* Send the packet */
690                 show_msg(outbuf);
691                 if (!send_smb(smbd_server_fd(),outbuf))
692                         exit_server("send_trans2_replies: send_smb failed.");
693
694                 pp += params_sent_thistime;
695                 pd += data_sent_thistime;
696
697                 params_to_send -= params_sent_thistime;
698                 data_to_send -= data_sent_thistime;
699
700                 /* Sanity check */
701                 if(params_to_send < 0 || data_to_send < 0) {
702                         DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
703                                 params_to_send, data_to_send));
704                         return -1;
705                 }
706         }
707
708         return 0;
709 }
710
711 /****************************************************************************
712  Reply to a TRANSACT2_OPEN.
713 ****************************************************************************/
714
715 static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, int bufsize,  
716                                 char **pparams, int total_params, char **ppdata, int total_data,
717                                 unsigned int max_data_bytes)
718 {
719         char *params = *pparams;
720         char *pdata = *ppdata;
721         int deny_mode;
722         int32 open_attr;
723         BOOL oplock_request;
724 #if 0
725         BOOL return_additional_info;
726         int16 open_sattr;
727         time_t open_time;
728 #endif
729         int open_ofun;
730         int32 open_size;
731         char *pname;
732         pstring fname;
733         SMB_OFF_T size=0;
734         int fattr=0,mtime=0;
735         SMB_INO_T inode = 0;
736         SMB_STRUCT_STAT sbuf;
737         int smb_action = 0;
738         BOOL bad_path = False;
739         files_struct *fsp;
740         TALLOC_CTX *ctx = NULL;
741         struct ea_list *ea_list = NULL;
742         uint16 flags = 0;
743         NTSTATUS status;
744         uint32 access_mask;
745         uint32 share_mode;
746         uint32 create_disposition;
747         uint32 create_options = 0;
748
749         /*
750          * Ensure we have enough parameters to perform the operation.
751          */
752
753         if (total_params < 29) {
754                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
755         }
756
757         flags = SVAL(params, 0);
758         deny_mode = SVAL(params, 2);
759         open_attr = SVAL(params,6);
760         oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
761         if (oplock_request) {
762                 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
763         }
764
765 #if 0
766         return_additional_info = BITSETW(params,0);
767         open_sattr = SVAL(params, 4);
768         open_time = make_unix_date3(params+8);
769 #endif
770         open_ofun = SVAL(params,12);
771         open_size = IVAL(params,14);
772         pname = &params[28];
773
774         if (IS_IPC(conn)) {
775                 return(ERROR_DOS(ERRSRV,ERRaccess));
776         }
777
778         srvstr_get_path(inbuf, fname, pname, sizeof(fname), -1, STR_TERMINATE, &status);
779         if (!NT_STATUS_IS_OK(status)) {
780                 return ERROR_NT(status);
781         }
782
783         DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
784                 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
785                 (unsigned int)open_ofun, open_size));
786
787         /* XXXX we need to handle passed times, sattr and flags */
788
789         unix_convert(fname,conn,0,&bad_path,&sbuf);
790         if (bad_path) {
791                 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
792         }
793     
794         if (!check_name(fname,conn)) {
795                 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
796         }
797
798         if (!map_open_params_to_ntcreate(fname, deny_mode, open_ofun,
799                                 &access_mask,
800                                 &share_mode,
801                                 &create_disposition,
802                                 &create_options)) {
803                 return ERROR_DOS(ERRDOS, ERRbadaccess);
804         }
805
806         /* Any data in this call is an EA list. */
807         if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
808                 return ERROR_NT(NT_STATUS_EAS_NOT_SUPPORTED);
809         }
810
811         if (total_data != 4) {
812                 if (total_data < 10) {
813                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
814                 }
815
816                 if (IVAL(pdata,0) > total_data) {
817                         DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
818                                 IVAL(pdata,0), (unsigned int)total_data));
819                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
820                 }
821
822                 ctx = talloc_init("TRANS2_OPEN_SET_EA");
823                 if (!ctx) {
824                         return ERROR_NT(NT_STATUS_NO_MEMORY);
825                 }
826                 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
827                 if (!ea_list) {
828                         talloc_destroy(ctx);
829                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
830                 }
831         } else if (IVAL(pdata,0) != 4) {
832                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
833         }
834
835         fsp = open_file_ntcreate(conn,fname,&sbuf,
836                 access_mask,
837                 share_mode,
838                 create_disposition,
839                 create_options,
840                 open_attr,
841                 oplock_request,
842                 &smb_action);
843       
844         if (!fsp) {
845                 talloc_destroy(ctx);
846                 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
847                         /* We have re-scheduled this call. */
848                         return -1;
849                 }
850                 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
851         }
852
853         size = get_file_size(sbuf);
854         fattr = dos_mode(conn,fname,&sbuf);
855         mtime = sbuf.st_mtime;
856         inode = sbuf.st_ino;
857         if (fattr & aDIR) {
858                 talloc_destroy(ctx);
859                 close_file(fsp,ERROR_CLOSE);
860                 return(ERROR_DOS(ERRDOS,ERRnoaccess));
861         }
862
863         if (total_data && smb_action == FILE_WAS_CREATED) {
864                 status = set_ea(conn, fsp, fname, ea_list);
865                 talloc_destroy(ctx);
866                 if (!NT_STATUS_IS_OK(status)) {
867                         close_file(fsp,ERROR_CLOSE);
868                         return ERROR_NT(status);
869                 }
870         }
871
872         /* Realloc the size of parameters and data we will return */
873         *pparams = SMB_REALLOC(*pparams, 30);
874         if(*pparams == NULL ) {
875                 return ERROR_NT(NT_STATUS_NO_MEMORY);
876         }
877         params = *pparams;
878
879         SSVAL(params,0,fsp->fnum);
880         SSVAL(params,2,open_attr);
881         srv_put_dos_date2(params,4, mtime);
882         SIVAL(params,8, (uint32)size);
883         SSVAL(params,12,deny_mode);
884         SSVAL(params,14,0); /* open_type - file or directory. */
885         SSVAL(params,16,0); /* open_state - only valid for IPC device. */
886
887         if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
888                 smb_action |= EXTENDED_OPLOCK_GRANTED;
889         }
890
891         SSVAL(params,18,smb_action);
892
893         /*
894          * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
895          */
896         SIVAL(params,20,inode);
897         SSVAL(params,24,0); /* Padding. */
898         if (flags & 8) {
899                 uint32 ea_size = estimate_ea_size(conn, fsp, fname);
900                 SIVAL(params, 26, ea_size);
901         } else {
902                 SIVAL(params, 26, 0);
903         }
904
905         /* Send the required number of replies */
906         send_trans2_replies(outbuf, bufsize, params, 30, *ppdata, 0);
907
908         return -1;
909 }
910
911 /*********************************************************
912  Routine to check if a given string matches exactly.
913  as a special case a mask of "." does NOT match. That
914  is required for correct wildcard semantics
915  Case can be significant or not.
916 **********************************************************/
917
918 static BOOL exact_match(char *str,char *mask, BOOL case_sig) 
919 {
920         if (mask[0] == '.' && mask[1] == 0)
921                 return False;
922         if (case_sig)   
923                 return strcmp(str,mask)==0;
924         if (StrCaseCmp(str,mask) != 0) {
925                 return False;
926         }
927         if (ms_has_wild(str)) {
928                 return False;
929         }
930         return True;
931 }
932
933 /****************************************************************************
934  Return the filetype for UNIX extensions.
935 ****************************************************************************/
936
937 static uint32 unix_filetype(mode_t mode)
938 {
939         if(S_ISREG(mode))
940                 return UNIX_TYPE_FILE;
941         else if(S_ISDIR(mode))
942                 return UNIX_TYPE_DIR;
943 #ifdef S_ISLNK
944         else if(S_ISLNK(mode))
945                 return UNIX_TYPE_SYMLINK;
946 #endif
947 #ifdef S_ISCHR
948         else if(S_ISCHR(mode))
949                 return UNIX_TYPE_CHARDEV;
950 #endif
951 #ifdef S_ISBLK
952         else if(S_ISBLK(mode))
953                 return UNIX_TYPE_BLKDEV;
954 #endif
955 #ifdef S_ISFIFO
956         else if(S_ISFIFO(mode))
957                 return UNIX_TYPE_FIFO;
958 #endif
959 #ifdef S_ISSOCK
960         else if(S_ISSOCK(mode))
961                 return UNIX_TYPE_SOCKET;
962 #endif
963
964         DEBUG(0,("unix_filetype: unknown filetype %u", (unsigned)mode));
965         return UNIX_TYPE_UNKNOWN;
966 }
967
968 /****************************************************************************
969  Map wire perms onto standard UNIX permissions. Obey share restrictions.
970 ****************************************************************************/
971
972 static mode_t unix_perms_from_wire( connection_struct *conn, SMB_STRUCT_STAT *pst, uint32 perms)
973 {
974         mode_t ret = 0;
975
976         if (perms == SMB_MODE_NO_CHANGE)
977                 return pst->st_mode;
978
979         ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
980         ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
981         ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
982         ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
983         ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
984         ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
985         ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
986         ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
987         ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
988 #ifdef S_ISVTX
989         ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
990 #endif
991 #ifdef S_ISGID
992         ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
993 #endif
994 #ifdef S_ISUID
995         ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
996 #endif
997
998         if (VALID_STAT(*pst) && S_ISDIR(pst->st_mode)) {
999                 ret &= lp_dir_mask(SNUM(conn));
1000                 /* Add in force bits */
1001                 ret |= lp_force_dir_mode(SNUM(conn));
1002         } else {
1003                 /* Apply mode mask */
1004                 ret &= lp_create_mask(SNUM(conn));
1005                 /* Add in force bits */
1006                 ret |= lp_force_create_mode(SNUM(conn));
1007         }
1008
1009         return ret;
1010 }
1011
1012 /****************************************************************************
1013  Get a level dependent lanman2 dir entry.
1014 ****************************************************************************/
1015
1016 static BOOL get_lanman2_dir_entry(connection_struct *conn,
1017                                   void *inbuf, void *outbuf,
1018                                  char *path_mask,uint32 dirtype,int info_level,
1019                                  int requires_resume_key,
1020                                  BOOL dont_descend,char **ppdata, 
1021                                  char *base_data, int space_remaining, 
1022                                  BOOL *out_of_space, BOOL *got_exact_match,
1023                                  int *last_entry_off, struct ea_list *name_list, TALLOC_CTX *ea_ctx)
1024 {
1025         const char *dname;
1026         BOOL found = False;
1027         SMB_STRUCT_STAT sbuf;
1028         pstring mask;
1029         pstring pathreal;
1030         pstring fname;
1031         char *p, *q, *pdata = *ppdata;
1032         uint32 reskey=0;
1033         long prev_dirpos=0;
1034         uint32 mode=0;
1035         SMB_OFF_T file_size = 0;
1036         SMB_BIG_UINT allocation_size = 0;
1037         uint32 len;
1038         time_t mdate=0, adate=0, cdate=0;
1039         char *nameptr;
1040         char *last_entry_ptr;
1041         BOOL was_8_3;
1042         uint32 nt_extmode; /* Used for NT connections instead of mode */
1043         BOOL needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
1044         BOOL check_mangled_names = lp_manglednames(SNUM(conn));
1045
1046         *fname = 0;
1047         *out_of_space = False;
1048         *got_exact_match = False;
1049
1050         if (!conn->dirptr)
1051                 return(False);
1052
1053         p = strrchr_m(path_mask,'/');
1054         if(p != NULL) {
1055                 if(p[1] == '\0')
1056                         pstrcpy(mask,"*.*");
1057                 else
1058                         pstrcpy(mask, p+1);
1059         } else
1060                 pstrcpy(mask, path_mask);
1061
1062
1063         while (!found) {
1064                 BOOL got_match;
1065                 /* Needed if we run out of space */
1066                 long curr_dirpos = prev_dirpos = dptr_TellDir(conn->dirptr);
1067                 dname = dptr_ReadDirName(conn->dirptr,&curr_dirpos,&sbuf);
1068
1069                 /*
1070                  * Due to bugs in NT client redirectors we are not using
1071                  * resume keys any more - set them to zero.
1072                  * Check out the related comments in findfirst/findnext.
1073                  * JRA.
1074                  */
1075
1076                 reskey = 0;
1077
1078                 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %ld\n",
1079                         (long)conn->dirptr,curr_dirpos));
1080       
1081                 if (!dname) 
1082                         return(False);
1083
1084                 pstrcpy(fname,dname);      
1085
1086                 if(!(got_match = *got_exact_match = exact_match(fname, mask, conn->case_sensitive)))
1087                         got_match = mask_match(fname, mask, conn->case_sensitive);
1088
1089                 if(!got_match && check_mangled_names && !mangle_is_8_3(fname, False, SNUM(conn))) {
1090
1091                         /*
1092                          * It turns out that NT matches wildcards against
1093                          * both long *and* short names. This may explain some
1094                          * of the wildcard wierdness from old DOS clients
1095                          * that some people have been seeing.... JRA.
1096                          */
1097
1098                         pstring newname;
1099                         pstrcpy( newname, fname);
1100                         mangle_map( newname, True, False, SNUM(conn));
1101                         if(!(got_match = *got_exact_match = exact_match(newname, mask, conn->case_sensitive)))
1102                                 got_match = mask_match(newname, mask, conn->case_sensitive);
1103                 }
1104
1105                 if(got_match) {
1106                         BOOL isdots = (strequal(fname,"..") || strequal(fname,"."));
1107                         if (dont_descend && !isdots)
1108                                 continue;
1109           
1110                         pstrcpy(pathreal,conn->dirpath);
1111                         if(needslash)
1112                                 pstrcat(pathreal,"/");
1113                         pstrcat(pathreal,dname);
1114
1115                         if (INFO_LEVEL_IS_UNIX(info_level)) {
1116                                 if (SMB_VFS_LSTAT(conn,pathreal,&sbuf) != 0) {
1117                                         DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",
1118                                                 pathreal,strerror(errno)));
1119                                         continue;
1120                                 }
1121                         } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,pathreal,&sbuf) != 0) {
1122
1123                                 /* Needed to show the msdfs symlinks as 
1124                                  * directories */
1125
1126                                 if(lp_host_msdfs() && 
1127                                    lp_msdfs_root(SNUM(conn)) &&
1128                                    is_msdfs_link(NULL,conn, pathreal, NULL, NULL,
1129                                                  &sbuf)) {
1130
1131                                         DEBUG(5,("get_lanman2_dir_entry: Masquerading msdfs link %s as a directory\n", pathreal));
1132                                         sbuf.st_mode = (sbuf.st_mode & 0xFFF) | S_IFDIR;
1133
1134                                 } else {
1135
1136                                         DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
1137                                                 pathreal,strerror(errno)));
1138                                         continue;
1139                                 }
1140                         }
1141
1142                         mode = dos_mode(conn,pathreal,&sbuf);
1143
1144                         if (!dir_check_ftype(conn,mode,dirtype)) {
1145                                 DEBUG(5,("[%s] attribs didn't match %x\n",fname,dirtype));
1146                                 continue;
1147                         }
1148
1149                         if (!(mode & aDIR))
1150                                 file_size = get_file_size(sbuf);
1151                         allocation_size = get_allocation_size(conn,NULL,&sbuf);
1152                         mdate = sbuf.st_mtime;
1153                         adate = sbuf.st_atime;
1154                         cdate = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
1155
1156                         if (lp_dos_filetime_resolution(SNUM(conn))) {
1157                                 cdate &= ~1;
1158                                 mdate &= ~1;
1159                                 adate &= ~1;
1160                         }
1161
1162
1163                         DEBUG(5,("get_lanman2_dir_entry found %s fname=%s\n",pathreal,fname));
1164           
1165                         found = True;
1166
1167                         dptr_DirCacheAdd(conn->dirptr, dname, curr_dirpos);
1168                 }
1169         }
1170
1171         mangle_map(fname,False,True,SNUM(conn));
1172
1173         p = pdata;
1174         last_entry_ptr = p;
1175
1176         nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
1177
1178         switch (info_level) {
1179                 case SMB_FIND_INFO_STANDARD:
1180                         DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1181                         if(requires_resume_key) {
1182                                 SIVAL(p,0,reskey);
1183                                 p += 4;
1184                         }
1185                         srv_put_dos_date2(p,0,cdate);
1186                         srv_put_dos_date2(p,4,adate);
1187                         srv_put_dos_date2(p,8,mdate);
1188                         SIVAL(p,12,(uint32)file_size);
1189                         SIVAL(p,16,(uint32)allocation_size);
1190                         SSVAL(p,20,mode);
1191                         p += 23;
1192                         nameptr = p;
1193                         p += align_string(outbuf, p, 0);
1194                         len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
1195                         if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1196                                 if (len > 2) {
1197                                         SCVAL(nameptr, -1, len - 2);
1198                                 } else {
1199                                         SCVAL(nameptr, -1, 0);
1200                                 }
1201                         } else {
1202                                 if (len > 1) {
1203                                         SCVAL(nameptr, -1, len - 1);
1204                                 } else {
1205                                         SCVAL(nameptr, -1, 0);
1206                                 }
1207                         }
1208                         p += len;
1209                         break;
1210
1211                 case SMB_FIND_EA_SIZE:
1212                         DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n"));
1213                         if(requires_resume_key) {
1214                                 SIVAL(p,0,reskey);
1215                                 p += 4;
1216                         }
1217                         srv_put_dos_date2(p,0,cdate);
1218                         srv_put_dos_date2(p,4,adate);
1219                         srv_put_dos_date2(p,8,mdate);
1220                         SIVAL(p,12,(uint32)file_size);
1221                         SIVAL(p,16,(uint32)allocation_size);
1222                         SSVAL(p,20,mode);
1223                         {
1224                                 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1225                                 SIVAL(p,22,ea_size); /* Extended attributes */
1226                         }
1227                         p += 27;
1228                         nameptr = p - 1;
1229                         len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE | STR_NOALIGN);
1230                         if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1231                                 if (len > 2) {
1232                                         len -= 2;
1233                                 } else {
1234                                         len = 0;
1235                                 }
1236                         } else {
1237                                 if (len > 1) {
1238                                         len -= 1;
1239                                 } else {
1240                                         len = 0;
1241                                 }
1242                         }
1243                         SCVAL(nameptr,0,len);
1244                         p += len;
1245                         SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1246                         break;
1247
1248                 case SMB_FIND_EA_LIST:
1249                 {
1250                         struct ea_list *file_list = NULL;
1251                         size_t ea_len = 0;
1252
1253                         DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n"));
1254                         if (!name_list) {
1255                                 return False;
1256                         }
1257                         if(requires_resume_key) {
1258                                 SIVAL(p,0,reskey);
1259                                 p += 4;
1260                         }
1261                         srv_put_dos_date2(p,0,cdate);
1262                         srv_put_dos_date2(p,4,adate);
1263                         srv_put_dos_date2(p,8,mdate);
1264                         SIVAL(p,12,(uint32)file_size);
1265                         SIVAL(p,16,(uint32)allocation_size);
1266                         SSVAL(p,20,mode);
1267                         p += 22; /* p now points to the EA area. */
1268
1269                         file_list = get_ea_list_from_file(ea_ctx, conn, NULL, pathreal, &ea_len);
1270                         name_list = ea_list_union(name_list, file_list, &ea_len);
1271
1272                         /* We need to determine if this entry will fit in the space available. */
1273                         /* Max string size is 255 bytes. */
1274                         if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1275                                 /* Move the dirptr back to prev_dirpos */
1276                                 dptr_SeekDir(conn->dirptr, prev_dirpos);
1277                                 *out_of_space = True;
1278                                 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1279                                 return False; /* Not finished - just out of space */
1280                         }
1281
1282                         /* Push the ea_data followed by the name. */
1283                         p += fill_ea_buffer(ea_ctx, p, space_remaining, conn, name_list);
1284                         nameptr = p;
1285                         len = srvstr_push(outbuf, p + 1, fname, -1, STR_TERMINATE | STR_NOALIGN);
1286                         if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1287                                 if (len > 2) {
1288                                         len -= 2;
1289                                 } else {
1290                                         len = 0;
1291                                 }
1292                         } else {
1293                                 if (len > 1) {
1294                                         len -= 1;
1295                                 } else {
1296                                         len = 0;
1297                                 }
1298                         }
1299                         SCVAL(nameptr,0,len);
1300                         p += len + 1;
1301                         SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1302                         break;
1303                 }
1304
1305                 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1306                         DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1307                         was_8_3 = mangle_is_8_3(fname, True, SNUM(conn));
1308                         p += 4;
1309                         SIVAL(p,0,reskey); p += 4;
1310                         put_long_date(p,cdate); p += 8;
1311                         put_long_date(p,adate); p += 8;
1312                         put_long_date(p,mdate); p += 8;
1313                         put_long_date(p,mdate); p += 8;
1314                         SOFF_T(p,0,file_size); p += 8;
1315                         SOFF_T(p,0,allocation_size); p += 8;
1316                         SIVAL(p,0,nt_extmode); p += 4;
1317                         q = p; p += 4; /* q is placeholder for name length. */
1318                         {
1319                                 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1320                                 SIVAL(p,0,ea_size); /* Extended attributes */
1321                                 p += 4;
1322                         }
1323                         /* Clear the short name buffer. This is
1324                          * IMPORTANT as not doing so will trigger
1325                          * a Win2k client bug. JRA.
1326                          */
1327                         if (!was_8_3 && check_mangled_names) {
1328                                 pstring mangled_name;
1329                                 pstrcpy(mangled_name, fname);
1330                                 mangle_map(mangled_name,True,True,SNUM(conn));
1331                                 mangled_name[12] = 0;
1332                                 len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE);
1333                                 if (len < 24) {
1334                                         memset(p + 2 + len,'\0',24 - len);
1335                                 }
1336                                 SSVAL(p, 0, len);
1337                         } else {
1338                                 memset(p,'\0',26);
1339                         }
1340                         p += 2 + 24;
1341                         len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1342                         SIVAL(q,0,len);
1343                         p += len;
1344                         SIVAL(p,0,0); /* Ensure any padding is null. */
1345                         len = PTR_DIFF(p, pdata);
1346                         len = (len + 3) & ~3;
1347                         SIVAL(pdata,0,len);
1348                         p = pdata + len;
1349                         break;
1350
1351                 case SMB_FIND_FILE_DIRECTORY_INFO:
1352                         DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1353                         p += 4;
1354                         SIVAL(p,0,reskey); p += 4;
1355                         put_long_date(p,cdate); p += 8;
1356                         put_long_date(p,adate); p += 8;
1357                         put_long_date(p,mdate); p += 8;
1358                         put_long_date(p,mdate); p += 8;
1359                         SOFF_T(p,0,file_size); p += 8;
1360                         SOFF_T(p,0,allocation_size); p += 8;
1361                         SIVAL(p,0,nt_extmode); p += 4;
1362                         len = srvstr_push(outbuf, p + 4, fname, -1, STR_TERMINATE_ASCII);
1363                         SIVAL(p,0,len);
1364                         p += 4 + len;
1365                         SIVAL(p,0,0); /* Ensure any padding is null. */
1366                         len = PTR_DIFF(p, pdata);
1367                         len = (len + 3) & ~3;
1368                         SIVAL(pdata,0,len);
1369                         p = pdata + len;
1370                         break;
1371       
1372                 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1373                         DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1374                         p += 4;
1375                         SIVAL(p,0,reskey); p += 4;
1376                         put_long_date(p,cdate); p += 8;
1377                         put_long_date(p,adate); p += 8;
1378                         put_long_date(p,mdate); p += 8;
1379                         put_long_date(p,mdate); p += 8;
1380                         SOFF_T(p,0,file_size); p += 8;
1381                         SOFF_T(p,0,allocation_size); p += 8;
1382                         SIVAL(p,0,nt_extmode); p += 4;
1383                         q = p; p += 4; /* q is placeholder for name length. */
1384                         {
1385                                 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1386                                 SIVAL(p,0,ea_size); /* Extended attributes */
1387                                 p +=4;
1388                         }
1389                         len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1390                         SIVAL(q, 0, len);
1391                         p += len;
1392
1393                         SIVAL(p,0,0); /* Ensure any padding is null. */
1394                         len = PTR_DIFF(p, pdata);
1395                         len = (len + 3) & ~3;
1396                         SIVAL(pdata,0,len);
1397                         p = pdata + len;
1398                         break;
1399
1400                 case SMB_FIND_FILE_NAMES_INFO:
1401                         DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1402                         p += 4;
1403                         SIVAL(p,0,reskey); p += 4;
1404                         p += 4;
1405                         /* this must *not* be null terminated or w2k gets in a loop trying to set an
1406                            acl on a dir (tridge) */
1407                         len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1408                         SIVAL(p, -4, len);
1409                         p += len;
1410                         SIVAL(p,0,0); /* Ensure any padding is null. */
1411                         len = PTR_DIFF(p, pdata);
1412                         len = (len + 3) & ~3;
1413                         SIVAL(pdata,0,len);
1414                         p = pdata + len;
1415                         break;
1416
1417                 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1418                         DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1419                         p += 4;
1420                         SIVAL(p,0,reskey); p += 4;
1421                         put_long_date(p,cdate); p += 8;
1422                         put_long_date(p,adate); p += 8;
1423                         put_long_date(p,mdate); p += 8;
1424                         put_long_date(p,mdate); p += 8;
1425                         SOFF_T(p,0,file_size); p += 8;
1426                         SOFF_T(p,0,allocation_size); p += 8;
1427                         SIVAL(p,0,nt_extmode); p += 4;
1428                         q = p; p += 4; /* q is placeholder for name length. */
1429                         {
1430                                 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1431                                 SIVAL(p,0,ea_size); /* Extended attributes */
1432                                 p +=4;
1433                         }
1434                         SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1435                         SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1436                         SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1437                         len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1438                         SIVAL(q, 0, len);
1439                         p += len; 
1440                         SIVAL(p,0,0); /* Ensure any padding is null. */
1441                         len = PTR_DIFF(p, pdata);
1442                         len = (len + 3) & ~3;
1443                         SIVAL(pdata,0,len);
1444                         p = pdata + len;
1445                         break;
1446
1447                 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1448                         DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1449                         was_8_3 = mangle_is_8_3(fname, True, SNUM(conn));
1450                         p += 4;
1451                         SIVAL(p,0,reskey); p += 4;
1452                         put_long_date(p,cdate); p += 8;
1453                         put_long_date(p,adate); p += 8;
1454                         put_long_date(p,mdate); p += 8;
1455                         put_long_date(p,mdate); p += 8;
1456                         SOFF_T(p,0,file_size); p += 8;
1457                         SOFF_T(p,0,allocation_size); p += 8;
1458                         SIVAL(p,0,nt_extmode); p += 4;
1459                         q = p; p += 4; /* q is placeholder for name length */
1460                         {
1461                                 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1462                                 SIVAL(p,0,ea_size); /* Extended attributes */
1463                                 p +=4;
1464                         }
1465                         /* Clear the short name buffer. This is
1466                          * IMPORTANT as not doing so will trigger
1467                          * a Win2k client bug. JRA.
1468                          */
1469                         if (!was_8_3 && check_mangled_names) {
1470                                 pstring mangled_name;
1471                                 pstrcpy(mangled_name, fname);
1472                                 mangle_map(mangled_name,True,True,SNUM(conn));
1473                                 mangled_name[12] = 0;
1474                                 len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE);
1475                                 SSVAL(p, 0, len);
1476                                 if (len < 24) {
1477                                         memset(p + 2 + len,'\0',24 - len);
1478                                 }
1479                                 SSVAL(p, 0, len);
1480                         } else {
1481                                 memset(p,'\0',26);
1482                         }
1483                         p += 26;
1484                         SSVAL(p,0,0); p += 2; /* Reserved ? */
1485                         SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1486                         SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1487                         len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1488                         SIVAL(q,0,len);
1489                         p += len;
1490                         SIVAL(p,0,0); /* Ensure any padding is null. */
1491                         len = PTR_DIFF(p, pdata);
1492                         len = (len + 3) & ~3;
1493                         SIVAL(pdata,0,len);
1494                         p = pdata + len;
1495                         break;
1496
1497                 /* CIFS UNIX Extension. */
1498
1499                 case SMB_FIND_FILE_UNIX:
1500                         DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1501                         p+= 4;
1502                         SIVAL(p,0,reskey); p+= 4;    /* Used for continuing search. */
1503
1504                         /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1505                         SOFF_T(p,0,get_file_size(sbuf));             /* File size 64 Bit */
1506                         p+= 8;
1507
1508                         SOFF_T(p,0,get_allocation_size(conn,NULL,&sbuf)); /* Number of bytes used on disk - 64 Bit */
1509                         p+= 8;
1510
1511                         put_long_date(p,sbuf.st_ctime);       /* Inode change Time 64 Bit */
1512                         put_long_date(p+8,sbuf.st_atime);     /* Last access time 64 Bit */
1513                         put_long_date(p+16,sbuf.st_mtime);    /* Last modification time 64 Bit */
1514                         p+= 24;
1515
1516                         SIVAL(p,0,sbuf.st_uid);               /* user id for the owner */
1517                         SIVAL(p,4,0);
1518                         p+= 8;
1519
1520                         SIVAL(p,0,sbuf.st_gid);               /* group id of owner */
1521                         SIVAL(p,4,0);
1522                         p+= 8;
1523
1524                         SIVAL(p,0,unix_filetype(sbuf.st_mode));
1525                         p+= 4;
1526
1527                         SIVAL(p,0,unix_dev_major(sbuf.st_rdev));   /* Major device number if type is device */
1528                         SIVAL(p,4,0);
1529                         p+= 8;
1530
1531                         SIVAL(p,0,unix_dev_minor(sbuf.st_rdev));   /* Minor device number if type is device */
1532                         SIVAL(p,4,0);
1533                         p+= 8;
1534
1535                         SINO_T_VAL(p,0,(SMB_INO_T)sbuf.st_ino);   /* inode number */
1536                         p+= 8;
1537
1538                         SIVAL(p,0, unix_perms_to_wire(sbuf.st_mode));     /* Standard UNIX file permissions */
1539                         SIVAL(p,4,0);
1540                         p+= 8;
1541
1542                         SIVAL(p,0,sbuf.st_nlink);             /* number of hard links */
1543                         SIVAL(p,4,0);
1544                         p+= 8;
1545
1546                         len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
1547                         p += len;
1548                         SIVAL(p,0,0); /* Ensure any padding is null. */
1549
1550                         len = PTR_DIFF(p, pdata);
1551                         len = (len + 3) & ~3;
1552                         SIVAL(pdata,0,len);     /* Offset from this structure to the beginning of the next one */
1553                         p = pdata + len;
1554                         /* End of SMB_QUERY_FILE_UNIX_BASIC */
1555
1556                         break;
1557
1558                 default:      
1559                         return(False);
1560         }
1561
1562
1563         if (PTR_DIFF(p,pdata) > space_remaining) {
1564                 /* Move the dirptr back to prev_dirpos */
1565                 dptr_SeekDir(conn->dirptr, prev_dirpos);
1566                 *out_of_space = True;
1567                 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1568                 return False; /* Not finished - just out of space */
1569         }
1570
1571         /* Setup the last entry pointer, as an offset from base_data */
1572         *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
1573         /* Advance the data pointer to the next slot */
1574         *ppdata = p;
1575
1576         return(found);
1577 }
1578
1579 /****************************************************************************
1580  Reply to a TRANS2_FINDFIRST.
1581 ****************************************************************************/
1582
1583 static int call_trans2findfirst(connection_struct *conn, char *inbuf, char *outbuf, int bufsize,  
1584                                 char **pparams, int total_params, char **ppdata, int total_data,
1585                                 unsigned int max_data_bytes)
1586 {
1587         /* We must be careful here that we don't return more than the
1588                 allowed number of data bytes. If this means returning fewer than
1589                 maxentries then so be it. We assume that the redirector has
1590                 enough room for the fixed number of parameter bytes it has
1591                 requested. */
1592         char *params = *pparams;
1593         char *pdata = *ppdata;
1594         uint32 dirtype = SVAL(params,0);
1595         int maxentries = SVAL(params,2);
1596         uint16 findfirst_flags = SVAL(params,4);
1597         BOOL close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
1598         BOOL close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1599         BOOL requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1600         int info_level = SVAL(params,6);
1601         pstring directory;
1602         pstring mask;
1603         char *p;
1604         int last_entry_off=0;
1605         int dptr_num = -1;
1606         int numentries = 0;
1607         int i;
1608         BOOL finished = False;
1609         BOOL dont_descend = False;
1610         BOOL out_of_space = False;
1611         int space_remaining;
1612         BOOL bad_path = False;
1613         BOOL mask_contains_wcard = False;
1614         SMB_STRUCT_STAT sbuf;
1615         TALLOC_CTX *ea_ctx = NULL;
1616         struct ea_list *ea_list = NULL;
1617         NTSTATUS ntstatus = NT_STATUS_OK;
1618
1619         if (total_params < 12) {
1620                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1621         }
1622
1623         *directory = *mask = 0;
1624
1625         DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
1626 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
1627                 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
1628                 info_level, max_data_bytes));
1629
1630         if (!maxentries) {
1631                 /* W2K3 seems to treat zero as 1. */
1632                 maxentries = 1;
1633         }
1634  
1635         switch (info_level) {
1636                 case SMB_FIND_INFO_STANDARD:
1637                 case SMB_FIND_EA_SIZE:
1638                 case SMB_FIND_EA_LIST:
1639                 case SMB_FIND_FILE_DIRECTORY_INFO:
1640                 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1641                 case SMB_FIND_FILE_NAMES_INFO:
1642                 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1643                 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1644                 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1645                         break;
1646                 case SMB_FIND_FILE_UNIX:
1647                         if (!lp_unix_extensions())
1648                                 return(ERROR_DOS(ERRDOS,ERRunknownlevel));
1649                         break;
1650                 default:
1651                         return(ERROR_DOS(ERRDOS,ERRunknownlevel));
1652         }
1653
1654         srvstr_get_path_wcard(inbuf, directory, params+12, sizeof(directory), -1, STR_TERMINATE, &ntstatus, &mask_contains_wcard);
1655         if (!NT_STATUS_IS_OK(ntstatus)) {
1656                 return ERROR_NT(ntstatus);
1657         }
1658
1659         RESOLVE_DFSPATH_WCARD(directory, conn, inbuf, outbuf);
1660
1661         unix_convert(directory,conn,0,&bad_path,&sbuf);
1662         if (bad_path) {
1663                 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
1664         }
1665         if(!check_name(directory,conn)) {
1666                 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
1667         }
1668
1669         p = strrchr_m(directory,'/');
1670         if(p == NULL) {
1671                 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
1672                 if((directory[0] == '.') && (directory[1] == '\0')) {
1673                         pstrcpy(mask,"*");
1674                         mask_contains_wcard = True;
1675                 } else {
1676                         pstrcpy(mask,directory);
1677                 }
1678                 pstrcpy(directory,"./");
1679         } else {
1680                 pstrcpy(mask,p+1);
1681                 *p = 0;
1682         }
1683
1684         DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
1685
1686         if (info_level == SMB_FIND_EA_LIST) {
1687                 uint32 ea_size;
1688
1689                 if (total_data < 4) {
1690                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1691                 }
1692
1693                 ea_size = IVAL(pdata,0);
1694                 if (ea_size != total_data) {
1695                         DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
1696 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
1697                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1698                 }
1699
1700                 if (!lp_ea_support(SNUM(conn))) {
1701                         return ERROR_DOS(ERRDOS,ERReasnotsupported);
1702                 }
1703                                                                                                                                                         
1704                 if ((ea_ctx = talloc_init("findnext_ea_list")) == NULL) {
1705                         return ERROR_NT(NT_STATUS_NO_MEMORY);
1706                 }
1707                                                                                                                                                         
1708                 /* Pull out the list of names. */
1709                 ea_list = read_ea_name_list(ea_ctx, pdata + 4, ea_size - 4);
1710                 if (!ea_list) {
1711                         talloc_destroy(ea_ctx);
1712                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1713                 }
1714         }
1715
1716         *ppdata = SMB_REALLOC(*ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1717         if(*ppdata == NULL ) {
1718                 talloc_destroy(ea_ctx);
1719                 return ERROR_NT(NT_STATUS_NO_MEMORY);
1720         }
1721         pdata = *ppdata;
1722
1723         /* Realloc the params space */
1724         *pparams = SMB_REALLOC(*pparams, 10);
1725         if (*pparams == NULL) {
1726                 talloc_destroy(ea_ctx);
1727                 return ERROR_NT(NT_STATUS_NO_MEMORY);
1728         }
1729         params = *pparams;
1730
1731         /* Save the wildcard match and attribs we are using on this directory - 
1732                 needed as lanman2 assumes these are being saved between calls */
1733
1734         dptr_num = dptr_create(conn,directory, False, True ,SVAL(inbuf,smb_pid), mask, mask_contains_wcard, dirtype);
1735         if (dptr_num < 0) {
1736                 talloc_destroy(ea_ctx);
1737                 return(UNIXERROR(ERRDOS,ERRbadfile));
1738         }
1739
1740         DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n",dptr_num, mask, dirtype));
1741
1742         /* We don't need to check for VOL here as this is returned by 
1743                 a different TRANS2 call. */
1744   
1745         DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
1746         if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
1747                 dont_descend = True;
1748     
1749         p = pdata;
1750         space_remaining = max_data_bytes;
1751         out_of_space = False;
1752
1753         for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
1754                 BOOL got_exact_match = False;
1755
1756                 /* this is a heuristic to avoid seeking the dirptr except when 
1757                         absolutely necessary. It allows for a filename of about 40 chars */
1758                 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
1759                         out_of_space = True;
1760                         finished = False;
1761                 } else {
1762                         finished = !get_lanman2_dir_entry(conn,
1763                                         inbuf, outbuf,
1764                                         mask,dirtype,info_level,
1765                                         requires_resume_key,dont_descend,
1766                                         &p,pdata,space_remaining, &out_of_space, &got_exact_match,
1767                                         &last_entry_off, ea_list, ea_ctx);
1768                 }
1769
1770                 if (finished && out_of_space)
1771                         finished = False;
1772
1773                 if (!finished && !out_of_space)
1774                         numentries++;
1775
1776                 /*
1777                  * As an optimisation if we know we aren't looking
1778                  * for a wildcard name (ie. the name matches the wildcard exactly)
1779                  * then we can finish on any (first) match.
1780                  * This speeds up large directory searches. JRA.
1781                  */
1782
1783                 if(got_exact_match)
1784                         finished = True;
1785
1786                 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
1787         }
1788   
1789         talloc_destroy(ea_ctx);
1790
1791         /* Check if we can close the dirptr */
1792         if(close_after_first || (finished && close_if_end)) {
1793                 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
1794                 dptr_close(&dptr_num);
1795         }
1796
1797         /* 
1798          * If there are no matching entries we must return ERRDOS/ERRbadfile - 
1799          * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
1800          * the protocol level is less than NT1. Tested with smbclient. JRA.
1801          * This should fix the OS/2 client bug #2335.
1802          */
1803
1804         if(numentries == 0) {
1805                 dptr_close(&dptr_num);
1806                 if (Protocol < PROTOCOL_NT1) {
1807                         return ERROR_DOS(ERRDOS,ERRnofiles);
1808                 } else {
1809                         return ERROR_BOTH(NT_STATUS_NO_SUCH_FILE,ERRDOS,ERRbadfile);
1810                 }
1811         }
1812
1813         /* At this point pdata points to numentries directory entries. */
1814
1815         /* Set up the return parameter block */
1816         SSVAL(params,0,dptr_num);
1817         SSVAL(params,2,numentries);
1818         SSVAL(params,4,finished);
1819         SSVAL(params,6,0); /* Never an EA error */
1820         SSVAL(params,8,last_entry_off);
1821
1822         send_trans2_replies( outbuf, bufsize, params, 10, pdata, PTR_DIFF(p,pdata));
1823
1824         if ((! *directory) && dptr_path(dptr_num))
1825                 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1826
1827         DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
1828                 smb_fn_name(CVAL(inbuf,smb_com)), 
1829                 mask, directory, dirtype, numentries ) );
1830
1831         /* 
1832          * Force a name mangle here to ensure that the
1833          * mask as an 8.3 name is top of the mangled cache.
1834          * The reasons for this are subtle. Don't remove
1835          * this code unless you know what you are doing
1836          * (see PR#13758). JRA.
1837          */
1838
1839         if(!mangle_is_8_3_wildcards( mask, False, SNUM(conn)))
1840                 mangle_map(mask, True, True, SNUM(conn));
1841
1842         return(-1);
1843 }
1844
1845 /****************************************************************************
1846  Reply to a TRANS2_FINDNEXT.
1847 ****************************************************************************/
1848
1849 static int call_trans2findnext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
1850                                         char **pparams, int total_params, char **ppdata, int total_data,
1851                                         unsigned int max_data_bytes)
1852 {
1853         /* We must be careful here that we don't return more than the
1854                 allowed number of data bytes. If this means returning fewer than
1855                 maxentries then so be it. We assume that the redirector has
1856                 enough room for the fixed number of parameter bytes it has
1857                 requested. */
1858         char *params = *pparams;
1859         char *pdata = *ppdata;
1860         int dptr_num = SVAL(params,0);
1861         int maxentries = SVAL(params,2);
1862         uint16 info_level = SVAL(params,4);
1863         uint32 resume_key = IVAL(params,6);
1864         uint16 findnext_flags = SVAL(params,10);
1865         BOOL close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
1866         BOOL close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1867         BOOL requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1868         BOOL continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
1869         BOOL mask_contains_wcard = False;
1870         pstring resume_name;
1871         pstring mask;
1872         pstring directory;
1873         char *p;
1874         uint16 dirtype;
1875         int numentries = 0;
1876         int i, last_entry_off=0;
1877         BOOL finished = False;
1878         BOOL dont_descend = False;
1879         BOOL out_of_space = False;
1880         int space_remaining;
1881         TALLOC_CTX *ea_ctx = NULL;
1882         struct ea_list *ea_list = NULL;
1883         NTSTATUS ntstatus = NT_STATUS_OK;
1884
1885         if (total_params < 12) {
1886                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1887         }
1888
1889         *mask = *directory = *resume_name = 0;
1890
1891         srvstr_get_path_wcard(inbuf, resume_name, params+12, sizeof(resume_name), -1, STR_TERMINATE, &ntstatus, &mask_contains_wcard);
1892         if (!NT_STATUS_IS_OK(ntstatus)) {
1893                 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
1894                    complain (it thinks we're asking for the directory above the shared
1895                    path or an invalid name). Catch this as the resume name is only compared, never used in
1896                    a file access. JRA. */
1897                 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_OBJECT_PATH_SYNTAX_BAD)) {
1898                         pstrcpy(resume_name, "..");
1899                 } else if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_OBJECT_NAME_INVALID)) {
1900                         pstrcpy(resume_name, ".");
1901                 } else {
1902                         return ERROR_NT(ntstatus);
1903                 }
1904         }
1905
1906         DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
1907 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
1908 resume_key = %d resume name = %s continue=%d level = %d\n",
1909                 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end, 
1910                 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
1911
1912         if (!maxentries) {
1913                 /* W2K3 seems to treat zero as 1. */
1914                 maxentries = 1;
1915         }
1916
1917         switch (info_level) {
1918                 case SMB_FIND_INFO_STANDARD:
1919                 case SMB_FIND_EA_SIZE:
1920                 case SMB_FIND_EA_LIST:
1921                 case SMB_FIND_FILE_DIRECTORY_INFO:
1922                 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1923                 case SMB_FIND_FILE_NAMES_INFO:
1924                 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1925                 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1926                 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1927                         break;
1928                 case SMB_FIND_FILE_UNIX:
1929                         if (!lp_unix_extensions())
1930                                 return(ERROR_DOS(ERRDOS,ERRunknownlevel));
1931                         break;
1932                 default:
1933                         return ERROR_DOS(ERRDOS,ERRunknownlevel);
1934         }
1935
1936         if (info_level == SMB_FIND_EA_LIST) {
1937                 uint32 ea_size;
1938
1939                 if (total_data < 4) {
1940                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1941                 }
1942
1943                 ea_size = IVAL(pdata,0);
1944                 if (ea_size != total_data) {
1945                         DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
1946 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
1947                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1948                 }
1949                                                                                                                                                      
1950                 if (!lp_ea_support(SNUM(conn))) {
1951                         return ERROR_DOS(ERRDOS,ERReasnotsupported);
1952                 }
1953                                                                                                                                                      
1954                 if ((ea_ctx = talloc_init("findnext_ea_list")) == NULL) {
1955                         return ERROR_NT(NT_STATUS_NO_MEMORY);
1956                 }
1957
1958                 /* Pull out the list of names. */
1959                 ea_list = read_ea_name_list(ea_ctx, pdata + 4, ea_size - 4);
1960                 if (!ea_list) {
1961                         talloc_destroy(ea_ctx);
1962                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1963                 }
1964         }
1965
1966         *ppdata = SMB_REALLOC( *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1967         if(*ppdata == NULL) {
1968                 talloc_destroy(ea_ctx);
1969                 return ERROR_NT(NT_STATUS_NO_MEMORY);
1970         }
1971
1972         pdata = *ppdata;
1973
1974         /* Realloc the params space */
1975         *pparams = SMB_REALLOC(*pparams, 6*SIZEOFWORD);
1976         if(*pparams == NULL ) {
1977                 talloc_destroy(ea_ctx);
1978                 return ERROR_NT(NT_STATUS_NO_MEMORY);
1979         }
1980
1981         params = *pparams;
1982
1983         /* Check that the dptr is valid */
1984         if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num))) {
1985                 talloc_destroy(ea_ctx);
1986                 return ERROR_DOS(ERRDOS,ERRnofiles);
1987         }
1988
1989         string_set(&conn->dirpath,dptr_path(dptr_num));
1990
1991         /* Get the wildcard mask from the dptr */
1992         if((p = dptr_wcard(dptr_num))== NULL) {
1993                 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
1994                 talloc_destroy(ea_ctx);
1995                 return ERROR_DOS(ERRDOS,ERRnofiles);
1996         }
1997
1998         pstrcpy(mask, p);
1999         pstrcpy(directory,conn->dirpath);
2000
2001         /* Get the attr mask from the dptr */
2002         dirtype = dptr_attr(dptr_num);
2003
2004         DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2005                 dptr_num, mask, dirtype, 
2006                 (long)conn->dirptr,
2007                 dptr_TellDir(conn->dirptr)));
2008
2009         /* We don't need to check for VOL here as this is returned by 
2010                 a different TRANS2 call. */
2011
2012         DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
2013         if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2014                 dont_descend = True;
2015     
2016         p = pdata;
2017         space_remaining = max_data_bytes;
2018         out_of_space = False;
2019
2020         /* 
2021          * Seek to the correct position. We no longer use the resume key but
2022          * depend on the last file name instead.
2023          */
2024
2025         if(*resume_name && !continue_bit) {
2026                 SMB_STRUCT_STAT st;
2027
2028                 long current_pos = 0;
2029                 /*
2030                  * Remember, mangle_map is called by
2031                  * get_lanman2_dir_entry(), so the resume name
2032                  * could be mangled. Ensure we check the unmangled name.
2033                  */
2034
2035                 if (mangle_is_mangled(resume_name, SNUM(conn))) {
2036                         mangle_check_cache(resume_name, sizeof(resume_name)-1, SNUM(conn));
2037                 }
2038
2039                 /*
2040                  * Fix for NT redirector problem triggered by resume key indexes
2041                  * changing between directory scans. We now return a resume key of 0
2042                  * and instead look for the filename to continue from (also given
2043                  * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2044                  * findfirst/findnext (as is usual) then the directory pointer
2045                  * should already be at the correct place.
2046                  */
2047
2048                 finished = !dptr_SearchDir(conn->dirptr, resume_name, &current_pos, &st);
2049         } /* end if resume_name && !continue_bit */
2050
2051         for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2052                 BOOL got_exact_match = False;
2053
2054                 /* this is a heuristic to avoid seeking the dirptr except when 
2055                         absolutely necessary. It allows for a filename of about 40 chars */
2056                 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2057                         out_of_space = True;
2058                         finished = False;
2059                 } else {
2060                         finished = !get_lanman2_dir_entry(conn,
2061                                                 inbuf, outbuf,
2062                                                 mask,dirtype,info_level,
2063                                                 requires_resume_key,dont_descend,
2064                                                 &p,pdata,space_remaining, &out_of_space, &got_exact_match,
2065                                                 &last_entry_off, ea_list, ea_ctx);
2066                 }
2067
2068                 if (finished && out_of_space)
2069                         finished = False;
2070
2071                 if (!finished && !out_of_space)
2072                         numentries++;
2073
2074                 /*
2075                  * As an optimisation if we know we aren't looking
2076                  * for a wildcard name (ie. the name matches the wildcard exactly)
2077                  * then we can finish on any (first) match.
2078                  * This speeds up large directory searches. JRA.
2079                  */
2080
2081                 if(got_exact_match)
2082                         finished = True;
2083
2084                 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2085         }
2086   
2087         talloc_destroy(ea_ctx);
2088
2089         /* Check if we can close the dirptr */
2090         if(close_after_request || (finished && close_if_end)) {
2091                 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2092                 dptr_close(&dptr_num); /* This frees up the saved mask */
2093         }
2094
2095         /* Set up the return parameter block */
2096         SSVAL(params,0,numentries);
2097         SSVAL(params,2,finished);
2098         SSVAL(params,4,0); /* Never an EA error */
2099         SSVAL(params,6,last_entry_off);
2100
2101         send_trans2_replies( outbuf, bufsize, params, 8, pdata, PTR_DIFF(p,pdata));
2102
2103         if ((! *directory) && dptr_path(dptr_num))
2104                 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
2105
2106         DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2107                 smb_fn_name(CVAL(inbuf,smb_com)), 
2108                 mask, directory, dirtype, numentries ) );
2109
2110         return(-1);
2111 }
2112
2113 /****************************************************************************
2114  Reply to a TRANS2_QFSINFO (query filesystem info).
2115 ****************************************************************************/
2116
2117 static int call_trans2qfsinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2118                                         char **pparams, int total_params, char **ppdata, int total_data,
2119                                         unsigned int max_data_bytes)
2120 {
2121         char *pdata = *ppdata;
2122         char *params = *pparams;
2123         uint16 info_level = SVAL(params,0);
2124         int data_len, len;
2125         SMB_STRUCT_STAT st;
2126         char *vname = volume_label(SNUM(conn));
2127         int snum = SNUM(conn);
2128         char *fstype = lp_fstype(SNUM(conn));
2129         int quota_flag = 0;
2130
2131         DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
2132
2133         if(SMB_VFS_STAT(conn,".",&st)!=0) {
2134                 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
2135                 return ERROR_DOS(ERRSRV,ERRinvdevice);
2136         }
2137
2138         *ppdata = SMB_REALLOC(*ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2139         if (*ppdata == NULL ) {
2140                 return ERROR_NT(NT_STATUS_NO_MEMORY);
2141         }
2142
2143         pdata = *ppdata;
2144         memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2145
2146         switch (info_level) {
2147                 case SMB_INFO_ALLOCATION:
2148                 {
2149                         SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2150                         data_len = 18;
2151                         if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2152                                 return(UNIXERROR(ERRHRD,ERRgeneral));
2153                         }
2154
2155                         block_size = lp_block_size(snum);
2156                         if (bsize < block_size) {
2157                                 SMB_BIG_UINT factor = block_size/bsize;
2158                                 bsize = block_size;
2159                                 dsize /= factor;
2160                                 dfree /= factor;
2161                         }
2162                         if (bsize > block_size) {
2163                                 SMB_BIG_UINT factor = bsize/block_size;
2164                                 bsize = block_size;
2165                                 dsize *= factor;
2166                                 dfree *= factor;
2167                         }
2168                         bytes_per_sector = 512;
2169                         sectors_per_unit = bsize/bytes_per_sector;
2170
2171                         DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2172 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2173                                 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2174
2175                         SIVAL(pdata,l1_idFileSystem,st.st_dev);
2176                         SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2177                         SIVAL(pdata,l1_cUnit,dsize);
2178                         SIVAL(pdata,l1_cUnitAvail,dfree);
2179                         SSVAL(pdata,l1_cbSector,bytes_per_sector);
2180                         break;
2181                 }
2182
2183                 case SMB_INFO_VOLUME:
2184                         /* Return volume name */
2185                         /* 
2186                          * Add volume serial number - hash of a combination of
2187                          * the called hostname and the service name.
2188                          */
2189                         SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2190                         /*
2191                          * Win2k3 and previous mess this up by sending a name length
2192                          * one byte short. I believe only older clients (OS/2 Win9x) use
2193                          * this call so try fixing this by adding a terminating null to
2194                          * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2195                          */
2196                         len = srvstr_push(outbuf, pdata+l2_vol_szVolLabel, vname, -1, STR_NOALIGN|STR_TERMINATE);
2197                         SCVAL(pdata,l2_vol_cch,len);
2198                         data_len = l2_vol_szVolLabel + len;
2199                         DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
2200                                 (unsigned)st.st_ctime, len, vname));
2201                         break;
2202
2203                 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2204                 case SMB_FS_ATTRIBUTE_INFORMATION:
2205
2206
2207 #if defined(HAVE_SYS_QUOTAS)
2208                         quota_flag = FILE_VOLUME_QUOTAS;
2209 #endif
2210
2211                         SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2212                                 (lp_nt_acl_support(SNUM(conn)) ? FILE_PERSISTENT_ACLS : 0)|
2213                                 quota_flag); /* FS ATTRIBUTES */
2214
2215                         SIVAL(pdata,4,255); /* Max filename component length */
2216                         /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2217                                 and will think we can't do long filenames */
2218                         len = srvstr_push(outbuf, pdata+12, fstype, -1, STR_UNICODE);
2219                         SIVAL(pdata,8,len);
2220                         data_len = 12 + len;
2221                         break;
2222
2223                 case SMB_QUERY_FS_LABEL_INFO:
2224                 case SMB_FS_LABEL_INFORMATION:
2225                         len = srvstr_push(outbuf, pdata+4, vname, -1, 0);
2226                         data_len = 4 + len;
2227                         SIVAL(pdata,0,len);
2228                         break;
2229
2230                 case SMB_QUERY_FS_VOLUME_INFO:      
2231                 case SMB_FS_VOLUME_INFORMATION:
2232
2233                         /* 
2234                          * Add volume serial number - hash of a combination of
2235                          * the called hostname and the service name.
2236                          */
2237                         SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^ 
2238                                 (str_checksum(get_local_machine_name())<<16));
2239
2240                         len = srvstr_push(outbuf, pdata+18, vname, -1, STR_UNICODE);
2241                         SIVAL(pdata,12,len);
2242                         data_len = 18+len;
2243                         DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n", 
2244                                 (int)strlen(vname),vname, lp_servicename(snum)));
2245                         break;
2246
2247                 case SMB_QUERY_FS_SIZE_INFO:
2248                 case SMB_FS_SIZE_INFORMATION:
2249                 {
2250                         SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2251                         data_len = 24;
2252                         if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2253                                 return(UNIXERROR(ERRHRD,ERRgeneral));
2254                         }
2255                         block_size = lp_block_size(snum);
2256                         if (bsize < block_size) {
2257                                 SMB_BIG_UINT factor = block_size/bsize;
2258                                 bsize = block_size;
2259                                 dsize /= factor;
2260                                 dfree /= factor;
2261                         }
2262                         if (bsize > block_size) {
2263                                 SMB_BIG_UINT factor = bsize/block_size;
2264                                 bsize = block_size;
2265                                 dsize *= factor;
2266                                 dfree *= factor;
2267                         }
2268                         bytes_per_sector = 512;
2269                         sectors_per_unit = bsize/bytes_per_sector;
2270                         DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2271 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2272                                 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2273                         SBIG_UINT(pdata,0,dsize);
2274                         SBIG_UINT(pdata,8,dfree);
2275                         SIVAL(pdata,16,sectors_per_unit);
2276                         SIVAL(pdata,20,bytes_per_sector);
2277                         break;
2278                 }
2279
2280                 case SMB_FS_FULL_SIZE_INFORMATION:
2281                 {
2282                         SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2283                         data_len = 32;
2284                         if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2285                                 return(UNIXERROR(ERRHRD,ERRgeneral));
2286                         }
2287                         block_size = lp_block_size(snum);
2288                         if (bsize < block_size) {
2289                                 SMB_BIG_UINT factor = block_size/bsize;
2290                                 bsize = block_size;
2291                                 dsize /= factor;
2292                                 dfree /= factor;
2293                         }
2294                         if (bsize > block_size) {
2295                                 SMB_BIG_UINT factor = bsize/block_size;
2296                                 bsize = block_size;
2297                                 dsize *= factor;
2298                                 dfree *= factor;
2299                         }
2300                         bytes_per_sector = 512;
2301                         sectors_per_unit = bsize/bytes_per_sector;
2302                         DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2303 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2304                                 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2305                         SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2306                         SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2307                         SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2308                         SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2309                         SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2310                         break;
2311                 }
2312
2313                 case SMB_QUERY_FS_DEVICE_INFO:
2314                 case SMB_FS_DEVICE_INFORMATION:
2315                         data_len = 8;
2316                         SIVAL(pdata,0,0); /* dev type */
2317                         SIVAL(pdata,4,0); /* characteristics */
2318                         break;
2319
2320 #ifdef HAVE_SYS_QUOTAS
2321                 case SMB_FS_QUOTA_INFORMATION:
2322                 /* 
2323                  * what we have to send --metze:
2324                  *
2325                  * Unknown1:            24 NULL bytes
2326                  * Soft Quota Treshold: 8 bytes seems like SMB_BIG_UINT or so
2327                  * Hard Quota Limit:    8 bytes seems like SMB_BIG_UINT or so
2328                  * Quota Flags:         2 byte :
2329                  * Unknown3:            6 NULL bytes
2330                  *
2331                  * 48 bytes total
2332                  * 
2333                  * details for Quota Flags:
2334                  * 
2335                  * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2336                  * 0x0010 Log Warn:  log if the user exceeds his Soft Quota
2337                  * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2338                  * 0x0001 Enable Quotas: enable quota for this fs
2339                  *
2340                  */
2341                 {
2342                         /* we need to fake up a fsp here,
2343                          * because its not send in this call
2344                          */
2345                         files_struct fsp;
2346                         SMB_NTQUOTA_STRUCT quotas;
2347                         
2348                         ZERO_STRUCT(fsp);
2349                         ZERO_STRUCT(quotas);
2350                         
2351                         fsp.conn = conn;
2352                         fsp.fnum = -1;
2353                         
2354                         /* access check */
2355                         if (current_user.ut.uid != 0) {
2356                                 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2357                                         lp_servicename(SNUM(conn)),conn->user));
2358                                 return ERROR_DOS(ERRDOS,ERRnoaccess);
2359                         }
2360                         
2361                         if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
2362                                 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2363                                 return ERROR_DOS(ERRSRV,ERRerror);
2364                         }
2365
2366                         data_len = 48;
2367
2368                         DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn))));          
2369                 
2370                         /* Unknown1 24 NULL bytes*/
2371                         SBIG_UINT(pdata,0,(SMB_BIG_UINT)0);
2372                         SBIG_UINT(pdata,8,(SMB_BIG_UINT)0);
2373                         SBIG_UINT(pdata,16,(SMB_BIG_UINT)0);
2374                 
2375                         /* Default Soft Quota 8 bytes */
2376                         SBIG_UINT(pdata,24,quotas.softlim);
2377
2378                         /* Default Hard Quota 8 bytes */
2379                         SBIG_UINT(pdata,32,quotas.hardlim);
2380         
2381                         /* Quota flag 2 bytes */
2382                         SSVAL(pdata,40,quotas.qflags);
2383                 
2384                         /* Unknown3 6 NULL bytes */
2385                         SSVAL(pdata,42,0);
2386                         SIVAL(pdata,44,0);
2387                         
2388                         break;
2389                 }
2390 #endif /* HAVE_SYS_QUOTAS */
2391                 case SMB_FS_OBJECTID_INFORMATION:
2392                         data_len = 64;
2393                         break;
2394
2395                 /*
2396                  * Query the version and capabilities of the CIFS UNIX extensions
2397                  * in use.
2398                  */
2399
2400                 case SMB_QUERY_CIFS_UNIX_INFO:
2401                         if (!lp_unix_extensions())
2402                                 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2403                         data_len = 12;
2404                         SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2405                         SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2406                         SBIG_UINT(pdata,4,((SMB_BIG_UINT)(CIFS_UNIX_POSIX_ACLS_CAP|
2407                                         CIFS_UNIX_POSIX_PATHNAMES_CAP))); /* We have POSIX ACLs and pathname capability. */
2408                         break;
2409
2410                 case SMB_QUERY_POSIX_FS_INFO:
2411                 {
2412                         int rc;
2413                         vfs_statvfs_struct svfs;
2414
2415                         if (!lp_unix_extensions())
2416                                 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2417                         
2418                         rc = SMB_VFS_STATVFS(conn, ".", &svfs);
2419
2420                         if (!rc) {
2421                                 data_len = 56;
2422                                 SIVAL(pdata,0,svfs.OptimalTransferSize);
2423                                 SIVAL(pdata,4,svfs.BlockSize);
2424                                 SBIG_UINT(pdata,8,svfs.TotalBlocks);
2425                                 SBIG_UINT(pdata,16,svfs.BlocksAvail);
2426                                 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
2427                                 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
2428                                 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
2429                                 SBIG_UINT(pdata,48,svfs.FsIdentifier);
2430                                 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
2431 #ifdef EOPNOTSUPP
2432                         } else if (rc == EOPNOTSUPP) {
2433                                 return ERROR_DOS(ERRDOS, ERRunknownlevel);
2434 #endif /* EOPNOTSUPP */
2435                         } else {
2436                                 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2437                                 return ERROR_DOS(ERRSRV,ERRerror);
2438                         }
2439                         break;
2440                 }
2441
2442                 case SMB_MAC_QUERY_FS_INFO:
2443                         /*
2444                          * Thursby MAC extension... ONLY on NTFS filesystems
2445                          * once we do streams then we don't need this
2446                          */
2447                         if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
2448                                 data_len = 88;
2449                                 SIVAL(pdata,84,0x100); /* Don't support mac... */
2450                                 break;
2451                         }
2452                         /* drop through */
2453                 default:
2454                         return ERROR_DOS(ERRDOS,ERRunknownlevel);
2455         }
2456
2457
2458         send_trans2_replies( outbuf, bufsize, params, 0, pdata, data_len);
2459
2460         DEBUG( 4, ( "%s info_level = %d\n", smb_fn_name(CVAL(inbuf,smb_com)), info_level) );
2461
2462         return -1;
2463 }
2464
2465 /****************************************************************************
2466  Reply to a TRANS2_SETFSINFO (set filesystem info).
2467 ****************************************************************************/
2468
2469 static int call_trans2setfsinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2470                                         char **pparams, int total_params, char **ppdata, int total_data,
2471                                         unsigned int max_data_bytes)
2472 {
2473         char *pdata = *ppdata;
2474         char *params = *pparams;
2475         uint16 info_level;
2476         int outsize;
2477
2478         DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
2479
2480         /*  */
2481         if (total_params < 4) {
2482                 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
2483                         total_params));
2484                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2485         }
2486
2487         info_level = SVAL(params,2);
2488
2489         switch(info_level) {
2490                 case SMB_SET_CIFS_UNIX_INFO:
2491                         {
2492                                 uint16 client_unix_major;
2493                                 uint16 client_unix_minor;
2494                                 uint32 client_unix_cap_low;
2495                                 uint32 client_unix_cap_high;
2496
2497                                 if (!lp_unix_extensions()) {
2498                                         return ERROR_DOS(ERRDOS,ERRunknownlevel);
2499                                 }
2500
2501                                 /* There should be 12 bytes of capabilities set. */
2502                                 if (total_data < 8) {
2503                                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2504                                 }
2505                                 client_unix_major = SVAL(pdata,0);
2506                                 client_unix_minor = SVAL(pdata,2);
2507                                 client_unix_cap_low = IVAL(pdata,4);
2508                                 client_unix_cap_high = IVAL(pdata,8);
2509                                 /* Just print these values for now. */
2510                                 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
2511 cap_low = 0x%x, cap_high = 0x%x\n",
2512                                         (unsigned int)client_unix_major,
2513                                         (unsigned int)client_unix_minor,
2514                                         (unsigned int)client_unix_cap_low,
2515                                         (unsigned int)client_unix_cap_high ));
2516
2517                                 /* Here is where we must switch to posix pathname processing... */
2518                                 lp_set_posix_pathnames();
2519                                 mangle_change_to_posix();
2520                                 break;
2521                         }
2522                 case SMB_FS_QUOTA_INFORMATION:
2523                         {
2524                                 files_struct *fsp = NULL;
2525                                 SMB_NTQUOTA_STRUCT quotas;
2526         
2527                                 ZERO_STRUCT(quotas);
2528
2529                                 /* access check */
2530                                 if ((current_user.ut.uid != 0)||!CAN_WRITE(conn)) {
2531                                         DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2532                                                 lp_servicename(SNUM(conn)),conn->user));
2533                                         return ERROR_DOS(ERRSRV,ERRaccess);
2534                                 }
2535
2536                                 /* note: normaly there're 48 bytes,
2537                                  * but we didn't use the last 6 bytes for now 
2538                                  * --metze 
2539                                  */
2540                                 fsp = file_fsp(params,0);
2541                                 if (!CHECK_NTQUOTA_HANDLE_OK(fsp,conn)) {
2542                                         DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
2543                                         return ERROR_NT(NT_STATUS_INVALID_HANDLE);
2544                                 }
2545
2546                                 if (total_data < 42) {
2547                                         DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
2548                                                 total_data));
2549                                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2550                                 }
2551                         
2552                                 /* unknown_1 24 NULL bytes in pdata*/
2553                 
2554                                 /* the soft quotas 8 bytes (SMB_BIG_UINT)*/
2555                                 quotas.softlim = (SMB_BIG_UINT)IVAL(pdata,24);
2556 #ifdef LARGE_SMB_OFF_T
2557                                 quotas.softlim |= (((SMB_BIG_UINT)IVAL(pdata,28)) << 32);
2558 #else /* LARGE_SMB_OFF_T */
2559                                 if ((IVAL(pdata,28) != 0)&&
2560                                         ((quotas.softlim != 0xFFFFFFFF)||
2561                                         (IVAL(pdata,28)!=0xFFFFFFFF))) {
2562                                         /* more than 32 bits? */
2563                                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2564                                 }
2565 #endif /* LARGE_SMB_OFF_T */
2566                 
2567                                 /* the hard quotas 8 bytes (SMB_BIG_UINT)*/
2568                                 quotas.hardlim = (SMB_BIG_UINT)IVAL(pdata,32);
2569 #ifdef LARGE_SMB_OFF_T
2570                                 quotas.hardlim |= (((SMB_BIG_UINT)IVAL(pdata,36)) << 32);
2571 #else /* LARGE_SMB_OFF_T */
2572                                 if ((IVAL(pdata,36) != 0)&&
2573                                         ((quotas.hardlim != 0xFFFFFFFF)||
2574                                         (IVAL(pdata,36)!=0xFFFFFFFF))) {
2575                                         /* more than 32 bits? */
2576                                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2577                                 }
2578 #endif /* LARGE_SMB_OFF_T */
2579                 
2580                                 /* quota_flags 2 bytes **/
2581                                 quotas.qflags = SVAL(pdata,40);
2582                 
2583                                 /* unknown_2 6 NULL bytes follow*/
2584                 
2585                                 /* now set the quotas */
2586                                 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
2587                                         DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2588                                         return ERROR_DOS(ERRSRV,ERRerror);
2589                                 }
2590                         
2591                                 break;
2592                         }
2593                 default:
2594                         DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
2595                                 info_level));
2596                         return ERROR_DOS(ERRDOS,ERRunknownlevel);
2597                         break;
2598         }
2599
2600         /* 
2601          * sending this reply works fine, 
2602          * but I'm not sure it's the same 
2603          * like windows do...
2604          * --metze
2605          */ 
2606         outsize = set_message(outbuf,10,0,True);
2607
2608         return outsize;
2609 }
2610
2611 /****************************************************************************
2612  Utility function to set bad path error.
2613 ****************************************************************************/
2614
2615 int set_bad_path_error(int err, BOOL bad_path, char *outbuf, int def_class, uint32 def_code)
2616 {
2617         DEBUG(10,("set_bad_path_error: err = %d bad_path = %d\n",
2618                         err, (int)bad_path ));
2619
2620         if(err == ENOENT) {
2621                 if (bad_path) {
2622                         return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
2623                 } else {
2624                         return ERROR_NT(NT_STATUS_OBJECT_NAME_NOT_FOUND);
2625                 }
2626         }
2627         return UNIXERROR(def_class,def_code);
2628 }
2629
2630 #if defined(HAVE_POSIX_ACLS)
2631 /****************************************************************************
2632  Utility function to count the number of entries in a POSIX acl.
2633 ****************************************************************************/
2634
2635 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
2636 {
2637         unsigned int ace_count = 0;
2638         int entry_id = SMB_ACL_FIRST_ENTRY;
2639         SMB_ACL_ENTRY_T entry;
2640
2641         while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
2642                 /* get_next... */
2643                 if (entry_id == SMB_ACL_FIRST_ENTRY) {
2644                         entry_id = SMB_ACL_NEXT_ENTRY;
2645                 }
2646                 ace_count++;
2647         }
2648         return ace_count;
2649 }
2650
2651 /****************************************************************************
2652  Utility function to marshall a POSIX acl into wire format.
2653 ****************************************************************************/
2654
2655 static BOOL marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
2656 {
2657         int entry_id = SMB_ACL_FIRST_ENTRY;
2658         SMB_ACL_ENTRY_T entry;
2659
2660         while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
2661                 SMB_ACL_TAG_T tagtype;
2662                 SMB_ACL_PERMSET_T permset;
2663                 unsigned char perms = 0;
2664                 unsigned int own_grp;
2665
2666                 /* get_next... */
2667                 if (entry_id == SMB_ACL_FIRST_ENTRY) {
2668                         entry_id = SMB_ACL_NEXT_ENTRY;
2669                 }
2670
2671                 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
2672                         DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
2673                         return False;
2674                 }
2675
2676                 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
2677                         DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
2678                         return False;
2679                 }
2680
2681                 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
2682                 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
2683                 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
2684
2685                 SCVAL(pdata,1,perms);
2686
2687                 switch (tagtype) {
2688                         case SMB_ACL_USER_OBJ:
2689                                 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
2690                                 own_grp = (unsigned int)pst->st_uid;
2691                                 SIVAL(pdata,2,own_grp);
2692                                 SIVAL(pdata,6,0);
2693                                 break;
2694                         case SMB_ACL_USER:
2695                                 {
2696                                         uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
2697                                         if (!puid) {
2698                                                 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
2699                                         }
2700                                         own_grp = (unsigned int)*puid;
2701                                         SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
2702                                         SCVAL(pdata,0,SMB_POSIX_ACL_USER);
2703                                         SIVAL(pdata,2,own_grp);
2704                                         SIVAL(pdata,6,0);
2705                                         break;
2706                                 }
2707                         case SMB_ACL_GROUP_OBJ:
2708                                 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
2709                                 own_grp = (unsigned int)pst->st_gid;
2710                                 SIVAL(pdata,2,own_grp);
2711                                 SIVAL(pdata,6,0);
2712                                 break;
2713                         case SMB_ACL_GROUP:
2714                                 {
2715                                         gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
2716                                         if (!pgid) {
2717                                                 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
2718                                         }
2719                                         own_grp = (unsigned int)*pgid;
2720                                         SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
2721                                         SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
2722                                         SIVAL(pdata,2,own_grp);
2723                                         SIVAL(pdata,6,0);
2724                                         break;
2725                                 }
2726                         case SMB_ACL_MASK:
2727                                 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
2728                                 SIVAL(pdata,2,0xFFFFFFFF);
2729                                 SIVAL(pdata,6,0xFFFFFFFF);
2730                                 break;
2731                         case SMB_ACL_OTHER:
2732                                 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
2733                                 SIVAL(pdata,2,0xFFFFFFFF);
2734                                 SIVAL(pdata,6,0xFFFFFFFF);
2735                                 break;
2736                         default:
2737                                 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
2738                                 return False;
2739                 }
2740                 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
2741         }
2742
2743         return True;
2744 }
2745 #endif
2746
2747 /****************************************************************************
2748  Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
2749  file name or file id).
2750 ****************************************************************************/
2751
2752 static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2753                                         unsigned int tran_call,
2754                                         char **pparams, int total_params, char **ppdata, int total_data,
2755                                         unsigned int max_data_bytes)
2756 {
2757         char *params = *pparams;
2758         char *pdata = *ppdata;
2759         uint16 info_level;
2760         int mode=0;
2761         int nlink;
2762         SMB_OFF_T file_size=0;
2763         SMB_BIG_UINT allocation_size=0;
2764         unsigned int data_size = 0;
2765         unsigned int param_size = 2;
2766         SMB_STRUCT_STAT sbuf;
2767         pstring fname, dos_fname;
2768         char *fullpathname;
2769         char *base_name;
2770         char *p;
2771         SMB_OFF_T pos = 0;
2772         BOOL bad_path = False;
2773         BOOL delete_pending = False;
2774         int len;
2775         time_t c_time;
2776         files_struct *fsp = NULL;
2777         TALLOC_CTX *ea_ctx = NULL;
2778         struct ea_list *ea_list = NULL;
2779         uint32 access_mask = 0x12019F; /* Default - GENERIC_EXECUTE mapping from Windows */
2780
2781         if (!params)
2782                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2783
2784         ZERO_STRUCT(sbuf);
2785
2786         if (tran_call == TRANSACT2_QFILEINFO) {
2787                 if (total_params < 4) {
2788                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2789                 }
2790
2791                 fsp = file_fsp(params,0);
2792                 info_level = SVAL(params,2);
2793
2794                 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
2795
2796                 if(fsp && (fsp->fake_file_handle)) {
2797                         /*
2798                          * This is actually for the QUOTA_FAKE_FILE --metze
2799                          */
2800                                                 
2801                         pstrcpy(fname, fsp->fsp_name);
2802                         /* We know this name is ok, it's already passed the checks. */
2803                         
2804                 } else if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
2805                         /*
2806                          * This is actually a QFILEINFO on a directory
2807                          * handle (returned from an NT SMB). NT5.0 seems
2808                          * to do this call. JRA.
2809                          */
2810                         /* We know this name is ok, it's already passed the checks. */
2811                         pstrcpy(fname, fsp->fsp_name);
2812                   
2813                         if (INFO_LEVEL_IS_UNIX(info_level)) {
2814                                 /* Always do lstat for UNIX calls. */
2815                                 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
2816                                         DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
2817                                         return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2818                                 }
2819                         } else if (SMB_VFS_STAT(conn,fname,&sbuf)) {
2820                                 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
2821                                 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2822                         }
2823
2824                         delete_pending = get_delete_on_close_flag(sbuf.st_dev, sbuf.st_ino);
2825                 } else {
2826                         /*
2827                          * Original code - this is an open file.
2828                          */
2829                         CHECK_FSP(fsp,conn);
2830
2831                         pstrcpy(fname, fsp->fsp_name);
2832                         if (SMB_VFS_FSTAT(fsp,fsp->fh->fd,&sbuf) != 0) {
2833                                 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
2834                                 return(UNIXERROR(ERRDOS,ERRbadfid));
2835                         }
2836                         pos = fsp->fh->position_information;
2837                         delete_pending = get_delete_on_close_flag(sbuf.st_dev, sbuf.st_ino);
2838                         access_mask = fsp->access_mask;
2839                 }
2840         } else {
2841                 NTSTATUS status = NT_STATUS_OK;
2842
2843                 /* qpathinfo */
2844                 if (total_params < 6) {
2845                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2846                 }
2847
2848                 info_level = SVAL(params,0);
2849
2850                 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
2851
2852                 srvstr_get_path(inbuf, fname, &params[6], sizeof(fname), -1, STR_TERMINATE, &status);
2853                 if (!NT_STATUS_IS_OK(status)) {
2854                         return ERROR_NT(status);
2855                 }
2856
2857                 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
2858
2859                 unix_convert(fname,conn,0,&bad_path,&sbuf);
2860                 if (bad_path) {
2861                         return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
2862                 }
2863                 if (!check_name(fname,conn)) {
2864                         DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
2865                         return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2866                 }
2867
2868                 if (INFO_LEVEL_IS_UNIX(info_level)) {
2869                         /* Always do lstat for UNIX calls. */
2870                         if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
2871                                 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
2872                                 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2873                         }
2874                 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) {
2875                         DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
2876                         return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2877                 }
2878
2879                 delete_pending = get_delete_on_close_flag(sbuf.st_dev, sbuf.st_ino);
2880                 if (delete_pending) {
2881                         return ERROR_NT(NT_STATUS_DELETE_PENDING);
2882                 }
2883         }
2884
2885         nlink = sbuf.st_nlink;
2886
2887         if ((nlink > 0) && S_ISDIR(sbuf.st_mode)) {
2888                 /* NTFS does not seem to count ".." */
2889                 nlink -= 1;
2890         }
2891
2892         if ((nlink > 0) && delete_pending) {
2893                 nlink -= 1;
2894         }
2895
2896         if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions())
2897                 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2898
2899         DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
2900                 fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
2901
2902         p = strrchr_m(fname,'/'); 
2903         if (!p)
2904                 base_name = fname;
2905         else
2906                 base_name = p+1;
2907
2908         mode = dos_mode(conn,fname,&sbuf);
2909         if (!mode)
2910                 mode = FILE_ATTRIBUTE_NORMAL;
2911
2912         fullpathname = fname;
2913         if (!(mode & aDIR))
2914                 file_size = get_file_size(sbuf);
2915
2916         /* Pull any EA list from the data portion. */
2917         if (info_level == SMB_INFO_QUERY_EAS_FROM_LIST) {
2918                 uint32 ea_size;
2919
2920                 if (total_data < 4) {
2921                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2922                 }
2923                 ea_size = IVAL(pdata,0);
2924
2925                 if (total_data > 0 && ea_size != total_data) {
2926                         DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
2927 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2928                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2929                 }
2930
2931                 if (!lp_ea_support(SNUM(conn))) {
2932                         return ERROR_DOS(ERRDOS,ERReasnotsupported);
2933                 }
2934
2935                 if ((ea_ctx = talloc_init("ea_list")) == NULL) {
2936                         return ERROR_NT(NT_STATUS_NO_MEMORY);
2937                 }
2938
2939                 /* Pull out the list of names. */
2940                 ea_list = read_ea_name_list(ea_ctx, pdata + 4, ea_size - 4);
2941                 if (!ea_list) {
2942                         talloc_destroy(ea_ctx);
2943                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2944                 }
2945         }
2946
2947         *pparams = SMB_REALLOC(*pparams,2);
2948         if (*pparams == NULL) {
2949                 talloc_destroy(ea_ctx);
2950                 return ERROR_NT(NT_STATUS_NO_MEMORY);
2951         }
2952         params = *pparams;
2953         SSVAL(params,0,0);
2954         data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
2955         *ppdata = SMB_REALLOC(*ppdata, data_size); 
2956         if (*ppdata == NULL ) {
2957                 talloc_destroy(ea_ctx);
2958                 return ERROR_NT(NT_STATUS_NO_MEMORY);
2959         }
2960         pdata = *ppdata;
2961
2962         c_time = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
2963
2964         allocation_size = get_allocation_size(conn,fsp,&sbuf);
2965
2966         if (fsp) {
2967                 if (fsp->pending_modtime) {
2968                         /* the pending modtime overrides the current modtime */
2969                         sbuf.st_mtime = fsp->pending_modtime;
2970                 }
2971         } else {
2972                 /* Do we have this path open ? */
2973                 files_struct *fsp1 = file_find_di_first(sbuf.st_dev, sbuf.st_ino);
2974                 if (fsp1 && fsp1->pending_modtime) {
2975                         /* the pending modtime overrides the current modtime */
2976                         sbuf.st_mtime = fsp1->pending_modtime;
2977                 }
2978                 if (fsp1 && fsp1->initial_allocation_size) {
2979                         allocation_size = get_allocation_size(conn, fsp1, &sbuf);
2980                 }
2981         }
2982
2983         if (lp_dos_filetime_resolution(SNUM(conn))) {
2984                 c_time &= ~1;
2985                 sbuf.st_atime &= ~1;
2986                 sbuf.st_ctime &= ~1;
2987                 sbuf.st_mtime &= ~1;
2988         }
2989
2990         /* NT expects the name to be in an exact form of the *full*
2991            filename. See the trans2 torture test */
2992         if (strequal(base_name,".")) {
2993                 pstrcpy(dos_fname, "\\");
2994         } else {
2995                 pstr_sprintf(dos_fname, "\\%s", fname);
2996                 string_replace(dos_fname, '/', '\\');
2997         }
2998
2999         switch (info_level) {
3000                 case SMB_INFO_STANDARD:
3001                         DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
3002                         data_size = 22;
3003                         srv_put_dos_date2(pdata,l1_fdateCreation,c_time);
3004                         srv_put_dos_date2(pdata,l1_fdateLastAccess,sbuf.st_atime);
3005                         srv_put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime); /* write time */
3006                         SIVAL(pdata,l1_cbFile,(uint32)file_size);
3007                         SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
3008                         SSVAL(pdata,l1_attrFile,mode);
3009                         break;
3010
3011                 case SMB_INFO_QUERY_EA_SIZE:
3012                 {
3013                         unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3014                         DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
3015                         data_size = 26;
3016                         srv_put_dos_date2(pdata,0,c_time);
3017                         srv_put_dos_date2(pdata,4,sbuf.st_atime);
3018                         srv_put_dos_date2(pdata,8,sbuf.st_mtime); /* write time */
3019                         SIVAL(pdata,12,(uint32)file_size);
3020                         SIVAL(pdata,16,(uint32)allocation_size);
3021                         SSVAL(pdata,20,mode);
3022                         SIVAL(pdata,22,ea_size);
3023                         break;
3024                 }
3025
3026                 case SMB_INFO_IS_NAME_VALID:
3027                         DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
3028                         if (tran_call == TRANSACT2_QFILEINFO) {
3029                                 /* os/2 needs this ? really ?*/      
3030                                 return ERROR_DOS(ERRDOS,ERRbadfunc); 
3031                         }
3032                         data_size = 0;
3033                         param_size = 0;
3034                         break;
3035                         
3036                 case SMB_INFO_QUERY_EAS_FROM_LIST:
3037                 {
3038                         size_t total_ea_len = 0;
3039                         struct ea_list *ea_file_list = NULL;
3040
3041                         DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
3042
3043                         ea_file_list = get_ea_list_from_file(ea_ctx, conn, fsp, fname, &total_ea_len);
3044                         ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
3045
3046                         if (!ea_list || (total_ea_len > data_size)) {
3047                                 talloc_destroy(ea_ctx);
3048                                 data_size = 4;
3049                                 SIVAL(pdata,0,4);   /* EA List Length must be set to 4 if no EA's. */
3050                                 break;
3051                         }
3052
3053                         data_size = fill_ea_buffer(ea_ctx, pdata, data_size, conn, ea_list);
3054                         talloc_destroy(ea_ctx);
3055                         break;
3056                 }
3057
3058                 case SMB_INFO_QUERY_ALL_EAS:
3059                 {
3060                         /* We have data_size bytes to put EA's into. */
3061                         size_t total_ea_len = 0;
3062
3063                         DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
3064
3065                         ea_ctx = talloc_init("ea_ctx");
3066                         if (!ea_ctx) {
3067                                 return ERROR_NT(NT_STATUS_NO_MEMORY);
3068                         }
3069
3070                         ea_list = get_ea_list_from_file(ea_ctx, conn, fsp, fname, &total_ea_len);
3071                         if (!ea_list || (total_ea_len > data_size)) {
3072                                 talloc_destroy(ea_ctx);
3073                                 data_size = 4;
3074                                 SIVAL(pdata,0,4);   /* EA List Length must be set to 4 if no EA's. */
3075                                 break;
3076                         }
3077
3078                         data_size = fill_ea_buffer(ea_ctx, pdata, data_size, conn, ea_list);
3079                         talloc_destroy(ea_ctx);
3080                         break;
3081                 }
3082
3083                 case SMB_FILE_BASIC_INFORMATION:
3084                 case SMB_QUERY_FILE_BASIC_INFO:
3085
3086                         if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
3087                                 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
3088                                 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
3089                         } else {
3090                                 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
3091                                 data_size = 40;
3092                                 SIVAL(pdata,36,0);
3093                         }
3094                         put_long_date(pdata,c_time);
3095                         put_long_date(pdata+8,sbuf.st_atime);
3096                         put_long_date(pdata+16,sbuf.st_mtime); /* write time */
3097                         put_long_date(pdata+24,sbuf.st_mtime); /* change time */
3098                         SIVAL(pdata,32,mode);
3099
3100                         DEBUG(5,("SMB_QFBI - "));
3101                         {
3102                                 time_t create_time = c_time;
3103                                 DEBUG(5,("create: %s ", ctime(&create_time)));
3104                         }
3105                         DEBUG(5,("access: %s ", ctime(&sbuf.st_atime)));
3106                         DEBUG(5,("write: %s ", ctime(&sbuf.st_mtime)));
3107                         DEBUG(5,("change: %s ", ctime(&sbuf.st_mtime)));
3108                         DEBUG(5,("mode: %x\n", mode));
3109                         break;
3110
3111                 case SMB_FILE_STANDARD_INFORMATION:
3112                 case SMB_QUERY_FILE_STANDARD_INFO:
3113
3114                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
3115                         data_size = 24;
3116                         SOFF_T(pdata,0,allocation_size);
3117                         SOFF_T(pdata,8,file_size);
3118                         SIVAL(pdata,16,nlink);
3119                         SCVAL(pdata,20,delete_pending?1:0);
3120                         SCVAL(pdata,21,(mode&aDIR)?1:0);
3121                         SSVAL(pdata,22,0); /* Padding. */
3122                         break;
3123
3124                 case SMB_FILE_EA_INFORMATION:
3125                 case SMB_QUERY_FILE_EA_INFO:
3126                 {
3127                         unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3128                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
3129                         data_size = 4;
3130                         SIVAL(pdata,0,ea_size);
3131                         break;
3132                 }
3133
3134                 /* Get the 8.3 name - used if NT SMB was negotiated. */
3135                 case SMB_QUERY_FILE_ALT_NAME_INFO:
3136                 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
3137                 {
3138                         pstring short_name;
3139
3140                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
3141                         pstrcpy(short_name,base_name);
3142                         /* Mangle if not already 8.3 */
3143                         if(!mangle_is_8_3(short_name, True, SNUM(conn))) {
3144                                 mangle_map(short_name,True,True,SNUM(conn));
3145                         }
3146                         len = srvstr_push(outbuf, pdata+4, short_name, -1, STR_UNICODE);
3147                         data_size = 4 + len;
3148                         SIVAL(pdata,0,len);
3149                         break;
3150                 }
3151
3152                 case SMB_QUERY_FILE_NAME_INFO:
3153                         /*
3154                           this must be *exactly* right for ACLs on mapped drives to work
3155                          */
3156                         len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
3157                         DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
3158                         data_size = 4 + len;
3159                         SIVAL(pdata,0,len);
3160                         break;
3161
3162                 case SMB_FILE_ALLOCATION_INFORMATION:
3163                 case SMB_QUERY_FILE_ALLOCATION_INFO:
3164                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
3165                         data_size = 8;
3166                         SOFF_T(pdata,0,allocation_size);
3167                         break;
3168
3169                 case SMB_FILE_END_OF_FILE_INFORMATION:
3170                 case SMB_QUERY_FILE_END_OF_FILEINFO:
3171                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
3172                         data_size = 8;
3173                         SOFF_T(pdata,0,file_size);
3174                         break;
3175
3176                 case SMB_QUERY_FILE_ALL_INFO:
3177                 case SMB_FILE_ALL_INFORMATION:
3178                 {
3179                         unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3180                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
3181                         put_long_date(pdata,c_time);
3182                         put_long_date(pdata+8,sbuf.st_atime);
3183                         put_long_date(pdata+16,sbuf.st_mtime); /* write time */
3184                         put_long_date(pdata+24,sbuf.st_mtime); /* change time */
3185                         SIVAL(pdata,32,mode);
3186                         SIVAL(pdata,36,0); /* padding. */
3187                         pdata += 40;
3188                         SOFF_T(pdata,0,allocation_size);
3189                         SOFF_T(pdata,8,file_size);
3190                         SIVAL(pdata,16,nlink);
3191                         SCVAL(pdata,20,delete_pending);
3192                         SCVAL(pdata,21,(mode&aDIR)?1:0);
3193                         SSVAL(pdata,22,0);
3194                         pdata += 24;
3195                         SIVAL(pdata,0,ea_size);
3196                         pdata += 4; /* EA info */
3197                         len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
3198                         SIVAL(pdata,0,len);
3199                         pdata += 4 + len;
3200                         data_size = PTR_DIFF(pdata,(*ppdata));
3201                         break;
3202                 }
3203                 case SMB_FILE_INTERNAL_INFORMATION:
3204                         /* This should be an index number - looks like
3205                            dev/ino to me :-) 
3206
3207                            I think this causes us to fail the IFSKIT
3208                            BasicFileInformationTest. -tpot */
3209
3210                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
3211                         SIVAL(pdata,0,sbuf.st_ino); /* FileIndexLow */
3212                         SIVAL(pdata,4,sbuf.st_dev); /* FileIndexHigh */
3213                         data_size = 8;
3214                         break;
3215
3216                 case SMB_FILE_ACCESS_INFORMATION:
3217                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
3218                         SIVAL(pdata,0,access_mask);
3219                         data_size = 4;
3220                         break;
3221
3222                 case SMB_FILE_NAME_INFORMATION:
3223                         /* Pathname with leading '\'. */
3224                         {
3225                                 size_t byte_len;
3226                                 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
3227                                 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
3228                                 SIVAL(pdata,0,byte_len);
3229                                 data_size = 4 + byte_len;
3230                                 break;
3231                         }
3232
3233                 case SMB_FILE_DISPOSITION_INFORMATION:
3234                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
3235                         data_size = 1;
3236                         SCVAL(pdata,0,delete_pending);
3237                         break;
3238
3239                 case SMB_FILE_POSITION_INFORMATION:
3240                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
3241                         data_size = 8;
3242                         SOFF_T(pdata,0,pos);
3243                         break;
3244