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