r15018: Merge Volker's ipc/trans2/nttrans changes over
[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 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_NT(NT_STATUS_INVALID_LEVEL);
1649                         }
1650                         break;
1651                 default:
1652                         return ERROR_NT(NT_STATUS_INVALID_LEVEL);
1653         }
1654
1655         srvstr_get_path_wcard(inbuf, directory, params+12, sizeof(directory), -1, STR_TERMINATE, &ntstatus, &mask_contains_wcard);
1656         if (!NT_STATUS_IS_OK(ntstatus)) {
1657                 return ERROR_NT(ntstatus);
1658         }
1659
1660         RESOLVE_DFSPATH_WCARD(directory, conn, inbuf, outbuf);
1661
1662         unix_convert(directory,conn,0,&bad_path,&sbuf);
1663         if (bad_path) {
1664                 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
1665         }
1666         if(!check_name(directory,conn)) {
1667                 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
1668         }
1669
1670         p = strrchr_m(directory,'/');
1671         if(p == NULL) {
1672                 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
1673                 if((directory[0] == '.') && (directory[1] == '\0')) {
1674                         pstrcpy(mask,"*");
1675                         mask_contains_wcard = True;
1676                 } else {
1677                         pstrcpy(mask,directory);
1678                 }
1679                 pstrcpy(directory,"./");
1680         } else {
1681                 pstrcpy(mask,p+1);
1682                 *p = 0;
1683         }
1684
1685         DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
1686
1687         if (info_level == SMB_FIND_EA_LIST) {
1688                 uint32 ea_size;
1689
1690                 if (total_data < 4) {
1691                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1692                 }
1693
1694                 ea_size = IVAL(pdata,0);
1695                 if (ea_size != total_data) {
1696                         DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
1697 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
1698                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1699                 }
1700
1701                 if (!lp_ea_support(SNUM(conn))) {
1702                         return ERROR_DOS(ERRDOS,ERReasnotsupported);
1703                 }
1704                                                                                                                                                         
1705                 if ((ea_ctx = talloc_init("findnext_ea_list")) == NULL) {
1706                         return ERROR_NT(NT_STATUS_NO_MEMORY);
1707                 }
1708                                                                                                                                                         
1709                 /* Pull out the list of names. */
1710                 ea_list = read_ea_name_list(ea_ctx, pdata + 4, ea_size - 4);
1711                 if (!ea_list) {
1712                         talloc_destroy(ea_ctx);
1713                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1714                 }
1715         }
1716
1717         *ppdata = SMB_REALLOC(*ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1718         if(*ppdata == NULL ) {
1719                 talloc_destroy(ea_ctx);
1720                 return ERROR_NT(NT_STATUS_NO_MEMORY);
1721         }
1722         pdata = *ppdata;
1723
1724         /* Realloc the params space */
1725         *pparams = SMB_REALLOC(*pparams, 10);
1726         if (*pparams == NULL) {
1727                 talloc_destroy(ea_ctx);
1728                 return ERROR_NT(NT_STATUS_NO_MEMORY);
1729         }
1730         params = *pparams;
1731
1732         /* Save the wildcard match and attribs we are using on this directory - 
1733                 needed as lanman2 assumes these are being saved between calls */
1734
1735         dptr_num = dptr_create(conn,directory, False, True ,SVAL(inbuf,smb_pid), mask, mask_contains_wcard, dirtype);
1736         if (dptr_num < 0) {
1737                 talloc_destroy(ea_ctx);
1738                 return(UNIXERROR(ERRDOS,ERRbadfile));
1739         }
1740
1741         DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n",dptr_num, mask, dirtype));
1742
1743         /* We don't need to check for VOL here as this is returned by 
1744                 a different TRANS2 call. */
1745   
1746         DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
1747         if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
1748                 dont_descend = True;
1749     
1750         p = pdata;
1751         space_remaining = max_data_bytes;
1752         out_of_space = False;
1753
1754         for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
1755                 BOOL got_exact_match = False;
1756
1757                 /* this is a heuristic to avoid seeking the dirptr except when 
1758                         absolutely necessary. It allows for a filename of about 40 chars */
1759                 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
1760                         out_of_space = True;
1761                         finished = False;
1762                 } else {
1763                         finished = !get_lanman2_dir_entry(conn,
1764                                         inbuf, outbuf,
1765                                         mask,dirtype,info_level,
1766                                         requires_resume_key,dont_descend,
1767                                         &p,pdata,space_remaining, &out_of_space, &got_exact_match,
1768                                         &last_entry_off, ea_list, ea_ctx);
1769                 }
1770
1771                 if (finished && out_of_space)
1772                         finished = False;
1773
1774                 if (!finished && !out_of_space)
1775                         numentries++;
1776
1777                 /*
1778                  * As an optimisation if we know we aren't looking
1779                  * for a wildcard name (ie. the name matches the wildcard exactly)
1780                  * then we can finish on any (first) match.
1781                  * This speeds up large directory searches. JRA.
1782                  */
1783
1784                 if(got_exact_match)
1785                         finished = True;
1786
1787                 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
1788         }
1789   
1790         talloc_destroy(ea_ctx);
1791
1792         /* Check if we can close the dirptr */
1793         if(close_after_first || (finished && close_if_end)) {
1794                 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
1795                 dptr_close(&dptr_num);
1796         }
1797
1798         /* 
1799          * If there are no matching entries we must return ERRDOS/ERRbadfile - 
1800          * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
1801          * the protocol level is less than NT1. Tested with smbclient. JRA.
1802          * This should fix the OS/2 client bug #2335.
1803          */
1804
1805         if(numentries == 0) {
1806                 dptr_close(&dptr_num);
1807                 if (Protocol < PROTOCOL_NT1) {
1808                         return ERROR_DOS(ERRDOS,ERRnofiles);
1809                 } else {
1810                         return ERROR_BOTH(NT_STATUS_NO_SUCH_FILE,ERRDOS,ERRbadfile);
1811                 }
1812         }
1813
1814         /* At this point pdata points to numentries directory entries. */
1815
1816         /* Set up the return parameter block */
1817         SSVAL(params,0,dptr_num);
1818         SSVAL(params,2,numentries);
1819         SSVAL(params,4,finished);
1820         SSVAL(params,6,0); /* Never an EA error */
1821         SSVAL(params,8,last_entry_off);
1822
1823         send_trans2_replies( outbuf, bufsize, params, 10, pdata, PTR_DIFF(p,pdata));
1824
1825         if ((! *directory) && dptr_path(dptr_num))
1826                 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1827
1828         DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
1829                 smb_fn_name(CVAL(inbuf,smb_com)), 
1830                 mask, directory, dirtype, numentries ) );
1831
1832         /* 
1833          * Force a name mangle here to ensure that the
1834          * mask as an 8.3 name is top of the mangled cache.
1835          * The reasons for this are subtle. Don't remove
1836          * this code unless you know what you are doing
1837          * (see PR#13758). JRA.
1838          */
1839
1840         if(!mangle_is_8_3_wildcards( mask, False, SNUM(conn)))
1841                 mangle_map(mask, True, True, SNUM(conn));
1842
1843         return(-1);
1844 }
1845
1846 /****************************************************************************
1847  Reply to a TRANS2_FINDNEXT.
1848 ****************************************************************************/
1849
1850 static int call_trans2findnext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
1851                                         char **pparams, int total_params, char **ppdata, int total_data,
1852                                         unsigned int max_data_bytes)
1853 {
1854         /* We must be careful here that we don't return more than the
1855                 allowed number of data bytes. If this means returning fewer than
1856                 maxentries then so be it. We assume that the redirector has
1857                 enough room for the fixed number of parameter bytes it has
1858                 requested. */
1859         char *params = *pparams;
1860         char *pdata = *ppdata;
1861         int dptr_num = SVAL(params,0);
1862         int maxentries = SVAL(params,2);
1863         uint16 info_level = SVAL(params,4);
1864         uint32 resume_key = IVAL(params,6);
1865         uint16 findnext_flags = SVAL(params,10);
1866         BOOL close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
1867         BOOL close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1868         BOOL requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1869         BOOL continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
1870         BOOL mask_contains_wcard = False;
1871         pstring resume_name;
1872         pstring mask;
1873         pstring directory;
1874         char *p;
1875         uint16 dirtype;
1876         int numentries = 0;
1877         int i, last_entry_off=0;
1878         BOOL finished = False;
1879         BOOL dont_descend = False;
1880         BOOL out_of_space = False;
1881         int space_remaining;
1882         TALLOC_CTX *ea_ctx = NULL;
1883         struct ea_list *ea_list = NULL;
1884         NTSTATUS ntstatus = NT_STATUS_OK;
1885
1886         if (total_params < 12) {
1887                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1888         }
1889
1890         *mask = *directory = *resume_name = 0;
1891
1892         srvstr_get_path_wcard(inbuf, resume_name, params+12, sizeof(resume_name), -1, STR_TERMINATE, &ntstatus, &mask_contains_wcard);
1893         if (!NT_STATUS_IS_OK(ntstatus)) {
1894                 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
1895                    complain (it thinks we're asking for the directory above the shared
1896                    path or an invalid name). Catch this as the resume name is only compared, never used in
1897                    a file access. JRA. */
1898                 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_OBJECT_PATH_SYNTAX_BAD)) {
1899                         pstrcpy(resume_name, "..");
1900                 } else if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_OBJECT_NAME_INVALID)) {
1901                         pstrcpy(resume_name, ".");
1902                 } else {
1903                         return ERROR_NT(ntstatus);
1904                 }
1905         }
1906
1907         DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
1908 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
1909 resume_key = %d resume name = %s continue=%d level = %d\n",
1910                 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end, 
1911                 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
1912
1913         if (!maxentries) {
1914                 /* W2K3 seems to treat zero as 1. */
1915                 maxentries = 1;
1916         }
1917
1918         switch (info_level) {
1919                 case SMB_FIND_INFO_STANDARD:
1920                 case SMB_FIND_EA_SIZE:
1921                 case SMB_FIND_EA_LIST:
1922                 case SMB_FIND_FILE_DIRECTORY_INFO:
1923                 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1924                 case SMB_FIND_FILE_NAMES_INFO:
1925                 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1926                 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1927                 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1928                         break;
1929                 case SMB_FIND_FILE_UNIX:
1930                         if (!lp_unix_extensions()) {
1931                                 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
1932                         }
1933                         break;
1934                 default:
1935                         return ERROR_NT(NT_STATUS_INVALID_LEVEL);
1936         }
1937
1938         if (info_level == SMB_FIND_EA_LIST) {
1939                 uint32 ea_size;
1940
1941                 if (total_data < 4) {
1942                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1943                 }
1944
1945                 ea_size = IVAL(pdata,0);
1946                 if (ea_size != total_data) {
1947                         DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
1948 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
1949                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1950                 }
1951                                                                                                                                                      
1952                 if (!lp_ea_support(SNUM(conn))) {
1953                         return ERROR_DOS(ERRDOS,ERReasnotsupported);
1954                 }
1955                                                                                                                                                      
1956                 if ((ea_ctx = talloc_init("findnext_ea_list")) == NULL) {
1957                         return ERROR_NT(NT_STATUS_NO_MEMORY);
1958                 }
1959
1960                 /* Pull out the list of names. */
1961                 ea_list = read_ea_name_list(ea_ctx, pdata + 4, ea_size - 4);
1962                 if (!ea_list) {
1963                         talloc_destroy(ea_ctx);
1964                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1965                 }
1966         }
1967
1968         *ppdata = SMB_REALLOC( *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1969         if(*ppdata == NULL) {
1970                 talloc_destroy(ea_ctx);
1971                 return ERROR_NT(NT_STATUS_NO_MEMORY);
1972         }
1973
1974         pdata = *ppdata;
1975
1976         /* Realloc the params space */
1977         *pparams = SMB_REALLOC(*pparams, 6*SIZEOFWORD);
1978         if(*pparams == NULL ) {
1979                 talloc_destroy(ea_ctx);
1980                 return ERROR_NT(NT_STATUS_NO_MEMORY);
1981         }
1982
1983         params = *pparams;
1984
1985         /* Check that the dptr is valid */
1986         if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num))) {
1987                 talloc_destroy(ea_ctx);
1988                 return ERROR_DOS(ERRDOS,ERRnofiles);
1989         }
1990
1991         string_set(&conn->dirpath,dptr_path(dptr_num));
1992
1993         /* Get the wildcard mask from the dptr */
1994         if((p = dptr_wcard(dptr_num))== NULL) {
1995                 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
1996                 talloc_destroy(ea_ctx);
1997                 return ERROR_DOS(ERRDOS,ERRnofiles);
1998         }
1999
2000         pstrcpy(mask, p);
2001         pstrcpy(directory,conn->dirpath);
2002
2003         /* Get the attr mask from the dptr */
2004         dirtype = dptr_attr(dptr_num);
2005
2006         DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2007                 dptr_num, mask, dirtype, 
2008                 (long)conn->dirptr,
2009                 dptr_TellDir(conn->dirptr)));
2010
2011         /* We don't need to check for VOL here as this is returned by 
2012                 a different TRANS2 call. */
2013
2014         DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
2015         if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2016                 dont_descend = True;
2017     
2018         p = pdata;
2019         space_remaining = max_data_bytes;
2020         out_of_space = False;
2021
2022         /* 
2023          * Seek to the correct position. We no longer use the resume key but
2024          * depend on the last file name instead.
2025          */
2026
2027         if(*resume_name && !continue_bit) {
2028                 SMB_STRUCT_STAT st;
2029
2030                 long current_pos = 0;
2031                 /*
2032                  * Remember, mangle_map is called by
2033                  * get_lanman2_dir_entry(), so the resume name
2034                  * could be mangled. Ensure we check the unmangled name.
2035                  */
2036
2037                 if (mangle_is_mangled(resume_name, SNUM(conn))) {
2038                         mangle_check_cache(resume_name, sizeof(resume_name)-1, SNUM(conn));
2039                 }
2040
2041                 /*
2042                  * Fix for NT redirector problem triggered by resume key indexes
2043                  * changing between directory scans. We now return a resume key of 0
2044                  * and instead look for the filename to continue from (also given
2045                  * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2046                  * findfirst/findnext (as is usual) then the directory pointer
2047                  * should already be at the correct place.
2048                  */
2049
2050                 finished = !dptr_SearchDir(conn->dirptr, resume_name, &current_pos, &st);
2051         } /* end if resume_name && !continue_bit */
2052
2053         for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2054                 BOOL got_exact_match = False;
2055
2056                 /* this is a heuristic to avoid seeking the dirptr except when 
2057                         absolutely necessary. It allows for a filename of about 40 chars */
2058                 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2059                         out_of_space = True;
2060                         finished = False;
2061                 } else {
2062                         finished = !get_lanman2_dir_entry(conn,
2063                                                 inbuf, outbuf,
2064                                                 mask,dirtype,info_level,
2065                                                 requires_resume_key,dont_descend,
2066                                                 &p,pdata,space_remaining, &out_of_space, &got_exact_match,
2067                                                 &last_entry_off, ea_list, ea_ctx);
2068                 }
2069
2070                 if (finished && out_of_space)
2071                         finished = False;
2072
2073                 if (!finished && !out_of_space)
2074                         numentries++;
2075
2076                 /*
2077                  * As an optimisation if we know we aren't looking
2078                  * for a wildcard name (ie. the name matches the wildcard exactly)
2079                  * then we can finish on any (first) match.
2080                  * This speeds up large directory searches. JRA.
2081                  */
2082
2083                 if(got_exact_match)
2084                         finished = True;
2085
2086                 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2087         }
2088   
2089         talloc_destroy(ea_ctx);
2090
2091         /* Check if we can close the dirptr */
2092         if(close_after_request || (finished && close_if_end)) {
2093                 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2094                 dptr_close(&dptr_num); /* This frees up the saved mask */
2095         }
2096
2097         /* Set up the return parameter block */
2098         SSVAL(params,0,numentries);
2099         SSVAL(params,2,finished);
2100         SSVAL(params,4,0); /* Never an EA error */
2101         SSVAL(params,6,last_entry_off);
2102
2103         send_trans2_replies( outbuf, bufsize, params, 8, pdata, PTR_DIFF(p,pdata));
2104
2105         if ((! *directory) && dptr_path(dptr_num))
2106                 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
2107
2108         DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2109                 smb_fn_name(CVAL(inbuf,smb_com)), 
2110                 mask, directory, dirtype, numentries ) );
2111
2112         return(-1);
2113 }
2114
2115 /****************************************************************************
2116  Reply to a TRANS2_QFSINFO (query filesystem info).
2117 ****************************************************************************/
2118
2119 static int call_trans2qfsinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2120                                         char **pparams, int total_params, char **ppdata, int total_data,
2121                                         unsigned int max_data_bytes)
2122 {
2123         char *pdata = *ppdata;
2124         char *params = *pparams;
2125         uint16 info_level = SVAL(params,0);
2126         int data_len, len;
2127         SMB_STRUCT_STAT st;
2128         char *vname = volume_label(SNUM(conn));
2129         int snum = SNUM(conn);
2130         char *fstype = lp_fstype(SNUM(conn));
2131         int quota_flag = 0;
2132
2133         DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
2134
2135         if(SMB_VFS_STAT(conn,".",&st)!=0) {
2136                 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
2137                 return ERROR_DOS(ERRSRV,ERRinvdevice);
2138         }
2139
2140         *ppdata = SMB_REALLOC(*ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2141         if (*ppdata == NULL ) {
2142                 return ERROR_NT(NT_STATUS_NO_MEMORY);
2143         }
2144
2145         pdata = *ppdata;
2146         memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2147
2148         switch (info_level) {
2149                 case SMB_INFO_ALLOCATION:
2150                 {
2151                         SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2152                         data_len = 18;
2153                         if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2154                                 return(UNIXERROR(ERRHRD,ERRgeneral));
2155                         }
2156
2157                         block_size = lp_block_size(snum);
2158                         if (bsize < block_size) {
2159                                 SMB_BIG_UINT factor = block_size/bsize;
2160                                 bsize = block_size;
2161                                 dsize /= factor;
2162                                 dfree /= factor;
2163                         }
2164                         if (bsize > block_size) {
2165                                 SMB_BIG_UINT factor = bsize/block_size;
2166                                 bsize = block_size;
2167                                 dsize *= factor;
2168                                 dfree *= factor;
2169                         }
2170                         bytes_per_sector = 512;
2171                         sectors_per_unit = bsize/bytes_per_sector;
2172
2173                         DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2174 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2175                                 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2176
2177                         SIVAL(pdata,l1_idFileSystem,st.st_dev);
2178                         SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2179                         SIVAL(pdata,l1_cUnit,dsize);
2180                         SIVAL(pdata,l1_cUnitAvail,dfree);
2181                         SSVAL(pdata,l1_cbSector,bytes_per_sector);
2182                         break;
2183                 }
2184
2185                 case SMB_INFO_VOLUME:
2186                         /* Return volume name */
2187                         /* 
2188                          * Add volume serial number - hash of a combination of
2189                          * the called hostname and the service name.
2190                          */
2191                         SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2192                         /*
2193                          * Win2k3 and previous mess this up by sending a name length
2194                          * one byte short. I believe only older clients (OS/2 Win9x) use
2195                          * this call so try fixing this by adding a terminating null to
2196                          * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2197                          */
2198                         len = srvstr_push(outbuf, pdata+l2_vol_szVolLabel, vname, -1, STR_NOALIGN|STR_TERMINATE);
2199                         SCVAL(pdata,l2_vol_cch,len);
2200                         data_len = l2_vol_szVolLabel + len;
2201                         DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
2202                                 (unsigned)st.st_ctime, len, vname));
2203                         break;
2204
2205                 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2206                 case SMB_FS_ATTRIBUTE_INFORMATION:
2207
2208
2209 #if defined(HAVE_SYS_QUOTAS)
2210                         quota_flag = FILE_VOLUME_QUOTAS;
2211 #endif
2212
2213                         SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2214                                 (lp_nt_acl_support(SNUM(conn)) ? FILE_PERSISTENT_ACLS : 0)|
2215                                 quota_flag); /* FS ATTRIBUTES */
2216
2217                         SIVAL(pdata,4,255); /* Max filename component length */
2218                         /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2219                                 and will think we can't do long filenames */
2220                         len = srvstr_push(outbuf, pdata+12, fstype, -1, STR_UNICODE);
2221                         SIVAL(pdata,8,len);
2222                         data_len = 12 + len;
2223                         break;
2224
2225                 case SMB_QUERY_FS_LABEL_INFO:
2226                 case SMB_FS_LABEL_INFORMATION:
2227                         len = srvstr_push(outbuf, pdata+4, vname, -1, 0);
2228                         data_len = 4 + len;
2229                         SIVAL(pdata,0,len);
2230                         break;
2231
2232                 case SMB_QUERY_FS_VOLUME_INFO:      
2233                 case SMB_FS_VOLUME_INFORMATION:
2234
2235                         /* 
2236                          * Add volume serial number - hash of a combination of
2237                          * the called hostname and the service name.
2238                          */
2239                         SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^ 
2240                                 (str_checksum(get_local_machine_name())<<16));
2241
2242                         len = srvstr_push(outbuf, pdata+18, vname, -1, STR_UNICODE);
2243                         SIVAL(pdata,12,len);
2244                         data_len = 18+len;
2245                         DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n", 
2246                                 (int)strlen(vname),vname, lp_servicename(snum)));
2247                         break;
2248
2249                 case SMB_QUERY_FS_SIZE_INFO:
2250                 case SMB_FS_SIZE_INFORMATION:
2251                 {
2252                         SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2253                         data_len = 24;
2254                         if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2255                                 return(UNIXERROR(ERRHRD,ERRgeneral));
2256                         }
2257                         block_size = lp_block_size(snum);
2258                         if (bsize < block_size) {
2259                                 SMB_BIG_UINT factor = block_size/bsize;
2260                                 bsize = block_size;
2261                                 dsize /= factor;
2262                                 dfree /= factor;
2263                         }
2264                         if (bsize > block_size) {
2265                                 SMB_BIG_UINT factor = bsize/block_size;
2266                                 bsize = block_size;
2267                                 dsize *= factor;
2268                                 dfree *= factor;
2269                         }
2270                         bytes_per_sector = 512;
2271                         sectors_per_unit = bsize/bytes_per_sector;
2272                         DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2273 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2274                                 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2275                         SBIG_UINT(pdata,0,dsize);
2276                         SBIG_UINT(pdata,8,dfree);
2277                         SIVAL(pdata,16,sectors_per_unit);
2278                         SIVAL(pdata,20,bytes_per_sector);
2279                         break;
2280                 }
2281
2282                 case SMB_FS_FULL_SIZE_INFORMATION:
2283                 {
2284                         SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2285                         data_len = 32;
2286                         if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2287                                 return(UNIXERROR(ERRHRD,ERRgeneral));
2288                         }
2289                         block_size = lp_block_size(snum);
2290                         if (bsize < block_size) {
2291                                 SMB_BIG_UINT factor = block_size/bsize;
2292                                 bsize = block_size;
2293                                 dsize /= factor;
2294                                 dfree /= factor;
2295                         }
2296                         if (bsize > block_size) {
2297                                 SMB_BIG_UINT factor = bsize/block_size;
2298                                 bsize = block_size;
2299                                 dsize *= factor;
2300                                 dfree *= factor;
2301                         }
2302                         bytes_per_sector = 512;
2303                         sectors_per_unit = bsize/bytes_per_sector;
2304                         DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2305 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2306                                 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2307                         SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2308                         SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2309                         SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2310                         SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2311                         SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2312                         break;
2313                 }
2314
2315                 case SMB_QUERY_FS_DEVICE_INFO:
2316                 case SMB_FS_DEVICE_INFORMATION:
2317                         data_len = 8;
2318                         SIVAL(pdata,0,0); /* dev type */
2319                         SIVAL(pdata,4,0); /* characteristics */
2320                         break;
2321
2322 #ifdef HAVE_SYS_QUOTAS
2323                 case SMB_FS_QUOTA_INFORMATION:
2324                 /* 
2325                  * what we have to send --metze:
2326                  *
2327                  * Unknown1:            24 NULL bytes
2328                  * Soft Quota Treshold: 8 bytes seems like SMB_BIG_UINT or so
2329                  * Hard Quota Limit:    8 bytes seems like SMB_BIG_UINT or so
2330                  * Quota Flags:         2 byte :
2331                  * Unknown3:            6 NULL bytes
2332                  *
2333                  * 48 bytes total
2334                  * 
2335                  * details for Quota Flags:
2336                  * 
2337                  * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2338                  * 0x0010 Log Warn:  log if the user exceeds his Soft Quota
2339                  * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2340                  * 0x0001 Enable Quotas: enable quota for this fs
2341                  *
2342                  */
2343                 {
2344                         /* we need to fake up a fsp here,
2345                          * because its not send in this call
2346                          */
2347                         files_struct fsp;
2348                         SMB_NTQUOTA_STRUCT quotas;
2349                         
2350                         ZERO_STRUCT(fsp);
2351                         ZERO_STRUCT(quotas);
2352                         
2353                         fsp.conn = conn;
2354                         fsp.fnum = -1;
2355                         
2356                         /* access check */
2357                         if (current_user.ut.uid != 0) {
2358                                 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2359                                         lp_servicename(SNUM(conn)),conn->user));
2360                                 return ERROR_DOS(ERRDOS,ERRnoaccess);
2361                         }
2362                         
2363                         if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
2364                                 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2365                                 return ERROR_DOS(ERRSRV,ERRerror);
2366                         }
2367
2368                         data_len = 48;
2369
2370                         DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn))));          
2371                 
2372                         /* Unknown1 24 NULL bytes*/
2373                         SBIG_UINT(pdata,0,(SMB_BIG_UINT)0);
2374                         SBIG_UINT(pdata,8,(SMB_BIG_UINT)0);
2375                         SBIG_UINT(pdata,16,(SMB_BIG_UINT)0);
2376                 
2377                         /* Default Soft Quota 8 bytes */
2378                         SBIG_UINT(pdata,24,quotas.softlim);
2379
2380                         /* Default Hard Quota 8 bytes */
2381                         SBIG_UINT(pdata,32,quotas.hardlim);
2382         
2383                         /* Quota flag 2 bytes */
2384                         SSVAL(pdata,40,quotas.qflags);
2385                 
2386                         /* Unknown3 6 NULL bytes */
2387                         SSVAL(pdata,42,0);
2388                         SIVAL(pdata,44,0);
2389                         
2390                         break;
2391                 }
2392 #endif /* HAVE_SYS_QUOTAS */
2393                 case SMB_FS_OBJECTID_INFORMATION:
2394                         data_len = 64;
2395                         break;
2396
2397                 /*
2398                  * Query the version and capabilities of the CIFS UNIX extensions
2399                  * in use.
2400                  */
2401
2402                 case SMB_QUERY_CIFS_UNIX_INFO:
2403                         if (!lp_unix_extensions()) {
2404                                 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2405                         }
2406                         data_len = 12;
2407                         SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2408                         SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2409                         /* We have POSIX ACLs, pathname and locking capability. */
2410                         SBIG_UINT(pdata,4,((SMB_BIG_UINT)(
2411                                         CIFS_UNIX_POSIX_ACLS_CAP|
2412                                         CIFS_UNIX_POSIX_PATHNAMES_CAP|
2413 #if defined(DEVELOPER) /* Not quite finished yet... */
2414                                         CIFS_UNIX_FCNTL_LOCKS_CAP)));
2415 #else
2416                                         0)));
2417 #endif
2418                         break;
2419
2420                 case SMB_QUERY_POSIX_FS_INFO:
2421                 {
2422                         int rc;
2423                         vfs_statvfs_struct svfs;
2424
2425                         if (!lp_unix_extensions()) {
2426                                 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2427                         }
2428
2429                         rc = SMB_VFS_STATVFS(conn, ".", &svfs);
2430
2431                         if (!rc) {
2432                                 data_len = 56;
2433                                 SIVAL(pdata,0,svfs.OptimalTransferSize);
2434                                 SIVAL(pdata,4,svfs.BlockSize);
2435                                 SBIG_UINT(pdata,8,svfs.TotalBlocks);
2436                                 SBIG_UINT(pdata,16,svfs.BlocksAvail);
2437                                 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
2438                                 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
2439                                 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
2440                                 SBIG_UINT(pdata,48,svfs.FsIdentifier);
2441                                 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
2442 #ifdef EOPNOTSUPP
2443                         } else if (rc == EOPNOTSUPP) {
2444                                 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2445 #endif /* EOPNOTSUPP */
2446                         } else {
2447                                 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2448                                 return ERROR_DOS(ERRSRV,ERRerror);
2449                         }
2450                         break;
2451                 }
2452
2453                 case SMB_MAC_QUERY_FS_INFO:
2454                         /*
2455                          * Thursby MAC extension... ONLY on NTFS filesystems
2456                          * once we do streams then we don't need this
2457                          */
2458                         if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
2459                                 data_len = 88;
2460                                 SIVAL(pdata,84,0x100); /* Don't support mac... */
2461                                 break;
2462                         }
2463                         /* drop through */
2464                 default:
2465                         return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2466         }
2467
2468
2469         send_trans2_replies( outbuf, bufsize, params, 0, pdata, data_len);
2470
2471         DEBUG( 4, ( "%s info_level = %d\n", smb_fn_name(CVAL(inbuf,smb_com)), info_level) );
2472
2473         return -1;
2474 }
2475
2476 /****************************************************************************
2477  Reply to a TRANS2_SETFSINFO (set filesystem info).
2478 ****************************************************************************/
2479
2480 static int call_trans2setfsinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2481                                         char **pparams, int total_params, char **ppdata, int total_data,
2482                                         unsigned int max_data_bytes)
2483 {
2484         char *pdata = *ppdata;
2485         char *params = *pparams;
2486         uint16 info_level;
2487         int outsize;
2488
2489         DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
2490
2491         /*  */
2492         if (total_params < 4) {
2493                 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
2494                         total_params));
2495                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2496         }
2497
2498         info_level = SVAL(params,2);
2499
2500         switch(info_level) {
2501                 case SMB_SET_CIFS_UNIX_INFO:
2502                         {
2503                                 uint16 client_unix_major;
2504                                 uint16 client_unix_minor;
2505                                 uint32 client_unix_cap_low;
2506                                 uint32 client_unix_cap_high;
2507
2508                                 if (!lp_unix_extensions()) {
2509                                         return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2510                                 }
2511
2512                                 /* There should be 12 bytes of capabilities set. */
2513                                 if (total_data < 8) {
2514                                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2515                                 }
2516                                 client_unix_major = SVAL(pdata,0);
2517                                 client_unix_minor = SVAL(pdata,2);
2518                                 client_unix_cap_low = IVAL(pdata,4);
2519                                 client_unix_cap_high = IVAL(pdata,8);
2520                                 /* Just print these values for now. */
2521                                 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
2522 cap_low = 0x%x, cap_high = 0x%x\n",
2523                                         (unsigned int)client_unix_major,
2524                                         (unsigned int)client_unix_minor,
2525                                         (unsigned int)client_unix_cap_low,
2526                                         (unsigned int)client_unix_cap_high ));
2527
2528                                 /* Here is where we must switch to posix pathname processing... */
2529                                 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
2530                                         lp_set_posix_pathnames();
2531                                         mangle_change_to_posix();
2532                                 }
2533 #if defined(DEVELOPER)
2534                                 if (client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) {
2535                                         lp_set_posix_cifsx_locktype(POSIX_LOCK);
2536                                 }
2537 #endif
2538                                 break;
2539                         }
2540                 case SMB_FS_QUOTA_INFORMATION:
2541                         {
2542                                 files_struct *fsp = NULL;
2543                                 SMB_NTQUOTA_STRUCT quotas;
2544         
2545                                 ZERO_STRUCT(quotas);
2546
2547                                 /* access check */
2548                                 if ((current_user.ut.uid != 0)||!CAN_WRITE(conn)) {
2549                                         DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2550                                                 lp_servicename(SNUM(conn)),conn->user));
2551                                         return ERROR_DOS(ERRSRV,ERRaccess);
2552                                 }
2553
2554                                 /* note: normaly there're 48 bytes,
2555                                  * but we didn't use the last 6 bytes for now 
2556                                  * --metze 
2557                                  */
2558                                 fsp = file_fsp(params,0);
2559                                 if (!CHECK_NTQUOTA_HANDLE_OK(fsp,conn)) {
2560                                         DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
2561                                         return ERROR_NT(NT_STATUS_INVALID_HANDLE);
2562                                 }
2563
2564                                 if (total_data < 42) {
2565                                         DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
2566                                                 total_data));
2567                                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2568                                 }
2569                         
2570                                 /* unknown_1 24 NULL bytes in pdata*/
2571                 
2572                                 /* the soft quotas 8 bytes (SMB_BIG_UINT)*/
2573                                 quotas.softlim = (SMB_BIG_UINT)IVAL(pdata,24);
2574 #ifdef LARGE_SMB_OFF_T
2575                                 quotas.softlim |= (((SMB_BIG_UINT)IVAL(pdata,28)) << 32);
2576 #else /* LARGE_SMB_OFF_T */
2577                                 if ((IVAL(pdata,28) != 0)&&
2578                                         ((quotas.softlim != 0xFFFFFFFF)||
2579                                         (IVAL(pdata,28)!=0xFFFFFFFF))) {
2580                                         /* more than 32 bits? */
2581                                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2582                                 }
2583 #endif /* LARGE_SMB_OFF_T */
2584                 
2585                                 /* the hard quotas 8 bytes (SMB_BIG_UINT)*/
2586                                 quotas.hardlim = (SMB_BIG_UINT)IVAL(pdata,32);
2587 #ifdef LARGE_SMB_OFF_T
2588                                 quotas.hardlim |= (((SMB_BIG_UINT)IVAL(pdata,36)) << 32);
2589 #else /* LARGE_SMB_OFF_T */
2590                                 if ((IVAL(pdata,36) != 0)&&
2591                                         ((quotas.hardlim != 0xFFFFFFFF)||
2592                                         (IVAL(pdata,36)!=0xFFFFFFFF))) {
2593                                         /* more than 32 bits? */
2594                                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2595                                 }
2596 #endif /* LARGE_SMB_OFF_T */
2597                 
2598                                 /* quota_flags 2 bytes **/
2599                                 quotas.qflags = SVAL(pdata,40);
2600                 
2601                                 /* unknown_2 6 NULL bytes follow*/
2602                 
2603                                 /* now set the quotas */
2604                                 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
2605                                         DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2606                                         return ERROR_DOS(ERRSRV,ERRerror);
2607                                 }
2608                         
2609                                 break;
2610                         }
2611                 default:
2612                         DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
2613                                 info_level));
2614                         return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2615                         break;
2616         }
2617
2618         /* 
2619          * sending this reply works fine, 
2620          * but I'm not sure it's the same 
2621          * like windows do...
2622          * --metze
2623          */ 
2624         outsize = set_message(outbuf,10,0,True);
2625
2626         return outsize;
2627 }
2628
2629 /****************************************************************************
2630  Utility function to set bad path error.
2631 ****************************************************************************/
2632
2633 int set_bad_path_error(int err, BOOL bad_path, char *outbuf, int def_class, uint32 def_code)
2634 {
2635         DEBUG(10,("set_bad_path_error: err = %d bad_path = %d\n",
2636                         err, (int)bad_path ));
2637
2638         if(err == ENOENT) {
2639                 if (bad_path) {
2640                         return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
2641                 } else {
2642                         return ERROR_NT(NT_STATUS_OBJECT_NAME_NOT_FOUND);
2643                 }
2644         }
2645         return UNIXERROR(def_class,def_code);
2646 }
2647
2648 #if defined(HAVE_POSIX_ACLS)
2649 /****************************************************************************
2650  Utility function to count the number of entries in a POSIX acl.
2651 ****************************************************************************/
2652
2653 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
2654 {
2655         unsigned int ace_count = 0;
2656         int entry_id = SMB_ACL_FIRST_ENTRY;
2657         SMB_ACL_ENTRY_T entry;
2658
2659         while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
2660                 /* get_next... */
2661                 if (entry_id == SMB_ACL_FIRST_ENTRY) {
2662                         entry_id = SMB_ACL_NEXT_ENTRY;
2663                 }
2664                 ace_count++;
2665         }
2666         return ace_count;
2667 }
2668
2669 /****************************************************************************
2670  Utility function to marshall a POSIX acl into wire format.
2671 ****************************************************************************/
2672
2673 static BOOL marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
2674 {
2675         int entry_id = SMB_ACL_FIRST_ENTRY;
2676         SMB_ACL_ENTRY_T entry;
2677
2678         while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
2679                 SMB_ACL_TAG_T tagtype;
2680                 SMB_ACL_PERMSET_T permset;
2681                 unsigned char perms = 0;
2682                 unsigned int own_grp;
2683
2684                 /* get_next... */
2685                 if (entry_id == SMB_ACL_FIRST_ENTRY) {
2686                         entry_id = SMB_ACL_NEXT_ENTRY;
2687                 }
2688
2689                 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
2690                         DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
2691                         return False;
2692                 }
2693
2694                 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
2695                         DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
2696                         return False;
2697                 }
2698
2699                 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
2700                 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
2701                 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
2702
2703                 SCVAL(pdata,1,perms);
2704
2705                 switch (tagtype) {
2706                         case SMB_ACL_USER_OBJ:
2707                                 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
2708                                 own_grp = (unsigned int)pst->st_uid;
2709                                 SIVAL(pdata,2,own_grp);
2710                                 SIVAL(pdata,6,0);
2711                                 break;
2712                         case SMB_ACL_USER:
2713                                 {
2714                                         uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
2715                                         if (!puid) {
2716                                                 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
2717                                         }
2718                                         own_grp = (unsigned int)*puid;
2719                                         SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
2720                                         SCVAL(pdata,0,SMB_POSIX_ACL_USER);
2721                                         SIVAL(pdata,2,own_grp);
2722                                         SIVAL(pdata,6,0);
2723                                         break;
2724                                 }
2725                         case SMB_ACL_GROUP_OBJ:
2726                                 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
2727                                 own_grp = (unsigned int)pst->st_gid;
2728                                 SIVAL(pdata,2,own_grp);
2729                                 SIVAL(pdata,6,0);
2730                                 break;
2731                         case SMB_ACL_GROUP:
2732                                 {
2733                                         gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
2734                                         if (!pgid) {
2735                                                 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
2736                                         }
2737                                         own_grp = (unsigned int)*pgid;
2738                                         SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
2739                                         SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
2740                                         SIVAL(pdata,2,own_grp);
2741                                         SIVAL(pdata,6,0);
2742                                         break;
2743                                 }
2744                         case SMB_ACL_MASK:
2745                                 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
2746                                 SIVAL(pdata,2,0xFFFFFFFF);
2747                                 SIVAL(pdata,6,0xFFFFFFFF);
2748                                 break;
2749                         case SMB_ACL_OTHER:
2750                                 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
2751                                 SIVAL(pdata,2,0xFFFFFFFF);
2752                                 SIVAL(pdata,6,0xFFFFFFFF);
2753                                 break;
2754                         default:
2755                                 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
2756                                 return False;
2757                 }
2758                 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
2759         }
2760
2761         return True;
2762 }
2763 #endif
2764
2765 /****************************************************************************
2766  Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
2767  file name or file id).
2768 ****************************************************************************/
2769
2770 static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2771                                         unsigned int tran_call,
2772                                         char **pparams, int total_params, char **ppdata, int total_data,
2773                                         unsigned int max_data_bytes)
2774 {
2775         char *params = *pparams;
2776         char *pdata = *ppdata;
2777         uint16 info_level;
2778         int mode=0;
2779         int nlink;
2780         SMB_OFF_T file_size=0;
2781         SMB_BIG_UINT allocation_size=0;
2782         unsigned int data_size = 0;
2783         unsigned int param_size = 2;
2784         SMB_STRUCT_STAT sbuf;
2785         pstring fname, dos_fname;
2786         char *fullpathname;
2787         char *base_name;
2788         char *p;
2789         char *lock_data = NULL;
2790         SMB_OFF_T pos = 0;
2791         BOOL bad_path = False;
2792         BOOL delete_pending = False;
2793         int len;
2794         time_t c_time;
2795         files_struct *fsp = NULL;
2796         TALLOC_CTX *data_ctx = NULL;
2797         struct ea_list *ea_list = NULL;
2798         uint32 access_mask = 0x12019F; /* Default - GENERIC_EXECUTE mapping from Windows */
2799
2800         if (!params)
2801                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2802
2803         ZERO_STRUCT(sbuf);
2804
2805         if (tran_call == TRANSACT2_QFILEINFO) {
2806                 if (total_params < 4) {
2807                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2808                 }
2809
2810                 fsp = file_fsp(params,0);
2811                 info_level = SVAL(params,2);
2812
2813                 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
2814
2815                 if(fsp && (fsp->fake_file_handle)) {
2816                         /*
2817                          * This is actually for the QUOTA_FAKE_FILE --metze
2818                          */
2819                                                 
2820                         pstrcpy(fname, fsp->fsp_name);
2821                         /* We know this name is ok, it's already passed the checks. */
2822                         
2823                 } else if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
2824                         /*
2825                          * This is actually a QFILEINFO on a directory
2826                          * handle (returned from an NT SMB). NT5.0 seems
2827                          * to do this call. JRA.
2828                          */
2829                         /* We know this name is ok, it's already passed the checks. */
2830                         pstrcpy(fname, fsp->fsp_name);
2831                   
2832                         if (INFO_LEVEL_IS_UNIX(info_level)) {
2833                                 /* Always do lstat for UNIX calls. */
2834                                 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
2835                                         DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
2836                                         return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2837                                 }
2838                         } else if (SMB_VFS_STAT(conn,fname,&sbuf)) {
2839                                 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
2840                                 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2841                         }
2842
2843                         delete_pending = get_delete_on_close_flag(sbuf.st_dev, sbuf.st_ino);
2844                 } else {
2845                         /*
2846                          * Original code - this is an open file.
2847                          */
2848                         CHECK_FSP(fsp,conn);
2849
2850                         pstrcpy(fname, fsp->fsp_name);
2851                         if (SMB_VFS_FSTAT(fsp,fsp->fh->fd,&sbuf) != 0) {
2852                                 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
2853                                 return(UNIXERROR(ERRDOS,ERRbadfid));
2854                         }
2855                         pos = fsp->fh->position_information;
2856                         delete_pending = get_delete_on_close_flag(sbuf.st_dev, sbuf.st_ino);
2857                         access_mask = fsp->access_mask;
2858                 }
2859         } else {
2860                 NTSTATUS status = NT_STATUS_OK;
2861