Fix a debug message
[kai/samba-autobuild/.git] / source3 / 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-2007
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 3 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, see <http://www.gnu.org/licenses/>.
24 */
25
26 #include "includes.h"
27
28 extern int max_send;
29 extern enum protocol_types Protocol;
30 extern uint32 global_client_caps;
31 extern struct current_user current_user;
32
33 #define get_file_size(sbuf) ((sbuf).st_size)
34 #define DIR_ENTRY_SAFETY_MARGIN 4096
35
36 static char *store_file_unix_basic(connection_struct *conn,
37                                 char *pdata,
38                                 files_struct *fsp,
39                                 const SMB_STRUCT_STAT *psbuf);
40
41 static char *store_file_unix_basic_info2(connection_struct *conn,
42                                 char *pdata,
43                                 files_struct *fsp,
44                                 const SMB_STRUCT_STAT *psbuf);
45
46 /********************************************************************
47  Roundup a value to the nearest allocation roundup size boundary.
48  Only do this for Windows clients.
49 ********************************************************************/
50
51 SMB_BIG_UINT smb_roundup(connection_struct *conn, SMB_BIG_UINT val)
52 {
53         SMB_BIG_UINT rval = lp_allocation_roundup_size(SNUM(conn));
54
55         /* Only roundup for Windows clients. */
56         enum remote_arch_types ra_type = get_remote_arch();
57         if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
58                 val = SMB_ROUNDUP(val,rval);
59         }
60         return val;
61 }
62
63 /********************************************************************
64  Given a stat buffer return the allocated size on disk, taking into
65  account sparse files.
66 ********************************************************************/
67
68 SMB_BIG_UINT get_allocation_size(connection_struct *conn, files_struct *fsp, const SMB_STRUCT_STAT *sbuf)
69 {
70         SMB_BIG_UINT ret;
71
72         if(S_ISDIR(sbuf->st_mode)) {
73                 return 0;
74         }
75
76 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
77         ret = (SMB_BIG_UINT)STAT_ST_BLOCKSIZE * (SMB_BIG_UINT)sbuf->st_blocks;
78 #else
79         ret = (SMB_BIG_UINT)get_file_size(*sbuf);
80 #endif
81
82         if (fsp && fsp->initial_allocation_size)
83                 ret = MAX(ret,fsp->initial_allocation_size);
84
85         return smb_roundup(conn, ret);
86 }
87
88 /****************************************************************************
89  Utility functions for dealing with extended attributes.
90 ****************************************************************************/
91
92 /****************************************************************************
93  Refuse to allow clients to overwrite our private xattrs.
94 ****************************************************************************/
95
96 static bool samba_private_attr_name(const char *unix_ea_name)
97 {
98         static const char *prohibited_ea_names[] = {
99                 SAMBA_POSIX_INHERITANCE_EA_NAME,
100                 SAMBA_XATTR_DOS_ATTRIB,
101                 NULL
102         };
103
104         int i;
105
106         for (i = 0; prohibited_ea_names[i]; i++) {
107                 if (strequal( prohibited_ea_names[i], unix_ea_name))
108                         return True;
109         }
110         return False;
111 }
112
113 /****************************************************************************
114  Get one EA value. Fill in a struct ea_struct.
115 ****************************************************************************/
116
117 static bool get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
118                                 const char *fname, char *ea_name, struct ea_struct *pea)
119 {
120         /* Get the value of this xattr. Max size is 64k. */
121         size_t attr_size = 256;
122         char *val = NULL;
123         ssize_t sizeret;
124
125  again:
126
127         val = TALLOC_REALLOC_ARRAY(mem_ctx, val, char, attr_size);
128         if (!val) {
129                 return False;
130         }
131
132         if (fsp && fsp->fh->fd != -1) {
133                 sizeret = SMB_VFS_FGETXATTR(fsp, fsp->fh->fd, ea_name, val, attr_size);
134         } else {
135                 sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
136         }
137
138         if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
139                 attr_size = 65536;
140                 goto again;
141         }
142
143         if (sizeret == -1) {
144                 return False;
145         }
146
147         DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name, (unsigned int)sizeret));
148         dump_data(10, (uint8 *)val, sizeret);
149
150         pea->flags = 0;
151         if (strnequal(ea_name, "user.", 5)) {
152                 pea->name = &ea_name[5];
153         } else {
154                 pea->name = ea_name;
155         }
156         pea->value.data = (unsigned char *)val;
157         pea->value.length = (size_t)sizeret;
158         return True;
159 }
160
161 /****************************************************************************
162  Return a linked list of the total EA's. Plus the total size
163 ****************************************************************************/
164
165 static struct ea_list *get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
166                                         const char *fname, size_t *pea_total_len)
167 {
168         /* Get a list of all xattrs. Max namesize is 64k. */
169         size_t ea_namelist_size = 1024;
170         char *ea_namelist;
171         char *p;
172         ssize_t sizeret;
173         int i;
174         struct ea_list *ea_list_head = NULL;
175
176         *pea_total_len = 0;
177
178         if (!lp_ea_support(SNUM(conn))) {
179                 return NULL;
180         }
181
182         for (i = 0, ea_namelist = TALLOC_ARRAY(mem_ctx, char, ea_namelist_size); i < 6;
183              ea_namelist = TALLOC_REALLOC_ARRAY(mem_ctx, ea_namelist, char, ea_namelist_size), i++) {
184
185                 if (!ea_namelist) {
186                         return NULL;
187                 }
188
189                 if (fsp && fsp->fh->fd != -1) {
190                         sizeret = SMB_VFS_FLISTXATTR(fsp, fsp->fh->fd, ea_namelist, ea_namelist_size);
191                 } else {
192                         sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist, ea_namelist_size);
193                 }
194
195                 if (sizeret == -1 && errno == ERANGE) {
196                         ea_namelist_size *= 2;
197                 } else {
198                         break;
199                 }
200         }
201
202         if (sizeret == -1)
203                 return NULL;
204
205         DEBUG(10,("get_ea_list_from_file: ea_namelist size = %u\n", (unsigned int)sizeret ));
206
207         if (sizeret) {
208                 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p) + 1) {
209                         struct ea_list *listp;
210
211                         if (strnequal(p, "system.", 7) || samba_private_attr_name(p))
212                                 continue;
213
214                         listp = TALLOC_P(mem_ctx, struct ea_list);
215                         if (!listp)
216                                 return NULL;
217
218                         if (!get_ea_value(mem_ctx, conn, fsp, fname, p, &listp->ea)) {
219                                 return NULL;
220                         }
221
222                         {
223                                 fstring dos_ea_name;
224                                 push_ascii_fstring(dos_ea_name, listp->ea.name);
225                                 *pea_total_len += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
226                                 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len = %u\n",
227                                         (unsigned int)*pea_total_len, dos_ea_name,
228                                         (unsigned int)listp->ea.value.length ));
229                         }
230                         DLIST_ADD_END(ea_list_head, listp, struct ea_list *);
231                 }
232                 /* Add on 4 for total length. */
233                 if (*pea_total_len) {
234                         *pea_total_len += 4;
235                 }
236         }
237
238         DEBUG(10,("get_ea_list_from_file: total_len = %u\n", (unsigned int)*pea_total_len));
239         return ea_list_head;
240 }
241
242 /****************************************************************************
243  Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
244  that was filled.
245 ****************************************************************************/
246
247 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
248         connection_struct *conn, struct ea_list *ea_list)
249 {
250         unsigned int ret_data_size = 4;
251         char *p = pdata;
252
253         SMB_ASSERT(total_data_size >= 4);
254
255         if (!lp_ea_support(SNUM(conn))) {
256                 SIVAL(pdata,4,0);
257                 return 4;
258         }
259
260         for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
261                 size_t dos_namelen;
262                 fstring dos_ea_name;
263                 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
264                 dos_namelen = strlen(dos_ea_name);
265                 if (dos_namelen > 255 || dos_namelen == 0) {
266                         break;
267                 }
268                 if (ea_list->ea.value.length > 65535) {
269                         break;
270                 }
271                 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
272                         break;
273                 }
274
275                 /* We know we have room. */
276                 SCVAL(p,0,ea_list->ea.flags);
277                 SCVAL(p,1,dos_namelen);
278                 SSVAL(p,2,ea_list->ea.value.length);
279                 fstrcpy(p+4, dos_ea_name);
280                 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
281
282                 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
283                 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
284         }
285
286         ret_data_size = PTR_DIFF(p, pdata);
287         DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
288         SIVAL(pdata,0,ret_data_size);
289         return ret_data_size;
290 }
291
292 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const char *fname)
293 {
294         size_t total_ea_len = 0;
295         TALLOC_CTX *mem_ctx = NULL;
296
297         if (!lp_ea_support(SNUM(conn))) {
298                 return 0;
299         }
300         mem_ctx = talloc_init("estimate_ea_size");
301         (void)get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
302         talloc_destroy(mem_ctx);
303         return total_ea_len;
304 }
305
306 /****************************************************************************
307  Ensure the EA name is case insensitive by matching any existing EA name.
308 ****************************************************************************/
309
310 static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
311 {
312         size_t total_ea_len;
313         TALLOC_CTX *mem_ctx = talloc_init("canonicalize_ea_name");
314         struct ea_list *ea_list = get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
315
316         for (; ea_list; ea_list = ea_list->next) {
317                 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
318                         DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
319                                 &unix_ea_name[5], ea_list->ea.name));
320                         safe_strcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-6);
321                         break;
322                 }
323         }
324         talloc_destroy(mem_ctx);
325 }
326
327 /****************************************************************************
328  Set or delete an extended attribute.
329 ****************************************************************************/
330
331 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp, const char *fname, struct ea_list *ea_list)
332 {
333         if (!lp_ea_support(SNUM(conn))) {
334                 return NT_STATUS_EAS_NOT_SUPPORTED;
335         }
336
337         for (;ea_list; ea_list = ea_list->next) {
338                 int ret;
339                 fstring unix_ea_name;
340
341                 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
342                 fstrcat(unix_ea_name, ea_list->ea.name);
343
344                 canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
345
346                 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
347
348                 if (samba_private_attr_name(unix_ea_name)) {
349                         DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
350                         return NT_STATUS_ACCESS_DENIED;
351                 }
352
353                 if (ea_list->ea.value.length == 0) {
354                         /* Remove the attribute. */
355                         if (fsp && (fsp->fh->fd != -1)) {
356                                 DEBUG(10,("set_ea: deleting ea name %s on file %s by file descriptor.\n",
357                                         unix_ea_name, fsp->fsp_name));
358                                 ret = SMB_VFS_FREMOVEXATTR(fsp, fsp->fh->fd, unix_ea_name);
359                         } else {
360                                 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
361                                         unix_ea_name, fname));
362                                 ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
363                         }
364 #ifdef ENOATTR
365                         /* Removing a non existent attribute always succeeds. */
366                         if (ret == -1 && errno == ENOATTR) {
367                                 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
368                                                 unix_ea_name));
369                                 ret = 0;
370                         }
371 #endif
372                 } else {
373                         if (fsp && (fsp->fh->fd != -1)) {
374                                 DEBUG(10,("set_ea: setting ea name %s on file %s by file descriptor.\n",
375                                         unix_ea_name, fsp->fsp_name));
376                                 ret = SMB_VFS_FSETXATTR(fsp, fsp->fh->fd, unix_ea_name,
377                                                         ea_list->ea.value.data, ea_list->ea.value.length, 0);
378                         } else {
379                                 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
380                                         unix_ea_name, fname));
381                                 ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name,
382                                                         ea_list->ea.value.data, ea_list->ea.value.length, 0);
383                         }
384                 }
385
386                 if (ret == -1) {
387 #ifdef ENOTSUP
388                         if (errno == ENOTSUP) {
389                                 return NT_STATUS_EAS_NOT_SUPPORTED;
390                         }
391 #endif
392                         return map_nt_error_from_unix(errno);
393                 }
394
395         }
396         return NT_STATUS_OK;
397 }
398 /****************************************************************************
399  Read a list of EA names from an incoming data buffer. Create an ea_list with them.
400 ****************************************************************************/
401
402 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
403 {
404         struct ea_list *ea_list_head = NULL;
405         size_t offset = 0;
406
407         while (offset + 2 < data_size) {
408                 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
409                 unsigned int namelen = CVAL(pdata,offset);
410
411                 offset++; /* Go past the namelen byte. */
412
413                 /* integer wrap paranioa. */
414                 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
415                                 (offset > data_size) || (namelen > data_size) ||
416                                 (offset + namelen >= data_size)) {
417                         break;
418                 }
419                 /* Ensure the name is null terminated. */
420                 if (pdata[offset + namelen] != '\0') {
421                         return NULL;
422                 }
423                 pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset]);
424                 if (!eal->ea.name) {
425                         return NULL;
426                 }
427
428                 offset += (namelen + 1); /* Go past the name + terminating zero. */
429                 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
430                 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
431         }
432
433         return ea_list_head;
434 }
435
436 /****************************************************************************
437  Read one EA list entry from the buffer.
438 ****************************************************************************/
439
440 struct ea_list *read_ea_list_entry(TALLOC_CTX *ctx, const char *pdata, size_t data_size, size_t *pbytes_used)
441 {
442         struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
443         uint16 val_len;
444         unsigned int namelen;
445
446         if (!eal) {
447                 return NULL;
448         }
449
450         if (data_size < 6) {
451                 return NULL;
452         }
453
454         eal->ea.flags = CVAL(pdata,0);
455         namelen = CVAL(pdata,1);
456         val_len = SVAL(pdata,2);
457
458         if (4 + namelen + 1 + val_len > data_size) {
459                 return NULL;
460         }
461
462         /* Ensure the name is null terminated. */
463         if (pdata[namelen + 4] != '\0') {
464                 return NULL;
465         }
466         pull_ascii_talloc(ctx, &eal->ea.name, pdata + 4);
467         if (!eal->ea.name) {
468                 return NULL;
469         }
470
471         eal->ea.value = data_blob_talloc(eal, NULL, (size_t)val_len + 1);
472         if (!eal->ea.value.data) {
473                 return NULL;
474         }
475
476         memcpy(eal->ea.value.data, pdata + 4 + namelen + 1, val_len);
477
478         /* Ensure we're null terminated just in case we print the value. */
479         eal->ea.value.data[val_len] = '\0';
480         /* But don't count the null. */
481         eal->ea.value.length--;
482
483         if (pbytes_used) {
484                 *pbytes_used = 4 + namelen + 1 + val_len;
485         }
486
487         DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal->ea.name));
488         dump_data(10, eal->ea.value.data, eal->ea.value.length);
489
490         return eal;
491 }
492
493 /****************************************************************************
494  Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
495 ****************************************************************************/
496
497 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
498 {
499         struct ea_list *ea_list_head = NULL;
500         size_t offset = 0;
501         size_t bytes_used = 0;
502
503         while (offset < data_size) {
504                 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
505
506                 if (!eal) {
507                         return NULL;
508                 }
509
510                 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
511                 offset += bytes_used;
512         }
513
514         return ea_list_head;
515 }
516
517 /****************************************************************************
518  Count the total EA size needed.
519 ****************************************************************************/
520
521 static size_t ea_list_size(struct ea_list *ealist)
522 {
523         fstring dos_ea_name;
524         struct ea_list *listp;
525         size_t ret = 0;
526
527         for (listp = ealist; listp; listp = listp->next) {
528                 push_ascii_fstring(dos_ea_name, listp->ea.name);
529                 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
530         }
531         /* Add on 4 for total length. */
532         if (ret) {
533                 ret += 4;
534         }
535
536         return ret;
537 }
538
539 /****************************************************************************
540  Return a union of EA's from a file list and a list of names.
541  The TALLOC context for the two lists *MUST* be identical as we steal
542  memory from one list to add to another. JRA.
543 ****************************************************************************/
544
545 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
546 {
547         struct ea_list *nlistp, *flistp;
548
549         for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
550                 for (flistp = file_list; flistp; flistp = flistp->next) {
551                         if (strequal(nlistp->ea.name, flistp->ea.name)) {
552                                 break;
553                         }
554                 }
555
556                 if (flistp) {
557                         /* Copy the data from this entry. */
558                         nlistp->ea.flags = flistp->ea.flags;
559                         nlistp->ea.value = flistp->ea.value;
560                 } else {
561                         /* Null entry. */
562                         nlistp->ea.flags = 0;
563                         ZERO_STRUCT(nlistp->ea.value);
564                 }
565         }
566
567         *total_ea_len = ea_list_size(name_list);
568         return name_list;
569 }
570
571 /****************************************************************************
572   Send the required number of replies back.
573   We assume all fields other than the data fields are
574   set correctly for the type of call.
575   HACK ! Always assumes smb_setup field is zero.
576 ****************************************************************************/
577
578 void send_trans2_replies(struct smb_request *req,
579                          const char *params,
580                          int paramsize,
581                          const char *pdata,
582                          int datasize,
583                          int max_data_bytes)
584 {
585         /* As we are using a protocol > LANMAN1 then the max_send
586          variable must have been set in the sessetupX call.
587          This takes precedence over the max_xmit field in the
588          global struct. These different max_xmit variables should
589          be merged as this is now too confusing */
590
591         int data_to_send = datasize;
592         int params_to_send = paramsize;
593         int useable_space;
594         const char *pp = params;
595         const char *pd = pdata;
596         int params_sent_thistime, data_sent_thistime, total_sent_thistime;
597         int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
598         int data_alignment_offset = 0;
599         bool overflow = False;
600
601         /* Modify the data_to_send and datasize and set the error if
602            we're trying to send more than max_data_bytes. We still send
603            the part of the packet(s) that fit. Strange, but needed
604            for OS/2. */
605
606         if (max_data_bytes > 0 && datasize > max_data_bytes) {
607                 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
608                         max_data_bytes, datasize ));
609                 datasize = data_to_send = max_data_bytes;
610                 overflow = True;
611         }
612
613         /* If there genuinely are no parameters or data to send just send the empty packet */
614
615         if(params_to_send == 0 && data_to_send == 0) {
616                 reply_outbuf(req, 10, 0);
617                 show_msg((char *)req->outbuf);
618                 return;
619         }
620
621         /* When sending params and data ensure that both are nicely aligned */
622         /* Only do this alignment when there is also data to send - else
623                 can cause NT redirector problems. */
624
625         if (((params_to_send % 4) != 0) && (data_to_send != 0))
626                 data_alignment_offset = 4 - (params_to_send % 4);
627
628         /* Space is bufsize minus Netbios over TCP header minus SMB header */
629         /* The alignment_offset is to align the param bytes on an even byte
630                 boundary. NT 4.0 Beta needs this to work correctly. */
631
632         useable_space = max_send - (smb_size
633                                     + 2 * 10 /* wct */
634                                     + alignment_offset
635                                     + data_alignment_offset);
636
637         /* useable_space can never be more than max_send minus the alignment offset. */
638
639         useable_space = MIN(useable_space, max_send - (alignment_offset+data_alignment_offset));
640
641         while (params_to_send || data_to_send) {
642                 /* Calculate whether we will totally or partially fill this packet */
643
644                 total_sent_thistime = params_to_send + data_to_send + alignment_offset + data_alignment_offset;
645
646                 /* We can never send more than useable_space */
647                 /*
648                  * Note that 'useable_space' does not include the alignment offsets,
649                  * but we must include the alignment offsets in the calculation of
650                  * the length of the data we send over the wire, as the alignment offsets
651                  * are sent here. Fix from Marc_Jacobsen@hp.com.
652                  */
653
654                 total_sent_thistime = MIN(total_sent_thistime, useable_space+ alignment_offset + data_alignment_offset);
655
656                 reply_outbuf(req, 10, total_sent_thistime);
657
658                 /* Set total params and data to be sent */
659                 SSVAL(req->outbuf,smb_tprcnt,paramsize);
660                 SSVAL(req->outbuf,smb_tdrcnt,datasize);
661
662                 /* Calculate how many parameters and data we can fit into
663                  * this packet. Parameters get precedence
664                  */
665
666                 params_sent_thistime = MIN(params_to_send,useable_space);
667                 data_sent_thistime = useable_space - params_sent_thistime;
668                 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
669
670                 SSVAL(req->outbuf,smb_prcnt, params_sent_thistime);
671
672                 /* smb_proff is the offset from the start of the SMB header to the
673                         parameter bytes, however the first 4 bytes of outbuf are
674                         the Netbios over TCP header. Thus use smb_base() to subtract
675                         them from the calculation */
676
677                 SSVAL(req->outbuf,smb_proff,
678                       ((smb_buf(req->outbuf)+alignment_offset)
679                        - smb_base(req->outbuf)));
680
681                 if(params_sent_thistime == 0)
682                         SSVAL(req->outbuf,smb_prdisp,0);
683                 else
684                         /* Absolute displacement of param bytes sent in this packet */
685                         SSVAL(req->outbuf,smb_prdisp,pp - params);
686
687                 SSVAL(req->outbuf,smb_drcnt, data_sent_thistime);
688                 if(data_sent_thistime == 0) {
689                         SSVAL(req->outbuf,smb_droff,0);
690                         SSVAL(req->outbuf,smb_drdisp, 0);
691                 } else {
692                         /* The offset of the data bytes is the offset of the
693                                 parameter bytes plus the number of parameters being sent this time */
694                         SSVAL(req->outbuf, smb_droff,
695                               ((smb_buf(req->outbuf)+alignment_offset)
696                                - smb_base(req->outbuf))
697                               + params_sent_thistime + data_alignment_offset);
698                         SSVAL(req->outbuf,smb_drdisp, pd - pdata);
699                 }
700
701                 /* Initialize the padding for alignment */
702
703                 if (alignment_offset != 0) {
704                         memset(smb_buf(req->outbuf), 0, alignment_offset);
705                 }
706
707                 /* Copy the param bytes into the packet */
708
709                 if(params_sent_thistime) {
710                         memcpy((smb_buf(req->outbuf)+alignment_offset), pp,
711                                params_sent_thistime);
712                 }
713
714                 /* Copy in the data bytes */
715                 if(data_sent_thistime) {
716                         if (data_alignment_offset != 0) {
717                                 memset((smb_buf(req->outbuf)+alignment_offset+
718                                         params_sent_thistime), 0,
719                                        data_alignment_offset);
720                         }
721                         memcpy(smb_buf(req->outbuf)+alignment_offset
722                                +params_sent_thistime+data_alignment_offset,
723                                pd,data_sent_thistime);
724                 }
725
726                 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
727                         params_sent_thistime, data_sent_thistime, useable_space));
728                 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
729                         params_to_send, data_to_send, paramsize, datasize));
730
731                 if (overflow) {
732                         error_packet_set((char *)req->outbuf,
733                                          ERRDOS,ERRbufferoverflow,
734                                          STATUS_BUFFER_OVERFLOW,
735                                          __LINE__,__FILE__);
736                 }
737
738                 /* Send the packet */
739                 show_msg((char *)req->outbuf);
740                 if (!send_smb(smbd_server_fd(),(char *)req->outbuf))
741                         exit_server_cleanly("send_trans2_replies: send_smb failed.");
742
743                 TALLOC_FREE(req->outbuf);
744
745                 pp += params_sent_thistime;
746                 pd += data_sent_thistime;
747
748                 params_to_send -= params_sent_thistime;
749                 data_to_send -= data_sent_thistime;
750
751                 /* Sanity check */
752                 if(params_to_send < 0 || data_to_send < 0) {
753                         DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
754                                 params_to_send, data_to_send));
755                         return;
756                 }
757         }
758
759         return;
760 }
761
762 /****************************************************************************
763  Reply to a TRANSACT2_OPEN.
764 ****************************************************************************/
765
766 static void call_trans2open(connection_struct *conn,
767                             struct smb_request *req,
768                             char **pparams, int total_params,
769                             char **ppdata, int total_data,
770                             unsigned int max_data_bytes)
771 {
772         char *params = *pparams;
773         char *pdata = *ppdata;
774         int deny_mode;
775         int32 open_attr;
776         bool oplock_request;
777 #if 0
778         bool return_additional_info;
779         int16 open_sattr;
780         time_t open_time;
781 #endif
782         int open_ofun;
783         uint32 open_size;
784         char *pname;
785         char *fname = NULL;
786         SMB_OFF_T size=0;
787         int fattr=0,mtime=0;
788         SMB_INO_T inode = 0;
789         SMB_STRUCT_STAT sbuf;
790         int smb_action = 0;
791         files_struct *fsp;
792         struct ea_list *ea_list = NULL;
793         uint16 flags = 0;
794         NTSTATUS status;
795         uint32 access_mask;
796         uint32 share_mode;
797         uint32 create_disposition;
798         uint32 create_options = 0;
799         TALLOC_CTX *ctx = talloc_tos();
800
801         /*
802          * Ensure we have enough parameters to perform the operation.
803          */
804
805         if (total_params < 29) {
806                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
807                 return;
808         }
809
810         flags = SVAL(params, 0);
811         deny_mode = SVAL(params, 2);
812         open_attr = SVAL(params,6);
813         oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
814         if (oplock_request) {
815                 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
816         }
817
818 #if 0
819         return_additional_info = BITSETW(params,0);
820         open_sattr = SVAL(params, 4);
821         open_time = make_unix_date3(params+8);
822 #endif
823         open_ofun = SVAL(params,12);
824         open_size = IVAL(params,14);
825         pname = &params[28];
826
827         if (IS_IPC(conn)) {
828                 reply_doserror(req, ERRSRV, ERRaccess);
829                 return;
830         }
831
832         srvstr_get_path(ctx, params, req->flags2, &fname, pname,
833                         total_params - 28, STR_TERMINATE,
834                         &status);
835         if (!NT_STATUS_IS_OK(status)) {
836                 reply_nterror(req, status);
837                 return;
838         }
839
840         DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
841                 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
842                 (unsigned int)open_ofun, open_size));
843
844         /* XXXX we need to handle passed times, sattr and flags */
845
846         status = unix_convert(ctx, conn, fname, False, &fname, NULL, &sbuf);
847         if (!NT_STATUS_IS_OK(status)) {
848                 reply_nterror(req, status);
849                 return;
850         }
851
852         status = check_name(conn, fname);
853         if (!NT_STATUS_IS_OK(status)) {
854                 reply_nterror(req, status);
855                 return;
856         }
857
858         if (open_ofun == 0) {
859                 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
860                 return;
861         }
862
863         if (!map_open_params_to_ntcreate(fname, deny_mode, open_ofun,
864                                 &access_mask,
865                                 &share_mode,
866                                 &create_disposition,
867                                 &create_options)) {
868                 reply_doserror(req, ERRDOS, ERRbadaccess);
869                 return;
870         }
871
872         /* Any data in this call is an EA list. */
873         if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
874                 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
875                 return;
876         }
877
878         if (total_data != 4) {
879                 if (total_data < 10) {
880                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
881                         return;
882                 }
883
884                 if (IVAL(pdata,0) > total_data) {
885                         DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
886                                 IVAL(pdata,0), (unsigned int)total_data));
887                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
888                         return;
889                 }
890
891                 ea_list = read_ea_list(talloc_tos(), pdata + 4,
892                                        total_data - 4);
893                 if (!ea_list) {
894                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
895                         return;
896                 }
897         } else if (IVAL(pdata,0) != 4) {
898                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
899                 return;
900         }
901
902         status = open_file_ntcreate(conn, req, fname, &sbuf,
903                 access_mask,
904                 share_mode,
905                 create_disposition,
906                 create_options,
907                 open_attr,
908                 oplock_request,
909                 &smb_action, &fsp);
910
911         if (!NT_STATUS_IS_OK(status)) {
912                 if (open_was_deferred(req->mid)) {
913                         /* We have re-scheduled this call. */
914                         return;
915                 }
916                 reply_openerror(req, status);
917                 return;
918         }
919
920         size = get_file_size(sbuf);
921         fattr = dos_mode(conn,fname,&sbuf);
922         mtime = sbuf.st_mtime;
923         inode = sbuf.st_ino;
924         if (fattr & aDIR) {
925                 close_file(fsp,ERROR_CLOSE);
926                 reply_doserror(req, ERRDOS,ERRnoaccess);
927                 return;
928         }
929
930         /* Save the requested allocation size. */
931         /* Allocate space for the file if a size hint is supplied */
932         if ((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) {
933                 SMB_BIG_UINT allocation_size = (SMB_BIG_UINT)open_size;
934                 if (allocation_size && (allocation_size > (SMB_BIG_UINT)size)) {
935                         fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
936                         if (fsp->is_directory) {
937                                 close_file(fsp,ERROR_CLOSE);
938                                 /* Can't set allocation size on a directory. */
939                                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
940                                 return;
941                         }
942                         if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
943                                 close_file(fsp,ERROR_CLOSE);
944                                 reply_nterror(req, NT_STATUS_DISK_FULL);
945                                 return;
946                         }
947
948                         /* Adjust size here to return the right size in the reply.
949                            Windows does it this way. */
950                         size = fsp->initial_allocation_size;
951                 } else {
952                         fsp->initial_allocation_size = smb_roundup(fsp->conn,(SMB_BIG_UINT)size);
953                 }
954         }
955
956         if (ea_list && smb_action == FILE_WAS_CREATED) {
957                 status = set_ea(conn, fsp, fname, ea_list);
958                 if (!NT_STATUS_IS_OK(status)) {
959                         close_file(fsp,ERROR_CLOSE);
960                         reply_nterror(req, status);
961                         return;
962                 }
963         }
964
965         /* Realloc the size of parameters and data we will return */
966         *pparams = (char *)SMB_REALLOC(*pparams, 30);
967         if(*pparams == NULL ) {
968                 reply_nterror(req, NT_STATUS_NO_MEMORY);
969                 return;
970         }
971         params = *pparams;
972
973         SSVAL(params,0,fsp->fnum);
974         SSVAL(params,2,fattr);
975         srv_put_dos_date2(params,4, mtime);
976         SIVAL(params,8, (uint32)size);
977         SSVAL(params,12,deny_mode);
978         SSVAL(params,14,0); /* open_type - file or directory. */
979         SSVAL(params,16,0); /* open_state - only valid for IPC device. */
980
981         if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
982                 smb_action |= EXTENDED_OPLOCK_GRANTED;
983         }
984
985         SSVAL(params,18,smb_action);
986
987         /*
988          * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
989          */
990         SIVAL(params,20,inode);
991         SSVAL(params,24,0); /* Padding. */
992         if (flags & 8) {
993                 uint32 ea_size = estimate_ea_size(conn, fsp, fname);
994                 SIVAL(params, 26, ea_size);
995         } else {
996                 SIVAL(params, 26, 0);
997         }
998
999         /* Send the required number of replies */
1000         send_trans2_replies(req, params, 30, *ppdata, 0, max_data_bytes);
1001 }
1002
1003 /*********************************************************
1004  Routine to check if a given string matches exactly.
1005  as a special case a mask of "." does NOT match. That
1006  is required for correct wildcard semantics
1007  Case can be significant or not.
1008 **********************************************************/
1009
1010 static bool exact_match(connection_struct *conn,
1011                 const char *str,
1012                 const char *mask)
1013 {
1014         if (mask[0] == '.' && mask[1] == 0)
1015                 return False;
1016         if (conn->case_sensitive)
1017                 return strcmp(str,mask)==0;
1018         if (StrCaseCmp(str,mask) != 0) {
1019                 return False;
1020         }
1021         if (dptr_has_wild(conn->dirptr)) {
1022                 return False;
1023         }
1024         return True;
1025 }
1026
1027 /****************************************************************************
1028  Return the filetype for UNIX extensions.
1029 ****************************************************************************/
1030
1031 static uint32 unix_filetype(mode_t mode)
1032 {
1033         if(S_ISREG(mode))
1034                 return UNIX_TYPE_FILE;
1035         else if(S_ISDIR(mode))
1036                 return UNIX_TYPE_DIR;
1037 #ifdef S_ISLNK
1038         else if(S_ISLNK(mode))
1039                 return UNIX_TYPE_SYMLINK;
1040 #endif
1041 #ifdef S_ISCHR
1042         else if(S_ISCHR(mode))
1043                 return UNIX_TYPE_CHARDEV;
1044 #endif
1045 #ifdef S_ISBLK
1046         else if(S_ISBLK(mode))
1047                 return UNIX_TYPE_BLKDEV;
1048 #endif
1049 #ifdef S_ISFIFO
1050         else if(S_ISFIFO(mode))
1051                 return UNIX_TYPE_FIFO;
1052 #endif
1053 #ifdef S_ISSOCK
1054         else if(S_ISSOCK(mode))
1055                 return UNIX_TYPE_SOCKET;
1056 #endif
1057
1058         DEBUG(0,("unix_filetype: unknown filetype %u", (unsigned)mode));
1059         return UNIX_TYPE_UNKNOWN;
1060 }
1061
1062 /****************************************************************************
1063  Map wire perms onto standard UNIX permissions. Obey share restrictions.
1064 ****************************************************************************/
1065
1066 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1067
1068 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1069                                 SMB_STRUCT_STAT *psbuf,
1070                                 uint32 perms,
1071                                 enum perm_type ptype,
1072                                 mode_t *ret_perms)
1073 {
1074         mode_t ret = 0;
1075
1076         if (perms == SMB_MODE_NO_CHANGE) {
1077                 if (!VALID_STAT(*psbuf)) {
1078                         return NT_STATUS_INVALID_PARAMETER;
1079                 } else {
1080                         *ret_perms = psbuf->st_mode;
1081                         return NT_STATUS_OK;
1082                 }
1083         }
1084
1085         ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1086         ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1087         ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1088         ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1089         ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1090         ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1091         ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1092         ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1093         ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1094 #ifdef S_ISVTX
1095         ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1096 #endif
1097 #ifdef S_ISGID
1098         ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1099 #endif
1100 #ifdef S_ISUID
1101         ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1102 #endif
1103
1104         switch (ptype) {
1105         case PERM_NEW_FILE:
1106                 /* Apply mode mask */
1107                 ret &= lp_create_mask(SNUM(conn));
1108                 /* Add in force bits */
1109                 ret |= lp_force_create_mode(SNUM(conn));
1110                 break;
1111         case PERM_NEW_DIR:
1112                 ret &= lp_dir_mask(SNUM(conn));
1113                 /* Add in force bits */
1114                 ret |= lp_force_dir_mode(SNUM(conn));
1115                 break;
1116         case PERM_EXISTING_FILE:
1117                 /* Apply mode mask */
1118                 ret &= lp_security_mask(SNUM(conn));
1119                 /* Add in force bits */
1120                 ret |= lp_force_security_mode(SNUM(conn));
1121                 break;
1122         case PERM_EXISTING_DIR:
1123                 /* Apply mode mask */
1124                 ret &= lp_dir_security_mask(SNUM(conn));
1125                 /* Add in force bits */
1126                 ret |= lp_force_dir_security_mode(SNUM(conn));
1127                 break;
1128         }
1129
1130         *ret_perms = ret;
1131         return NT_STATUS_OK;
1132 }
1133
1134 /****************************************************************************
1135  Get a level dependent lanman2 dir entry.
1136 ****************************************************************************/
1137
1138 static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
1139                                 connection_struct *conn,
1140                                 uint16 flags2,
1141                                 const char *path_mask,
1142                                 uint32 dirtype,
1143                                 int info_level,
1144                                 int requires_resume_key,
1145                                 bool dont_descend,
1146                                 char **ppdata,
1147                                 char *base_data,
1148                                 char *end_data,
1149                                 int space_remaining,
1150                                 bool *out_of_space,
1151                                 bool *got_exact_match,
1152                                 int *last_entry_off,
1153                                 struct ea_list *name_list)
1154 {
1155         const char *dname;
1156         bool found = False;
1157         SMB_STRUCT_STAT sbuf;
1158         const char *mask = NULL;
1159         char *pathreal = NULL;
1160         const char *fname = NULL;
1161         char *p, *q, *pdata = *ppdata;
1162         uint32 reskey=0;
1163         long prev_dirpos=0;
1164         uint32 mode=0;
1165         SMB_OFF_T file_size = 0;
1166         SMB_BIG_UINT allocation_size = 0;
1167         uint32 len;
1168         struct timespec mdate_ts, adate_ts, create_date_ts;
1169         time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1170         char *nameptr;
1171         char *last_entry_ptr;
1172         bool was_8_3;
1173         uint32 nt_extmode; /* Used for NT connections instead of mode */
1174         bool needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
1175         bool check_mangled_names = lp_manglednames(conn->params);
1176         char mangled_name[13]; /* mangled 8.3 name. */
1177
1178         *out_of_space = False;
1179         *got_exact_match = False;
1180
1181         ZERO_STRUCT(mdate_ts);
1182         ZERO_STRUCT(adate_ts);
1183         ZERO_STRUCT(create_date_ts);
1184
1185         if (!conn->dirptr) {
1186                 return(False);
1187         }
1188
1189         p = strrchr_m(path_mask,'/');
1190         if(p != NULL) {
1191                 if(p[1] == '\0') {
1192                         mask = talloc_strdup(ctx,"*.*");
1193                 } else {
1194                         mask = p+1;
1195                 }
1196         } else {
1197                 mask = path_mask;
1198         }
1199
1200         while (!found) {
1201                 bool got_match;
1202                 bool ms_dfs_link = False;
1203
1204                 /* Needed if we run out of space */
1205                 long curr_dirpos = prev_dirpos = dptr_TellDir(conn->dirptr);
1206                 dname = dptr_ReadDirName(ctx,conn->dirptr,&curr_dirpos,&sbuf);
1207
1208                 /*
1209                  * Due to bugs in NT client redirectors we are not using
1210                  * resume keys any more - set them to zero.
1211                  * Check out the related comments in findfirst/findnext.
1212                  * JRA.
1213                  */
1214
1215                 reskey = 0;
1216
1217                 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %ld\n",
1218                         (long)conn->dirptr,curr_dirpos));
1219
1220                 if (!dname) {
1221                         return(False);
1222                 }
1223
1224                 /*
1225                  * fname may get mangled, dname is never mangled.
1226                  * Whenever we're accessing the filesystem we use
1227                  * pathreal which is composed from dname.
1228                  */
1229
1230                 pathreal = NULL;
1231                 fname = dname;
1232
1233                 /* Mangle fname if it's an illegal name. */
1234                 if (mangle_must_mangle(dname,conn->params)) {
1235                         if (!name_to_8_3(dname,mangled_name,True,conn->params)) {
1236                                 continue; /* Error - couldn't mangle. */
1237                         }
1238                         fname = mangled_name;
1239                 }
1240
1241                 if(!(got_match = *got_exact_match = exact_match(conn, fname, mask))) {
1242                         got_match = mask_match(fname, mask, conn->case_sensitive);
1243                 }
1244
1245                 if(!got_match && check_mangled_names &&
1246                    !mangle_is_8_3(fname, False, conn->params)) {
1247                         /*
1248                          * It turns out that NT matches wildcards against
1249                          * both long *and* short names. This may explain some
1250                          * of the wildcard wierdness from old DOS clients
1251                          * that some people have been seeing.... JRA.
1252                          */
1253                         /* Force the mangling into 8.3. */
1254                         if (!name_to_8_3( fname, mangled_name, False, conn->params)) {
1255                                 continue; /* Error - couldn't mangle. */
1256                         }
1257
1258                         if(!(got_match = *got_exact_match = exact_match(conn, mangled_name, mask))) {
1259                                 got_match = mask_match(mangled_name, mask, conn->case_sensitive);
1260                         }
1261                 }
1262
1263                 if (got_match) {
1264                         bool isdots = (ISDOT(dname) || ISDOTDOT(dname));
1265
1266                         if (dont_descend && !isdots) {
1267                                 continue;
1268                         }
1269
1270                         if (needslash) {
1271                                 pathreal = NULL;
1272                                 pathreal = talloc_asprintf(ctx,
1273                                         "%s/%s",
1274                                         conn->dirpath,
1275                                         dname);
1276                         } else {
1277                                 pathreal = talloc_asprintf(ctx,
1278                                         "%s%s",
1279                                         conn->dirpath,
1280                                         dname);
1281                         }
1282
1283                         if (!pathreal) {
1284                                 return False;
1285                         }
1286
1287                         if (INFO_LEVEL_IS_UNIX(info_level)) {
1288                                 if (SMB_VFS_LSTAT(conn,pathreal,&sbuf) != 0) {
1289                                         DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",
1290                                                 pathreal,strerror(errno)));
1291                                         TALLOC_FREE(pathreal);
1292                                         continue;
1293                                 }
1294                         } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,pathreal,&sbuf) != 0) {
1295                                 /* Needed to show the msdfs symlinks as
1296                                  * directories */
1297
1298                                 if(lp_host_msdfs() &&
1299                                    lp_msdfs_root(SNUM(conn)) &&
1300                                    ((ms_dfs_link = is_msdfs_link(conn, pathreal, &sbuf)) == True)) {
1301                                         DEBUG(5,("get_lanman2_dir_entry: Masquerading msdfs link %s "
1302                                                 "as a directory\n",
1303                                                 pathreal));
1304                                         sbuf.st_mode = (sbuf.st_mode & 0xFFF) | S_IFDIR;
1305
1306                                 } else {
1307
1308                                         DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
1309                                                 pathreal,strerror(errno)));
1310                                         TALLOC_FREE(pathreal);
1311                                         continue;
1312                                 }
1313                         }
1314
1315                         if (ms_dfs_link) {
1316                                 mode = dos_mode_msdfs(conn,pathreal,&sbuf);
1317                         } else {
1318                                 mode = dos_mode(conn,pathreal,&sbuf);
1319                         }
1320
1321                         if (!dir_check_ftype(conn,mode,dirtype)) {
1322                                 DEBUG(5,("get_lanman2_dir_entry: [%s] attribs didn't match %x\n",fname,dirtype));
1323                                 TALLOC_FREE(pathreal);
1324                                 continue;
1325                         }
1326
1327                         if (!(mode & aDIR)) {
1328                                 file_size = get_file_size(sbuf);
1329                         }
1330                         allocation_size = get_allocation_size(conn,NULL,&sbuf);
1331
1332                         mdate_ts = get_mtimespec(&sbuf);
1333                         adate_ts = get_atimespec(&sbuf);
1334                         create_date_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
1335
1336                         if (lp_dos_filetime_resolution(SNUM(conn))) {
1337                                 dos_filetime_timespec(&create_date_ts);
1338                                 dos_filetime_timespec(&mdate_ts);
1339                                 dos_filetime_timespec(&adate_ts);
1340                         }
1341
1342                         create_date = convert_timespec_to_time_t(create_date_ts);
1343                         mdate = convert_timespec_to_time_t(mdate_ts);
1344                         adate = convert_timespec_to_time_t(adate_ts);
1345
1346                         DEBUG(5,("get_lanman2_dir_entry: found %s fname=%s\n",pathreal,fname));
1347
1348                         found = True;
1349
1350                         dptr_DirCacheAdd(conn->dirptr, dname, curr_dirpos);
1351                 }
1352         }
1353
1354         p = pdata;
1355         last_entry_ptr = p;
1356
1357         nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
1358
1359         switch (info_level) {
1360                 case SMB_FIND_INFO_STANDARD:
1361                         DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1362                         if(requires_resume_key) {
1363                                 SIVAL(p,0,reskey);
1364                                 p += 4;
1365                         }
1366                         srv_put_dos_date2(p,0,create_date);
1367                         srv_put_dos_date2(p,4,adate);
1368                         srv_put_dos_date2(p,8,mdate);
1369                         SIVAL(p,12,(uint32)file_size);
1370                         SIVAL(p,16,(uint32)allocation_size);
1371                         SSVAL(p,20,mode);
1372                         p += 23;
1373                         nameptr = p;
1374                         p += align_string(pdata, p, 0);
1375                         len = srvstr_push(base_data, flags2, p,
1376                                           fname, PTR_DIFF(end_data, p),
1377                                           STR_TERMINATE);
1378                         if (flags2 & FLAGS2_UNICODE_STRINGS) {
1379                                 if (len > 2) {
1380                                         SCVAL(nameptr, -1, len - 2);
1381                                 } else {
1382                                         SCVAL(nameptr, -1, 0);
1383                                 }
1384                         } else {
1385                                 if (len > 1) {
1386                                         SCVAL(nameptr, -1, len - 1);
1387                                 } else {
1388                                         SCVAL(nameptr, -1, 0);
1389                                 }
1390                         }
1391                         p += len;
1392                         break;
1393
1394                 case SMB_FIND_EA_SIZE:
1395                         DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n"));
1396                         if(requires_resume_key) {
1397                                 SIVAL(p,0,reskey);
1398                                 p += 4;
1399                         }
1400                         srv_put_dos_date2(p,0,create_date);
1401                         srv_put_dos_date2(p,4,adate);
1402                         srv_put_dos_date2(p,8,mdate);
1403                         SIVAL(p,12,(uint32)file_size);
1404                         SIVAL(p,16,(uint32)allocation_size);
1405                         SSVAL(p,20,mode);
1406                         {
1407                                 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1408                                 SIVAL(p,22,ea_size); /* Extended attributes */
1409                         }
1410                         p += 27;
1411                         nameptr = p - 1;
1412                         len = srvstr_push(base_data, flags2,
1413                                           p, fname, PTR_DIFF(end_data, p),
1414                                           STR_TERMINATE | STR_NOALIGN);
1415                         if (flags2 & FLAGS2_UNICODE_STRINGS) {
1416                                 if (len > 2) {
1417                                         len -= 2;
1418                                 } else {
1419                                         len = 0;
1420                                 }
1421                         } else {
1422                                 if (len > 1) {
1423                                         len -= 1;
1424                                 } else {
1425                                         len = 0;
1426                                 }
1427                         }
1428                         SCVAL(nameptr,0,len);
1429                         p += len;
1430                         SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1431                         break;
1432
1433                 case SMB_FIND_EA_LIST:
1434                 {
1435                         struct ea_list *file_list = NULL;
1436                         size_t ea_len = 0;
1437
1438                         DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n"));
1439                         if (!name_list) {
1440                                 return False;
1441                         }
1442                         if(requires_resume_key) {
1443                                 SIVAL(p,0,reskey);
1444                                 p += 4;
1445                         }
1446                         srv_put_dos_date2(p,0,create_date);
1447                         srv_put_dos_date2(p,4,adate);
1448                         srv_put_dos_date2(p,8,mdate);
1449                         SIVAL(p,12,(uint32)file_size);
1450                         SIVAL(p,16,(uint32)allocation_size);
1451                         SSVAL(p,20,mode);
1452                         p += 22; /* p now points to the EA area. */
1453
1454                         file_list = get_ea_list_from_file(ctx, conn, NULL, pathreal, &ea_len);
1455                         name_list = ea_list_union(name_list, file_list, &ea_len);
1456
1457                         /* We need to determine if this entry will fit in the space available. */
1458                         /* Max string size is 255 bytes. */
1459                         if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1460                                 /* Move the dirptr back to prev_dirpos */
1461                                 dptr_SeekDir(conn->dirptr, prev_dirpos);
1462                                 *out_of_space = True;
1463                                 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1464                                 return False; /* Not finished - just out of space */
1465                         }
1466
1467                         /* Push the ea_data followed by the name. */
1468                         p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1469                         nameptr = p;
1470                         len = srvstr_push(base_data, flags2,
1471                                           p + 1, fname, PTR_DIFF(end_data, p+1),
1472                                           STR_TERMINATE | STR_NOALIGN);
1473                         if (flags2 & FLAGS2_UNICODE_STRINGS) {
1474                                 if (len > 2) {
1475                                         len -= 2;
1476                                 } else {
1477                                         len = 0;
1478                                 }
1479                         } else {
1480                                 if (len > 1) {
1481                                         len -= 1;
1482                                 } else {
1483                                         len = 0;
1484                                 }
1485                         }
1486                         SCVAL(nameptr,0,len);
1487                         p += len + 1;
1488                         SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1489                         break;
1490                 }
1491
1492                 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1493                         DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1494                         was_8_3 = mangle_is_8_3(fname, True, conn->params);
1495                         p += 4;
1496                         SIVAL(p,0,reskey); p += 4;
1497                         put_long_date_timespec(p,create_date_ts); p += 8;
1498                         put_long_date_timespec(p,adate_ts); p += 8;
1499                         put_long_date_timespec(p,mdate_ts); p += 8;
1500                         put_long_date_timespec(p,mdate_ts); p += 8;
1501                         SOFF_T(p,0,file_size); p += 8;
1502                         SOFF_T(p,0,allocation_size); p += 8;
1503                         SIVAL(p,0,nt_extmode); p += 4;
1504                         q = p; p += 4; /* q is placeholder for name length. */
1505                         {
1506                                 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1507                                 SIVAL(p,0,ea_size); /* Extended attributes */
1508                                 p += 4;
1509                         }
1510                         /* Clear the short name buffer. This is
1511                          * IMPORTANT as not doing so will trigger
1512                          * a Win2k client bug. JRA.
1513                          */
1514                         if (!was_8_3 && check_mangled_names) {
1515                                 if (!name_to_8_3(fname,mangled_name,True,
1516                                                    conn->params)) {
1517                                         /* Error - mangle failed ! */
1518                                         memset(mangled_name,'\0',12);
1519                                 }
1520                                 mangled_name[12] = 0;
1521                                 len = srvstr_push(base_data, flags2,
1522                                                   p+2, mangled_name, 24,
1523                                                   STR_UPPER|STR_UNICODE);
1524                                 if (len < 24) {
1525                                         memset(p + 2 + len,'\0',24 - len);
1526                                 }
1527                                 SSVAL(p, 0, len);
1528                         } else {
1529                                 memset(p,'\0',26);
1530                         }
1531                         p += 2 + 24;
1532                         len = srvstr_push(base_data, flags2, p,
1533                                           fname, PTR_DIFF(end_data, p),
1534                                           STR_TERMINATE_ASCII);
1535                         SIVAL(q,0,len);
1536                         p += len;
1537                         SIVAL(p,0,0); /* Ensure any padding is null. */
1538                         len = PTR_DIFF(p, pdata);
1539                         len = (len + 3) & ~3;
1540                         SIVAL(pdata,0,len);
1541                         p = pdata + len;
1542                         break;
1543
1544                 case SMB_FIND_FILE_DIRECTORY_INFO:
1545                         DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1546                         p += 4;
1547                         SIVAL(p,0,reskey); p += 4;
1548                         put_long_date_timespec(p,create_date_ts); p += 8;
1549                         put_long_date_timespec(p,adate_ts); p += 8;
1550                         put_long_date_timespec(p,mdate_ts); p += 8;
1551                         put_long_date_timespec(p,mdate_ts); p += 8;
1552                         SOFF_T(p,0,file_size); p += 8;
1553                         SOFF_T(p,0,allocation_size); p += 8;
1554                         SIVAL(p,0,nt_extmode); p += 4;
1555                         len = srvstr_push(base_data, flags2,
1556                                           p + 4, fname, PTR_DIFF(end_data, p+4),
1557                                           STR_TERMINATE_ASCII);
1558                         SIVAL(p,0,len);
1559                         p += 4 + len;
1560                         SIVAL(p,0,0); /* Ensure any padding is null. */
1561                         len = PTR_DIFF(p, pdata);
1562                         len = (len + 3) & ~3;
1563                         SIVAL(pdata,0,len);
1564                         p = pdata + len;
1565                         break;
1566
1567                 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1568                         DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1569                         p += 4;
1570                         SIVAL(p,0,reskey); p += 4;
1571                         put_long_date_timespec(p,create_date_ts); p += 8;
1572                         put_long_date_timespec(p,adate_ts); p += 8;
1573                         put_long_date_timespec(p,mdate_ts); p += 8;
1574                         put_long_date_timespec(p,mdate_ts); p += 8;
1575                         SOFF_T(p,0,file_size); p += 8;
1576                         SOFF_T(p,0,allocation_size); p += 8;
1577                         SIVAL(p,0,nt_extmode); p += 4;
1578                         q = p; p += 4; /* q is placeholder for name length. */
1579                         {
1580                                 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1581                                 SIVAL(p,0,ea_size); /* Extended attributes */
1582                                 p +=4;
1583                         }
1584                         len = srvstr_push(base_data, flags2, p,
1585                                           fname, PTR_DIFF(end_data, p),
1586                                           STR_TERMINATE_ASCII);
1587                         SIVAL(q, 0, len);
1588                         p += len;
1589
1590                         SIVAL(p,0,0); /* Ensure any padding is null. */
1591                         len = PTR_DIFF(p, pdata);
1592                         len = (len + 3) & ~3;
1593                         SIVAL(pdata,0,len);
1594                         p = pdata + len;
1595                         break;
1596
1597                 case SMB_FIND_FILE_NAMES_INFO:
1598                         DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1599                         p += 4;
1600                         SIVAL(p,0,reskey); p += 4;
1601                         p += 4;
1602                         /* this must *not* be null terminated or w2k gets in a loop trying to set an
1603                            acl on a dir (tridge) */
1604                         len = srvstr_push(base_data, flags2, p,
1605                                           fname, PTR_DIFF(end_data, p),
1606                                           STR_TERMINATE_ASCII);
1607                         SIVAL(p, -4, len);
1608                         p += len;
1609                         SIVAL(p,0,0); /* Ensure any padding is null. */
1610                         len = PTR_DIFF(p, pdata);
1611                         len = (len + 3) & ~3;
1612                         SIVAL(pdata,0,len);
1613                         p = pdata + len;
1614                         break;
1615
1616                 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1617                         DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1618                         p += 4;
1619                         SIVAL(p,0,reskey); p += 4;
1620                         put_long_date_timespec(p,create_date_ts); p += 8;
1621                         put_long_date_timespec(p,adate_ts); p += 8;
1622                         put_long_date_timespec(p,mdate_ts); p += 8;
1623                         put_long_date_timespec(p,mdate_ts); p += 8;
1624                         SOFF_T(p,0,file_size); p += 8;
1625                         SOFF_T(p,0,allocation_size); p += 8;
1626                         SIVAL(p,0,nt_extmode); p += 4;
1627                         q = p; p += 4; /* q is placeholder for name length. */
1628                         {
1629                                 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1630                                 SIVAL(p,0,ea_size); /* Extended attributes */
1631                                 p +=4;
1632                         }
1633                         SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1634                         SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1635                         SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1636                         len = srvstr_push(base_data, flags2, p,
1637                                           fname, PTR_DIFF(end_data, p),
1638                                           STR_TERMINATE_ASCII);
1639                         SIVAL(q, 0, len);
1640                         p += len; 
1641                         SIVAL(p,0,0); /* Ensure any padding is null. */
1642                         len = PTR_DIFF(p, pdata);
1643                         len = (len + 3) & ~3;
1644                         SIVAL(pdata,0,len);
1645                         p = pdata + len;
1646                         break;
1647
1648                 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1649                         DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1650                         was_8_3 = mangle_is_8_3(fname, True, conn->params);
1651                         p += 4;
1652                         SIVAL(p,0,reskey); p += 4;
1653                         put_long_date_timespec(p,create_date_ts); p += 8;
1654                         put_long_date_timespec(p,adate_ts); p += 8;
1655                         put_long_date_timespec(p,mdate_ts); p += 8;
1656                         put_long_date_timespec(p,mdate_ts); p += 8;
1657                         SOFF_T(p,0,file_size); p += 8;
1658                         SOFF_T(p,0,allocation_size); p += 8;
1659                         SIVAL(p,0,nt_extmode); p += 4;
1660                         q = p; p += 4; /* q is placeholder for name length */
1661                         {
1662                                 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1663                                 SIVAL(p,0,ea_size); /* Extended attributes */
1664                                 p +=4;
1665                         }
1666                         /* Clear the short name buffer. This is
1667                          * IMPORTANT as not doing so will trigger
1668                          * a Win2k client bug. JRA.
1669                          */
1670                         if (!was_8_3 && check_mangled_names) {
1671                                 if (!name_to_8_3(fname,mangled_name,True,
1672                                                 conn->params)) {
1673                                         /* Error - mangle failed ! */
1674                                         memset(mangled_name,'\0',12);
1675                                 }
1676                                 mangled_name[12] = 0;
1677                                 len = srvstr_push(base_data, flags2,
1678                                                   p+2, mangled_name, 24,
1679                                                   STR_UPPER|STR_UNICODE);
1680                                 SSVAL(p, 0, len);
1681                                 if (len < 24) {
1682                                         memset(p + 2 + len,'\0',24 - len);
1683                                 }
1684                                 SSVAL(p, 0, len);
1685                         } else {
1686                                 memset(p,'\0',26);
1687                         }
1688                         p += 26;
1689                         SSVAL(p,0,0); p += 2; /* Reserved ? */
1690                         SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1691                         SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1692                         len = srvstr_push(base_data, flags2, p,
1693                                           fname, PTR_DIFF(end_data, p),
1694                                           STR_TERMINATE_ASCII);
1695                         SIVAL(q,0,len);
1696                         p += len;
1697                         SIVAL(p,0,0); /* Ensure any padding is null. */
1698                         len = PTR_DIFF(p, pdata);
1699                         len = (len + 3) & ~3;
1700                         SIVAL(pdata,0,len);
1701                         p = pdata + len;
1702                         break;
1703
1704                 /* CIFS UNIX Extension. */
1705
1706                 case SMB_FIND_FILE_UNIX:
1707                 case SMB_FIND_FILE_UNIX_INFO2:
1708                         p+= 4;
1709                         SIVAL(p,0,reskey); p+= 4;    /* Used for continuing search. */
1710
1711                         /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1712
1713                         if (info_level == SMB_FIND_FILE_UNIX) {
1714                                 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1715                                 p = store_file_unix_basic(conn, p,
1716                                                         NULL, &sbuf);
1717                                 len = srvstr_push(base_data, flags2, p,
1718                                                   fname, PTR_DIFF(end_data, p),
1719                                                   STR_TERMINATE);
1720                         } else {
1721                                 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
1722                                 p = store_file_unix_basic_info2(conn, p,
1723                                                         NULL, &sbuf);
1724                                 nameptr = p;
1725                                 p += 4;
1726                                 len = srvstr_push(base_data, flags2, p, fname,
1727                                                   PTR_DIFF(end_data, p), 0);
1728                                 SIVAL(nameptr, 0, len);
1729                         }
1730
1731                         p += len;
1732                         SIVAL(p,0,0); /* Ensure any padding is null. */
1733
1734                         len = PTR_DIFF(p, pdata);
1735                         len = (len + 3) & ~3;
1736                         SIVAL(pdata,0,len);     /* Offset from this structure to the beginning of the next one */
1737                         p = pdata + len;
1738                         /* End of SMB_QUERY_FILE_UNIX_BASIC */
1739
1740                         break;
1741
1742                 default:
1743                         return(False);
1744         }
1745
1746
1747         if (PTR_DIFF(p,pdata) > space_remaining) {
1748                 /* Move the dirptr back to prev_dirpos */
1749                 dptr_SeekDir(conn->dirptr, prev_dirpos);
1750                 *out_of_space = True;
1751                 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1752                 return False; /* Not finished - just out of space */
1753         }
1754
1755         /* Setup the last entry pointer, as an offset from base_data */
1756         *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
1757         /* Advance the data pointer to the next slot */
1758         *ppdata = p;
1759
1760         return(found);
1761 }
1762
1763 /****************************************************************************
1764  Reply to a TRANS2_FINDFIRST.
1765 ****************************************************************************/
1766
1767 static void call_trans2findfirst(connection_struct *conn,
1768                                  struct smb_request *req,
1769                                  char **pparams, int total_params,
1770                                  char **ppdata, int total_data,
1771                                  unsigned int max_data_bytes)
1772 {
1773         /* We must be careful here that we don't return more than the
1774                 allowed number of data bytes. If this means returning fewer than
1775                 maxentries then so be it. We assume that the redirector has
1776                 enough room for the fixed number of parameter bytes it has
1777                 requested. */
1778         char *params = *pparams;
1779         char *pdata = *ppdata;
1780         char *data_end;
1781         uint32 dirtype;
1782         int maxentries;
1783         uint16 findfirst_flags;
1784         bool close_after_first;
1785         bool close_if_end;
1786         bool requires_resume_key;
1787         int info_level;
1788         char *directory = NULL;
1789         const char *mask = NULL;
1790         char *p;
1791         int last_entry_off=0;
1792         int dptr_num = -1;
1793         int numentries = 0;
1794         int i;
1795         bool finished = False;
1796         bool dont_descend = False;
1797         bool out_of_space = False;
1798         int space_remaining;
1799         bool mask_contains_wcard = False;
1800         SMB_STRUCT_STAT sbuf;
1801         struct ea_list *ea_list = NULL;
1802         NTSTATUS ntstatus = NT_STATUS_OK;
1803         TALLOC_CTX *ctx = talloc_tos();
1804
1805         if (total_params < 13) {
1806                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1807                 return;
1808         }
1809
1810         dirtype = SVAL(params,0);
1811         maxentries = SVAL(params,2);
1812         findfirst_flags = SVAL(params,4);
1813         close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
1814         close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1815         requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1816         info_level = SVAL(params,6);
1817
1818         DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
1819 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
1820                 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
1821                 info_level, max_data_bytes));
1822
1823         if (!maxentries) {
1824                 /* W2K3 seems to treat zero as 1. */
1825                 maxentries = 1;
1826         }
1827  
1828         switch (info_level) {
1829                 case SMB_FIND_INFO_STANDARD:
1830                 case SMB_FIND_EA_SIZE:
1831                 case SMB_FIND_EA_LIST:
1832                 case SMB_FIND_FILE_DIRECTORY_INFO:
1833                 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1834                 case SMB_FIND_FILE_NAMES_INFO:
1835                 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1836                 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1837                 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1838                         break;
1839                 case SMB_FIND_FILE_UNIX:
1840                 case SMB_FIND_FILE_UNIX_INFO2:
1841                         if (!lp_unix_extensions()) {
1842                                 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1843                                 return;
1844                         }
1845                         break;
1846                 default:
1847                         reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1848                         return;
1849         }
1850
1851         srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
1852                               params+12, total_params - 12,
1853                               STR_TERMINATE, &ntstatus, &mask_contains_wcard);
1854         if (!NT_STATUS_IS_OK(ntstatus)) {
1855                 reply_nterror(req, ntstatus);
1856                 return;
1857         }
1858
1859         ntstatus = resolve_dfspath_wcard(ctx, conn,
1860                         req->flags2 & FLAGS2_DFS_PATHNAMES,
1861                         directory,
1862                         &directory,
1863                         &mask_contains_wcard);
1864         if (!NT_STATUS_IS_OK(ntstatus)) {
1865                 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
1866                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1867                                         ERRSRV, ERRbadpath);
1868                         return;
1869                 }
1870                 reply_nterror(req, ntstatus);
1871                 return;
1872         }
1873
1874         ntstatus = unix_convert(ctx, conn, directory, True, &directory, NULL, &sbuf);
1875         if (!NT_STATUS_IS_OK(ntstatus)) {
1876                 reply_nterror(req, ntstatus);
1877                 return;
1878         }
1879
1880         ntstatus = check_name(conn, directory);
1881         if (!NT_STATUS_IS_OK(ntstatus)) {
1882                 reply_nterror(req, ntstatus);
1883                 return;
1884         }
1885
1886         p = strrchr_m(directory,'/');
1887         if(p == NULL) {
1888                 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
1889                 if((directory[0] == '.') && (directory[1] == '\0')) {
1890                         mask = "*";
1891                         mask_contains_wcard = True;
1892                 } else {
1893                         mask = directory;
1894                 }
1895                 directory = talloc_strdup(talloc_tos(), "./");
1896                 if (!directory) {
1897                         reply_nterror(req, NT_STATUS_NO_MEMORY);
1898                         return;
1899                 }
1900         } else {
1901                 mask = p+1;
1902                 *p = 0;
1903         }
1904
1905         DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
1906
1907         if (info_level == SMB_FIND_EA_LIST) {
1908                 uint32 ea_size;
1909
1910                 if (total_data < 4) {
1911                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1912                         return;
1913                 }
1914
1915                 ea_size = IVAL(pdata,0);
1916                 if (ea_size != total_data) {
1917                         DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
1918 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
1919                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1920                         return;
1921                 }
1922
1923                 if (!lp_ea_support(SNUM(conn))) {
1924                         reply_doserror(req, ERRDOS, ERReasnotsupported);
1925                         return;
1926                 }
1927
1928                 /* Pull out the list of names. */
1929                 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
1930                 if (!ea_list) {
1931                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1932                         return;
1933                 }
1934         }
1935
1936         *ppdata = (char *)SMB_REALLOC(
1937                 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1938         if(*ppdata == NULL ) {
1939                 reply_nterror(req, NT_STATUS_NO_MEMORY);
1940                 return;
1941         }
1942         pdata = *ppdata;
1943         data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
1944
1945         /* Realloc the params space */
1946         *pparams = (char *)SMB_REALLOC(*pparams, 10);
1947         if (*pparams == NULL) {
1948                 reply_nterror(req, NT_STATUS_NO_MEMORY);
1949                 return;
1950         }
1951         params = *pparams;
1952
1953         /* Save the wildcard match and attribs we are using on this directory - 
1954                 needed as lanman2 assumes these are being saved between calls */
1955
1956         ntstatus = dptr_create(conn,
1957                                 directory,
1958                                 False,
1959                                 True,
1960                                 req->smbpid,
1961                                 mask,
1962                                 mask_contains_wcard,
1963                                 dirtype,
1964                                 &conn->dirptr);
1965
1966         if (!NT_STATUS_IS_OK(ntstatus)) {
1967                 reply_nterror(req, ntstatus);
1968                 return;
1969         }
1970
1971         dptr_num = dptr_dnum(conn->dirptr);
1972         DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
1973
1974         /* We don't need to check for VOL here as this is returned by
1975                 a different TRANS2 call. */
1976
1977         DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
1978         if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
1979                 dont_descend = True;
1980
1981         p = pdata;
1982         space_remaining = max_data_bytes;
1983         out_of_space = False;
1984
1985         for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
1986                 bool got_exact_match = False;
1987
1988                 /* this is a heuristic to avoid seeking the dirptr except when 
1989                         absolutely necessary. It allows for a filename of about 40 chars */
1990                 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
1991                         out_of_space = True;
1992                         finished = False;
1993                 } else {
1994                         TALLOC_CTX *sub_ctx = talloc_stackframe();
1995
1996                         finished = !get_lanman2_dir_entry(sub_ctx,
1997                                         conn,
1998                                         req->flags2,
1999                                         mask,dirtype,info_level,
2000                                         requires_resume_key,dont_descend,
2001                                         &p,pdata,data_end,
2002                                         space_remaining, &out_of_space,
2003                                         &got_exact_match,
2004                                         &last_entry_off, ea_list);
2005
2006                         TALLOC_FREE(sub_ctx);
2007                 }
2008
2009                 if (finished && out_of_space)
2010                         finished = False;
2011
2012                 if (!finished && !out_of_space)
2013                         numentries++;
2014
2015                 /*
2016                  * As an optimisation if we know we aren't looking
2017                  * for a wildcard name (ie. the name matches the wildcard exactly)
2018                  * then we can finish on any (first) match.
2019                  * This speeds up large directory searches. JRA.
2020                  */
2021
2022                 if(got_exact_match)
2023                         finished = True;
2024
2025                 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2026         }
2027
2028         /* Check if we can close the dirptr */
2029         if(close_after_first || (finished && close_if_end)) {
2030                 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2031                 dptr_close(&dptr_num);
2032         }
2033
2034         /*
2035          * If there are no matching entries we must return ERRDOS/ERRbadfile -
2036          * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2037          * the protocol level is less than NT1. Tested with smbclient. JRA.
2038          * This should fix the OS/2 client bug #2335.
2039          */
2040
2041         if(numentries == 0) {
2042                 dptr_close(&dptr_num);
2043                 if (Protocol < PROTOCOL_NT1) {
2044                         reply_doserror(req, ERRDOS, ERRnofiles);
2045                         return;
2046                 } else {
2047                         reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2048                                         ERRDOS, ERRbadfile);
2049                         return;
2050                 }
2051         }
2052
2053         /* At this point pdata points to numentries directory entries. */
2054
2055         /* Set up the return parameter block */
2056         SSVAL(params,0,dptr_num);
2057         SSVAL(params,2,numentries);
2058         SSVAL(params,4,finished);
2059         SSVAL(params,6,0); /* Never an EA error */
2060         SSVAL(params,8,last_entry_off);
2061
2062         send_trans2_replies(req, params, 10, pdata, PTR_DIFF(p,pdata),
2063                             max_data_bytes);
2064
2065         if ((! *directory) && dptr_path(dptr_num)) {
2066                 directory = talloc_strdup(talloc_tos(),dptr_path(dptr_num));
2067                 if (!directory) {
2068                         reply_nterror(req, NT_STATUS_NO_MEMORY);
2069                 }
2070         }
2071
2072         DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2073                 smb_fn_name(CVAL(req->inbuf,smb_com)),
2074                 mask, directory, dirtype, numentries ) );
2075
2076         /*
2077          * Force a name mangle here to ensure that the
2078          * mask as an 8.3 name is top of the mangled cache.
2079          * The reasons for this are subtle. Don't remove
2080          * this code unless you know what you are doing
2081          * (see PR#13758). JRA.
2082          */
2083
2084         if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2085                 char mangled_name[13];
2086                 name_to_8_3(mask, mangled_name, True, conn->params);
2087         }
2088
2089         return;
2090 }
2091
2092 /****************************************************************************
2093  Reply to a TRANS2_FINDNEXT.
2094 ****************************************************************************/
2095
2096 static void call_trans2findnext(connection_struct *conn,
2097                                 struct smb_request *req,
2098                                 char **pparams, int total_params,
2099                                 char **ppdata, int total_data,
2100                                 unsigned int max_data_bytes)
2101 {
2102         /* We must be careful here that we don't return more than the
2103                 allowed number of data bytes. If this means returning fewer than
2104                 maxentries then so be it. We assume that the redirector has
2105                 enough room for the fixed number of parameter bytes it has
2106                 requested. */
2107         char *params = *pparams;
2108         char *pdata = *ppdata;
2109         char *data_end;
2110         int dptr_num;
2111         int maxentries;
2112         uint16 info_level;
2113         uint32 resume_key;
2114         uint16 findnext_flags;
2115         bool close_after_request;
2116         bool close_if_end;
2117         bool requires_resume_key;
2118         bool continue_bit;
2119         bool mask_contains_wcard = False;
2120         char *resume_name = NULL;
2121         const char *mask = NULL;
2122         const char *directory = NULL;
2123         char *p = NULL;
2124         uint16 dirtype;
2125         int numentries = 0;
2126         int i, last_entry_off=0;
2127         bool finished = False;
2128         bool dont_descend = False;
2129         bool out_of_space = False;
2130         int space_remaining;
2131         struct ea_list *ea_list = NULL;
2132         NTSTATUS ntstatus = NT_STATUS_OK;
2133         TALLOC_CTX *ctx = talloc_tos();
2134
2135         if (total_params < 13) {
2136                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2137                 return;
2138         }
2139
2140         dptr_num = SVAL(params,0);
2141         maxentries = SVAL(params,2);
2142         info_level = SVAL(params,4);
2143         resume_key = IVAL(params,6);
2144         findnext_flags = SVAL(params,10);
2145         close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2146         close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2147         requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2148         continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2149
2150         srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2151                               params+12,
2152                               total_params - 12, STR_TERMINATE, &ntstatus,
2153                               &mask_contains_wcard);
2154         if (!NT_STATUS_IS_OK(ntstatus)) {
2155                 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2156                    complain (it thinks we're asking for the directory above the shared
2157                    path or an invalid name). Catch this as the resume name is only compared, never used in
2158                    a file access. JRA. */
2159                 srvstr_pull_talloc(ctx, params, req->flags2,
2160                                 &resume_name, params+12,
2161                                 total_params - 12,
2162                                 STR_TERMINATE);
2163
2164                 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2165                         reply_nterror(req, ntstatus);
2166                         return;
2167                 }
2168         }
2169
2170         DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2171 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2172 resume_key = %d resume name = %s continue=%d level = %d\n",
2173                 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end, 
2174                 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
2175
2176         if (!maxentries) {
2177                 /* W2K3 seems to treat zero as 1. */
2178                 maxentries = 1;
2179         }
2180
2181         switch (info_level) {
2182                 case SMB_FIND_INFO_STANDARD:
2183                 case SMB_FIND_EA_SIZE:
2184                 case SMB_FIND_EA_LIST:
2185                 case SMB_FIND_FILE_DIRECTORY_INFO:
2186                 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2187                 case SMB_FIND_FILE_NAMES_INFO:
2188                 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2189                 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2190                 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2191                         break;
2192                 case SMB_FIND_FILE_UNIX:
2193                 case SMB_FIND_FILE_UNIX_INFO2:
2194                         if (!lp_unix_extensions()) {
2195                                 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2196                                 return;
2197                         }
2198                         break;
2199                 default:
2200                         reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2201                         return;
2202         }
2203
2204         if (info_level == SMB_FIND_EA_LIST) {
2205                 uint32 ea_size;
2206
2207                 if (total_data < 4) {
2208                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2209                         return;
2210                 }
2211
2212                 ea_size = IVAL(pdata,0);
2213                 if (ea_size != total_data) {
2214                         DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2215 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2216                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2217                         return;
2218                 }
2219
2220                 if (!lp_ea_support(SNUM(conn))) {
2221                         reply_doserror(req, ERRDOS, ERReasnotsupported);
2222                         return;
2223                 }
2224
2225                 /* Pull out the list of names. */
2226                 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2227                 if (!ea_list) {
2228                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2229                         return;
2230                 }
2231         }
2232
2233         *ppdata = (char *)SMB_REALLOC(
2234                 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2235         if(*ppdata == NULL) {
2236                 reply_nterror(req, NT_STATUS_NO_MEMORY);
2237                 return;
2238         }
2239
2240         pdata = *ppdata;
2241         data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2242
2243         /* Realloc the params space */
2244         *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2245         if(*pparams == NULL ) {
2246                 reply_nterror(req, NT_STATUS_NO_MEMORY);
2247                 return;
2248         }
2249
2250         params = *pparams;
2251
2252         /* Check that the dptr is valid */
2253         if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num))) {
2254                 reply_doserror(req, ERRDOS, ERRnofiles);
2255                 return;
2256         }
2257
2258         string_set(&conn->dirpath,dptr_path(dptr_num));
2259
2260         /* Get the wildcard mask from the dptr */
2261         if((p = dptr_wcard(dptr_num))== NULL) {
2262                 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2263                 reply_doserror(req, ERRDOS, ERRnofiles);
2264                 return;
2265         }
2266
2267         mask = p;
2268         directory = conn->dirpath;
2269
2270         /* Get the attr mask from the dptr */
2271         dirtype = dptr_attr(dptr_num);
2272
2273         DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2274                 dptr_num, mask, dirtype,
2275                 (long)conn->dirptr,
2276                 dptr_TellDir(conn->dirptr)));
2277
2278         /* We don't need to check for VOL here as this is returned by
2279                 a different TRANS2 call. */
2280
2281         DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
2282         if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2283                 dont_descend = True;
2284
2285         p = pdata;
2286         space_remaining = max_data_bytes;
2287         out_of_space = False;
2288
2289         /*
2290          * Seek to the correct position. We no longer use the resume key but
2291          * depend on the last file name instead.
2292          */
2293
2294         if(*resume_name && !continue_bit) {
2295                 SMB_STRUCT_STAT st;
2296
2297                 long current_pos = 0;
2298                 /*
2299                  * Remember, name_to_8_3 is called by
2300                  * get_lanman2_dir_entry(), so the resume name
2301                  * could be mangled. Ensure we check the unmangled name.
2302                  */
2303
2304                 if (mangle_is_mangled(resume_name, conn->params)) {
2305                         char *new_resume_name = NULL;
2306                         mangle_lookup_name_from_8_3(ctx,
2307                                                 resume_name,
2308                                                 &new_resume_name,
2309                                                 conn->params);
2310                         if (new_resume_name) {
2311                                 resume_name = new_resume_name;
2312                         }
2313                 }
2314
2315                 /*
2316                  * Fix for NT redirector problem triggered by resume key indexes
2317                  * changing between directory scans. We now return a resume key of 0
2318                  * and instead look for the filename to continue from (also given
2319                  * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2320                  * findfirst/findnext (as is usual) then the directory pointer
2321                  * should already be at the correct place.
2322                  */
2323
2324                 finished = !dptr_SearchDir(conn->dirptr, resume_name, &current_pos, &st);
2325         } /* end if resume_name && !continue_bit */
2326
2327         for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2328                 bool got_exact_match = False;
2329
2330                 /* this is a heuristic to avoid seeking the dirptr except when 
2331                         absolutely necessary. It allows for a filename of about 40 chars */
2332                 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2333                         out_of_space = True;
2334                         finished = False;
2335                 } else {
2336                         TALLOC_CTX *sub_ctx = talloc_stackframe();
2337
2338                         finished = !get_lanman2_dir_entry(sub_ctx,
2339                                                 conn,
2340                                                 req->flags2,
2341                                                 mask,dirtype,info_level,
2342                                                 requires_resume_key,dont_descend,
2343                                                 &p,pdata,data_end,
2344                                                 space_remaining, &out_of_space,
2345                                                 &got_exact_match,
2346                                                 &last_entry_off, ea_list);
2347
2348                         TALLOC_FREE(sub_ctx);
2349                 }
2350
2351                 if (finished && out_of_space)
2352                         finished = False;
2353
2354                 if (!finished && !out_of_space)
2355                         numentries++;
2356
2357                 /*
2358                  * As an optimisation if we know we aren't looking
2359                  * for a wildcard name (ie. the name matches the wildcard exactly)
2360                  * then we can finish on any (first) match.
2361                  * This speeds up large directory searches. JRA.
2362                  */
2363
2364                 if(got_exact_match)
2365                         finished = True;
2366
2367                 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2368         }
2369
2370         DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2371                 smb_fn_name(CVAL(req->inbuf,smb_com)),
2372                 mask, directory, dirtype, numentries ) );
2373
2374         /* Check if we can close the dirptr */
2375         if(close_after_request || (finished && close_if_end)) {
2376                 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2377                 dptr_close(&dptr_num); /* This frees up the saved mask */
2378         }
2379
2380         /* Set up the return parameter block */
2381         SSVAL(params,0,numentries);
2382         SSVAL(params,2,finished);
2383         SSVAL(params,4,0); /* Never an EA error */
2384         SSVAL(params,6,last_entry_off);
2385
2386         send_trans2_replies(req, params, 8, pdata, PTR_DIFF(p,pdata),
2387                             max_data_bytes);
2388
2389         return;
2390 }
2391
2392 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
2393 {
2394         E_md4hash(lp_servicename(SNUM(conn)),objid);
2395         return objid;
2396 }
2397
2398 /****************************************************************************
2399  Reply to a TRANS2_QFSINFO (query filesystem info).
2400 ****************************************************************************/
2401
2402 static void call_trans2qfsinfo(connection_struct *conn,
2403                                struct smb_request *req,
2404                                char **pparams, int total_params,
2405                                char **ppdata, int total_data,
2406                                unsigned int max_data_bytes)
2407 {
2408         char *pdata, *end_data;
2409         char *params = *pparams;
2410         uint16 info_level;
2411         int data_len, len;
2412         SMB_STRUCT_STAT st;
2413         const char *vname = volume_label(SNUM(conn));
2414         int snum = SNUM(conn);
2415         char *fstype = lp_fstype(SNUM(conn));
2416         int quota_flag = 0;
2417
2418         if (total_params < 2) {
2419                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2420                 return;
2421         }
2422
2423         info_level = SVAL(params,0);
2424
2425         DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
2426
2427         if(SMB_VFS_STAT(conn,".",&st)!=0) {
2428                 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
2429                 reply_doserror(req, ERRSRV, ERRinvdevice);
2430                 return;
2431         }
2432
2433         *ppdata = (char *)SMB_REALLOC(
2434                 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2435         if (*ppdata == NULL ) {
2436                 reply_nterror(req, NT_STATUS_NO_MEMORY);
2437                 return;
2438         }
2439
2440         pdata = *ppdata;
2441         memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2442         end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2443
2444         switch (info_level) {
2445                 case SMB_INFO_ALLOCATION:
2446                 {
2447                         SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2448                         data_len = 18;
2449                         if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2450                                 reply_unixerror(req, ERRHRD, ERRgeneral);
2451                                 return;
2452                         }
2453
2454                         block_size = lp_block_size(snum);
2455                         if (bsize < block_size) {
2456                                 SMB_BIG_UINT factor = block_size/bsize;
2457                                 bsize = block_size;
2458                                 dsize /= factor;
2459                                 dfree /= factor;
2460                         }
2461                         if (bsize > block_size) {
2462                                 SMB_BIG_UINT factor = bsize/block_size;
2463                                 bsize = block_size;
2464                                 dsize *= factor;
2465                                 dfree *= factor;
2466                         }
2467                         bytes_per_sector = 512;
2468                         sectors_per_unit = bsize/bytes_per_sector;
2469
2470                         DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2471 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2472                                 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2473
2474                         SIVAL(pdata,l1_idFileSystem,st.st_dev);
2475                         SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2476                         SIVAL(pdata,l1_cUnit,dsize);
2477                         SIVAL(pdata,l1_cUnitAvail,dfree);
2478                         SSVAL(pdata,l1_cbSector,bytes_per_sector);
2479                         break;
2480                 }
2481
2482                 case SMB_INFO_VOLUME:
2483                         /* Return volume name */
2484                         /* 
2485                          * Add volume serial number - hash of a combination of
2486                          * the called hostname and the service name.
2487                          */
2488                         SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2489                         /*
2490                          * Win2k3 and previous mess this up by sending a name length
2491                          * one byte short. I believe only older clients (OS/2 Win9x) use
2492                          * this call so try fixing this by adding a terminating null to
2493                          * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2494                          */
2495                         len = srvstr_push(
2496                                 pdata, req->flags2,
2497                                 pdata+l2_vol_szVolLabel, vname,
2498                                 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
2499                                 STR_NOALIGN|STR_TERMINATE);
2500                         SCVAL(pdata,l2_vol_cch,len);
2501                         data_len = l2_vol_szVolLabel + len;
2502                         DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
2503                                 (unsigned)st.st_ctime, len, vname));
2504                         break;
2505
2506                 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2507                 case SMB_FS_ATTRIBUTE_INFORMATION:
2508
2509
2510 #if defined(HAVE_SYS_QUOTAS)
2511                         quota_flag = FILE_VOLUME_QUOTAS;
2512 #endif
2513
2514                         SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2515                                 (lp_nt_acl_support(SNUM(conn)) ? FILE_PERSISTENT_ACLS : 0)|
2516                                 FILE_SUPPORTS_OBJECT_IDS|
2517                                 FILE_UNICODE_ON_DISK|
2518                                 quota_flag); /* FS ATTRIBUTES */
2519
2520                         SIVAL(pdata,4,255); /* Max filename component length */
2521                         /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2522                                 and will think we can't do long filenames */
2523                         len = srvstr_push(pdata, req->flags2, pdata+12, fstype,
2524                                           PTR_DIFF(end_data, pdata+12),
2525                                           STR_UNICODE);
2526                         SIVAL(pdata,8,len);
2527                         data_len = 12 + len;
2528                         break;
2529
2530                 case SMB_QUERY_FS_LABEL_INFO:
2531                 case SMB_FS_LABEL_INFORMATION:
2532                         len = srvstr_push(pdata, req->flags2, pdata+4, vname,
2533                                           PTR_DIFF(end_data, pdata+4), 0);
2534                         data_len = 4 + len;
2535                         SIVAL(pdata,0,len);
2536                         break;
2537
2538                 case SMB_QUERY_FS_VOLUME_INFO:      
2539                 case SMB_FS_VOLUME_INFORMATION:
2540
2541                         /* 
2542                          * Add volume serial number - hash of a combination of
2543                          * the called hostname and the service name.
2544                          */
2545                         SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^ 
2546                                 (str_checksum(get_local_machine_name())<<16));
2547
2548                         /* Max label len is 32 characters. */
2549                         len = srvstr_push(pdata, req->flags2, pdata+18, vname,
2550                                           PTR_DIFF(end_data, pdata+18),
2551                                           STR_UNICODE);
2552                         SIVAL(pdata,12,len);
2553                         data_len = 18+len;
2554
2555                         DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n", 
2556                                 (int)strlen(vname),vname, lp_servicename(snum)));
2557                         break;
2558
2559                 case SMB_QUERY_FS_SIZE_INFO:
2560                 case SMB_FS_SIZE_INFORMATION:
2561                 {
2562                         SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2563                         data_len = 24;
2564                         if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2565                                 reply_unixerror(req, ERRHRD, ERRgeneral);
2566                                 return;
2567                         }
2568                         block_size = lp_block_size(snum);
2569                         if (bsize < block_size) {
2570                                 SMB_BIG_UINT factor = block_size/bsize;
2571                                 bsize = block_size;
2572                                 dsize /= factor;
2573                                 dfree /= factor;
2574                         }
2575                         if (bsize > block_size) {
2576                                 SMB_BIG_UINT factor = bsize/block_size;
2577                                 bsize = block_size;
2578                                 dsize *= factor;
2579                                 dfree *= factor;
2580                         }
2581                         bytes_per_sector = 512;
2582                         sectors_per_unit = bsize/bytes_per_sector;
2583                         DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2584 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2585                                 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2586                         SBIG_UINT(pdata,0,dsize);
2587                         SBIG_UINT(pdata,8,dfree);
2588                         SIVAL(pdata,16,sectors_per_unit);
2589                         SIVAL(pdata,20,bytes_per_sector);
2590                         break;
2591                 }
2592
2593                 case SMB_FS_FULL_SIZE_INFORMATION:
2594                 {
2595                         SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2596                         data_len = 32;
2597                         if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2598                                 reply_unixerror(req, ERRHRD, ERRgeneral);
2599                                 return;
2600                         }
2601                         block_size = lp_block_size(snum);
2602                         if (bsize < block_size) {
2603                                 SMB_BIG_UINT factor = block_size/bsize;
2604                                 bsize = block_size;
2605                                 dsize /= factor;
2606                                 dfree /= factor;
2607                         }
2608                         if (bsize > block_size) {
2609                                 SMB_BIG_UINT factor = bsize/block_size;
2610                                 bsize = block_size;
2611                                 dsize *= factor;
2612                                 dfree *= factor;
2613                         }
2614                         bytes_per_sector = 512;
2615                         sectors_per_unit = bsize/bytes_per_sector;
2616                         DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2617 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2618                                 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2619                         SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2620                         SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2621                         SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2622                         SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2623                         SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2624                         break;
2625                 }
2626
2627                 case SMB_QUERY_FS_DEVICE_INFO:
2628                 case SMB_FS_DEVICE_INFORMATION:
2629                         data_len = 8;
2630                         SIVAL(pdata,0,0); /* dev type */
2631                         SIVAL(pdata,4,0); /* characteristics */
2632                         break;
2633
2634 #ifdef HAVE_SYS_QUOTAS
2635                 case SMB_FS_QUOTA_INFORMATION:
2636                 /* 
2637                  * what we have to send --metze:
2638                  *
2639                  * Unknown1:            24 NULL bytes
2640                  * Soft Quota Treshold: 8 bytes seems like SMB_BIG_UINT or so
2641                  * Hard Quota Limit:    8 bytes seems like SMB_BIG_UINT or so
2642                  * Quota Flags:         2 byte :
2643                  * Unknown3:            6 NULL bytes
2644                  *
2645                  * 48 bytes total
2646                  * 
2647                  * details for Quota Flags:
2648                  * 
2649                  * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2650                  * 0x0010 Log Warn:  log if the user exceeds his Soft Quota
2651                  * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2652                  * 0x0001 Enable Quotas: enable quota for this fs
2653                  *
2654                  */
2655                 {
2656                         /* we need to fake up a fsp here,
2657                          * because its not send in this call
2658                          */
2659                         files_struct fsp;
2660                         SMB_NTQUOTA_STRUCT quotas;
2661                         
2662                         ZERO_STRUCT(fsp);
2663                         ZERO_STRUCT(quotas);
2664                         
2665                         fsp.conn = conn;
2666                         fsp.fnum = -1;
2667                         
2668                         /* access check */
2669                         if (current_user.ut.uid != 0) {
2670                                 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2671                                         lp_servicename(SNUM(conn)),conn->user));
2672                                 reply_doserror(req, ERRDOS, ERRnoaccess);
2673                                 return;
2674                         }
2675                         
2676                         if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
2677                                 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2678                                 reply_doserror(req, ERRSRV, ERRerror);
2679                                 return;
2680                         }
2681
2682                         data_len = 48;
2683
2684                         DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn))));          
2685                 
2686                         /* Unknown1 24 NULL bytes*/
2687                         SBIG_UINT(pdata,0,(SMB_BIG_UINT)0);
2688                         SBIG_UINT(pdata,8,(SMB_BIG_UINT)0);
2689                         SBIG_UINT(pdata,16,(SMB_BIG_UINT)0);
2690                 
2691                         /* Default Soft Quota 8 bytes */
2692                         SBIG_UINT(pdata,24,quotas.softlim);
2693
2694                         /* Default Hard Quota 8 bytes */
2695                         SBIG_UINT(pdata,32,quotas.hardlim);
2696         
2697                         /* Quota flag 2 bytes */
2698                         SSVAL(pdata,40,quotas.qflags);
2699                 
2700                         /* Unknown3 6 NULL bytes */
2701                         SSVAL(pdata,42,0);
2702                         SIVAL(pdata,44,0);
2703                         
2704                         break;
2705                 }
2706 #endif /* HAVE_SYS_QUOTAS */
2707                 case SMB_FS_OBJECTID_INFORMATION:
2708                 {
2709                         unsigned char objid[16];
2710                         memcpy(pdata,create_volume_objectid(conn, objid),16);
2711                         data_len = 64;
2712                         break;
2713                 }
2714
2715                 /*
2716                  * Query the version and capabilities of the CIFS UNIX extensions
2717                  * in use.
2718                  */
2719
2720                 case SMB_QUERY_CIFS_UNIX_INFO:
2721                 {
2722                         bool large_write = lp_min_receive_file_size() &&
2723                                                 !srv_is_signing_active();
2724
2725                         if (!lp_unix_extensions()) {
2726                                 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2727                                 return;
2728                         }
2729                         data_len = 12;
2730                         SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2731                         SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2732                         /* We have POSIX ACLs, pathname and locking capability. */
2733                         SBIG_UINT(pdata,4,((SMB_BIG_UINT)(
2734                                         CIFS_UNIX_POSIX_ACLS_CAP|
2735                                         CIFS_UNIX_POSIX_PATHNAMES_CAP|
2736                                         CIFS_UNIX_FCNTL_LOCKS_CAP|
2737                                         CIFS_UNIX_EXTATTR_CAP|
2738                                         CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
2739                                         CIFS_UNIX_LARGE_READ_CAP|
2740                                         (large_write ?
2741                                         CIFS_UNIX_LARGE_WRITE_CAP : 0))));
2742                         break;
2743                 }
2744
2745                 case SMB_QUERY_POSIX_FS_INFO:
2746                 {
2747                         int rc;
2748                         vfs_statvfs_struct svfs;
2749
2750                         if (!lp_unix_extensions()) {
2751                                 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2752                                 return;
2753                         }
2754
2755                         rc = SMB_VFS_STATVFS(conn, ".", &svfs);
2756
2757                         if (!rc) {
2758                                 data_len = 56;
2759                                 SIVAL(pdata,0,svfs.OptimalTransferSize);
2760                                 SIVAL(pdata,4,svfs.BlockSize);
2761                                 SBIG_UINT(pdata,8,svfs.TotalBlocks);
2762                                 SBIG_UINT(pdata,16,svfs.BlocksAvail);
2763                                 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
2764                                 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
2765                                 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
2766                                 SBIG_UINT(pdata,48,svfs.FsIdentifier);
2767                                 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
2768 #ifdef EOPNOTSUPP
2769                         } else if (rc == EOPNOTSUPP) {
2770                                 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2771                                 return;
2772 #endif /* EOPNOTSUPP */
2773                         } else {
2774                                 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2775                                 reply_doserror(req, ERRSRV, ERRerror);
2776                                 return;
2777                         }
2778                         break;
2779                 }
2780
2781                 case SMB_QUERY_POSIX_WHOAMI:
2782                 {
2783                         uint32_t flags = 0;
2784                         uint32_t sid_bytes;
2785                         int i;
2786
2787                         if (!lp_unix_extensions()) {
2788                                 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2789                                 return;
2790                         }
2791
2792                         if (max_data_bytes < 40) {
2793                                 reply_nterror(req, NT_STATUS_BUFFER_TOO_SMALL);
2794                                 return;
2795                         }
2796
2797                         /* We ARE guest if global_sid_Builtin_Guests is
2798                          * in our list of SIDs.
2799                          */
2800                         if (nt_token_check_sid(&global_sid_Builtin_Guests,
2801                                     current_user.nt_user_token)) {
2802                                 flags |= SMB_WHOAMI_GUEST;
2803                         }
2804
2805                         /* We are NOT guest if global_sid_Authenticated_Users
2806                          * is in our list of SIDs.
2807                          */
2808                         if (nt_token_check_sid(&global_sid_Authenticated_Users,
2809                                     current_user.nt_user_token)) {
2810                                 flags &= ~SMB_WHOAMI_GUEST;
2811                         }
2812
2813                         /* NOTE: 8 bytes for UID/GID, irrespective of native
2814                          * platform size. This matches
2815                          * SMB_QUERY_FILE_UNIX_BASIC and friends.
2816                          */
2817                         data_len = 4 /* flags */
2818                             + 4 /* flag mask */
2819                             + 8 /* uid */
2820                             + 8 /* gid */
2821                             + 4 /* ngroups */
2822                             + 4 /* num_sids */
2823                             + 4 /* SID bytes */
2824                             + 4 /* pad/reserved */
2825                             + (current_user.ut.ngroups * 8)
2826                                 /* groups list */
2827                             + (current_user.nt_user_token->num_sids *
2828                                     SID_MAX_SIZE)
2829                                 /* SID list */;
2830
2831                         SIVAL(pdata, 0, flags);
2832                         SIVAL(pdata, 4, SMB_WHOAMI_MASK);
2833                         SBIG_UINT(pdata, 8, (SMB_BIG_UINT)current_user.ut.uid);
2834                         SBIG_UINT(pdata, 16, (SMB_BIG_UINT)current_user.ut.gid);
2835
2836
2837                         if (data_len >= max_data_bytes) {
2838                                 /* Potential overflow, skip the GIDs and SIDs. */
2839
2840                                 SIVAL(pdata, 24, 0); /* num_groups */
2841                                 SIVAL(pdata, 28, 0); /* num_sids */
2842                                 SIVAL(pdata, 32, 0); /* num_sid_bytes */
2843                                 SIVAL(pdata, 36, 0); /* reserved */
2844
2845                                 data_len = 40;
2846                                 break;
2847                         }
2848
2849                         SIVAL(pdata, 24, current_user.ut.ngroups);
2850                         SIVAL(pdata, 28,
2851                                 current_user.nt_user_token->num_sids);
2852
2853                         /* We walk the SID list twice, but this call is fairly
2854                          * infrequent, and I don't expect that it's performance
2855                          * sensitive -- jpeach
2856                          */
2857                         for (i = 0, sid_bytes = 0;
2858                             i < current_user.nt_user_token->num_sids; ++i) {
2859                                 sid_bytes +=
2860                                     sid_size(&current_user.nt_user_token->user_sids[i]);
2861                         }
2862
2863                         /* SID list byte count */
2864                         SIVAL(pdata, 32, sid_bytes);
2865
2866                         /* 4 bytes pad/reserved - must be zero */
2867                         SIVAL(pdata, 36, 0);
2868                         data_len = 40;
2869
2870                         /* GID list */
2871                         for (i = 0; i < current_user.ut.ngroups; ++i) {
2872                                 SBIG_UINT(pdata, data_len,
2873                                         (SMB_BIG_UINT)current_user.ut.groups[i]);
2874                                 data_len += 8;
2875                         }
2876
2877                         /* SID list */
2878                         for (i = 0;
2879                             i < current_user.nt_user_token->num_sids; ++i) {
2880                                 int sid_len =
2881                                     sid_size(&current_user.nt_user_token->user_sids[i]);
2882
2883                                 sid_linearize(pdata + data_len, sid_len,
2884                                     &current_user.nt_user_token->user_sids[i]);
2885                                 data_len += sid_len;
2886                         }
2887
2888                         break;
2889                 }
2890
2891                 case SMB_MAC_QUERY_FS_INFO:
2892                         /*
2893                          * Thursby MAC extension... ONLY on NTFS filesystems
2894                          * once we do streams then we don't need this
2895                          */
2896                         if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
2897                                 data_len = 88;
2898                                 SIVAL(pdata,84,0x100); /* Don't support mac... */
2899                                 break;
2900                         }
2901                         /* drop through */
2902                 default:
2903                         reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2904                         return;
2905         }
2906
2907
2908         send_trans2_replies(req, params, 0, pdata, data_len,
2909                             max_data_bytes);
2910
2911         DEBUG( 4, ( "%s info_level = %d\n",
2912                     smb_fn_name(CVAL(req->inbuf,smb_com)), info_level) );
2913
2914         return;
2915 }
2916
2917 /****************************************************************************
2918  Reply to a TRANS2_SETFSINFO (set filesystem info).
2919 ****************************************************************************/
2920
2921 static void call_trans2setfsinfo(connection_struct *conn,
2922                                  struct smb_request *req,
2923                                  char **pparams, int total_params,
2924                                  char **ppdata, int total_data,
2925                                  unsigned int max_data_bytes)
2926 {
2927         char *pdata = *ppdata;
2928         char *params = *pparams;
2929         uint16 info_level;
2930
2931         DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
2932
2933         /*  */
2934         if (total_params < 4) {
2935                 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
2936                         total_params));
2937                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2938                 return;
2939         }
2940
2941         info_level = SVAL(params,2);
2942
2943         switch(info_level) {
2944                 case SMB_SET_CIFS_UNIX_INFO:
2945                         {
2946                                 uint16 client_unix_major;
2947                                 uint16 client_unix_minor;
2948                                 uint32 client_unix_cap_low;
2949                                 uint32 client_unix_cap_high;
2950
2951                                 if (!lp_unix_extensions()) {
2952                                         reply_nterror(req,
2953                                                       NT_STATUS_INVALID_LEVEL);
2954                                         return;
2955                                 }
2956
2957                                 /* There should be 12 bytes of capabilities set. */
2958                                 if (total_data < 8) {
2959                                         reply_nterror(
2960                                                 req,
2961                                                 NT_STATUS_INVALID_PARAMETER);
2962                                         return;
2963                                 }
2964                                 client_unix_major = SVAL(pdata,0);
2965                                 client_unix_minor = SVAL(pdata,2);
2966                                 client_unix_cap_low = IVAL(pdata,4);
2967                                 client_unix_cap_high = IVAL(pdata,8);
2968                                 /* Just print these values for now. */
2969                                 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
2970 cap_low = 0x%x, cap_high = 0x%x\n",
2971                                         (unsigned int)client_unix_major,
2972                                         (unsigned int)client_unix_minor,
2973                                         (unsigned int)client_unix_cap_low,
2974                                         (unsigned int)client_unix_cap_high ));
2975
2976                                 /* Here is where we must switch to posix pathname processing... */
2977                                 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
2978                                         lp_set_posix_pathnames();
2979                                         mangle_change_to_posix();
2980                                 }
2981
2982                                 if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
2983                                     !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
2984                                         /* Client that knows how to do posix locks,
2985                                          * but not posix open/mkdir operations. Set a
2986                                          * default type for read/write checks. */
2987
2988                                         lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
2989
2990                                 }
2991                                 break;
2992                         }
2993                 case SMB_FS_QUOTA_INFORMATION:
2994                         {
2995                                 files_struct *fsp = NULL;
2996                                 SMB_NTQUOTA_STRUCT quotas;
2997         
2998                                 ZERO_STRUCT(quotas);
2999
3000                                 /* access check */
3001                                 if ((current_user.ut.uid != 0)||!CAN_WRITE(conn)) {
3002                                         DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3003                                                 lp_servicename(SNUM(conn)),conn->user));
3004                                         reply_doserror(req, ERRSRV, ERRaccess);
3005                                         return;
3006                                 }
3007
3008                                 /* note: normaly there're 48 bytes,
3009                                  * but we didn't use the last 6 bytes for now 
3010                                  * --metze 
3011                                  */
3012                                 fsp = file_fsp(SVAL(params,0));
3013                                 if (!CHECK_NTQUOTA_HANDLE_OK(fsp,conn)) {
3014                                         DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3015                                         reply_nterror(
3016                                                 req, NT_STATUS_INVALID_HANDLE);
3017                                         return;
3018                                 }
3019
3020                                 if (total_data < 42) {
3021                                         DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3022                                                 total_data));
3023                                         reply_nterror(
3024                                                 req,
3025                                                 NT_STATUS_INVALID_PARAMETER);
3026                                         return;
3027                                 }
3028                         
3029                                 /* unknown_1 24 NULL bytes in pdata*/
3030                 
3031                                 /* the soft quotas 8 bytes (SMB_BIG_UINT)*/
3032                                 quotas.softlim = (SMB_BIG_UINT)IVAL(pdata,24);
3033 #ifdef LARGE_SMB_OFF_T
3034                                 quotas.softlim |= (((SMB_BIG_UINT)IVAL(pdata,28)) << 32);
3035 #else /* LARGE_SMB_OFF_T */
3036                                 if ((IVAL(pdata,28) != 0)&&
3037                                         ((quotas.softlim != 0xFFFFFFFF)||
3038                                         (IVAL(pdata,28)!=0xFFFFFFFF))) {
3039                                         /* more than 32 bits? */
3040                                         reply_nterror(
3041                                                 req,
3042                                                 NT_STATUS_INVALID_PARAMETER);
3043                                         return;
3044                                 }
3045 #endif /* LARGE_SMB_OFF_T */
3046                 
3047                                 /* the hard quotas 8 bytes (SMB_BIG_UINT)*/
3048                                 quotas.hardlim = (SMB_BIG_UINT)IVAL(pdata,32);
3049 #ifdef LARGE_SMB_OFF_T
3050                                 quotas.hardlim |= (((SMB_BIG_UINT)IVAL(pdata,36)) << 32);
3051 #else /* LARGE_SMB_OFF_T */
3052                                 if ((IVAL(pdata,36) != 0)&&
3053                                         ((quotas.hardlim != 0xFFFFFFFF)||
3054                                         (IVAL(pdata,36)!=0xFFFFFFFF))) {
3055                                         /* more than 32 bits? */
3056                                         reply_nterror(
3057                                                 req,
3058                                                 NT_STATUS_INVALID_PARAMETER);
3059                                         return;
3060                                 }
3061 #endif /* LARGE_SMB_OFF_T */
3062                 
3063                                 /* quota_flags 2 bytes **/
3064                                 quotas.qflags = SVAL(pdata,40);
3065                 
3066                                 /* unknown_2 6 NULL bytes follow*/
3067                 
3068                                 /* now set the quotas */
3069                                 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
3070                                         DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3071                                         reply_doserror(req, ERRSRV, ERRerror);
3072                                         return;
3073                                 }
3074                         
3075                                 break;
3076                         }
3077                 default:
3078                         DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3079                                 info_level));
3080                         reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3081                         return;
3082                         break;
3083         }
3084
3085         /* 
3086          * sending this reply works fine, 
3087          * but I'm not sure it's the same 
3088          * like windows do...
3089          * --metze
3090          */
3091         reply_outbuf(req, 10, 0);
3092 }
3093
3094 #if defined(HAVE_POSIX_ACLS)
3095 /****************************************************************************
3096  Utility function to count the number of entries in a POSIX acl.
3097 ****************************************************************************/
3098
3099 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3100 {
3101         unsigned int ace_count = 0;
3102         int entry_id = SMB_ACL_FIRST_ENTRY;
3103         SMB_ACL_ENTRY_T entry;
3104
3105         while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3106                 /* get_next... */
3107                 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3108                         entry_id = SMB_ACL_NEXT_ENTRY;
3109                 }
3110                 ace_count++;
3111         }
3112         return ace_count;
3113 }
3114
3115 /****************************************************************************
3116  Utility function to marshall a POSIX acl into wire format.
3117 ****************************************************************************/
3118
3119 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3120 {
3121         int entry_id = SMB_ACL_FIRST_ENTRY;
3122         SMB_ACL_ENTRY_T entry;
3123
3124         while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3125                 SMB_ACL_TAG_T tagtype;
3126                 SMB_ACL_PERMSET_T permset;
3127                 unsigned char perms = 0;
3128                 unsigned int own_grp;
3129
3130                 /* get_next... */
3131                 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3132                         entry_id = SMB_ACL_NEXT_ENTRY;
3133                 }
3134
3135                 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
3136                         DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3137                         return False;
3138                 }
3139
3140                 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
3141                         DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3142                         return False;
3143                 }
3144
3145                 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3146                 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3147                 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3148
3149                 SCVAL(pdata,1,perms);
3150
3151                 switch (tagtype) {
3152                         case SMB_ACL_USER_OBJ:
3153                                 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3154                                 own_grp = (unsigned int)pst->st_uid;
3155                                 SIVAL(pdata,2,own_grp);
3156                                 SIVAL(pdata,6,0);
3157                                 break;
3158                         case SMB_ACL_USER:
3159                                 {
3160                                         uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3161                                         if (!puid) {
3162                                                 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3163                                                 return False;
3164                                         }
3165                                         own_grp = (unsigned int)*puid;
3166                                         SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
3167                                         SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3168                                         SIVAL(pdata,2,own_grp);
3169                                         SIVAL(pdata,6,0);
3170                                         break;
3171                                 }
3172                         case SMB_ACL_GROUP_OBJ:
3173                                 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3174                                 own_grp = (unsigned int)pst->st_gid;
3175                                 SIVAL(pdata,2,own_grp);
3176                                 SIVAL(pdata,6,0);
3177                                 break;
3178                         case SMB_ACL_GROUP:
3179                                 {
3180                                         gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3181                                         if (!pgid) {
3182                                                 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3183                                                 return False;
3184                                         }
3185                                         own_grp = (unsigned int)*pgid;
3186                                         SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
3187                                         SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3188                                         SIVAL(pdata,2,own_grp);
3189                                         SIVAL(pdata,6,0);
3190                                         break;
3191                                 }
3192                         case SMB_ACL_MASK:
3193                                 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3194                                 SIVAL(pdata,2,0xFFFFFFFF);
3195                                 SIVAL(pdata,6,0xFFFFFFFF);
3196                                 break;
3197                         case SMB_ACL_OTHER:
3198                                 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3199                                 SIVAL(pdata,2,0xFFFFFFFF);
3200                                 SIVAL(pdata,6,0xFFFFFFFF);
3201                                 break;
3202                         default:
3203                                 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3204                                 return False;
3205                 }
3206                 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3207         }
3208
3209         return True;
3210 }
3211 #endif
3212
3213 /****************************************************************************
3214  Store the FILE_UNIX_BASIC info.
3215 ****************************************************************************/
3216
3217 static char *store_file_unix_basic(connection_struct *conn,
3218                                 char *pdata,
3219                                 files_struct *fsp,
3220                                 const SMB_STRUCT_STAT *psbuf)
3221 {
3222         DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3223         DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_mode));
3224
3225         SOFF_T(pdata,0,get_file_size(*psbuf));             /* File size 64 Bit */
3226         pdata += 8;
3227
3228         SOFF_T(pdata,0,get_allocation_size(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3229         pdata += 8;
3230
3231         put_long_date_timespec(pdata,get_ctimespec(psbuf));       /* Change Time 64 Bit */
3232         put_long_date_timespec(pdata+8,get_atimespec(psbuf));     /* Last access time 64 Bit */
3233         put_long_date_timespec(pdata+16,get_mtimespec(psbuf));    /* Last modification time 64 Bit */
3234         pdata += 24;
3235
3236         SIVAL(pdata,0,psbuf->st_uid);               /* user id for the owner */
3237         SIVAL(pdata,4,0);
3238         pdata += 8;
3239
3240         SIVAL(pdata,0,psbuf->st_gid);               /* group id of owner */
3241         SIVAL(pdata,4,0);
3242         pdata += 8;
3243
3244         SIVAL(pdata,0,unix_filetype(psbuf->st_mode));
3245         pdata += 4;
3246
3247         SIVAL(pdata,0,unix_dev_major(psbuf->st_rdev));   /* Major device number if type is device */
3248         SIVAL(pdata,4,0);
3249         pdata += 8;
3250
3251         SIVAL(pdata,0,unix_dev_minor(psbuf->st_rdev));   /* Minor device number if type is device */
3252         SIVAL(pdata,4,0);
3253         pdata += 8;
3254
3255         SINO_T_VAL(pdata,0,(SMB_INO_T)psbuf->st_ino);   /* inode number */
3256         pdata += 8;
3257                                 
3258         SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_mode));     /* Standard UNIX file permissions */
3259         SIVAL(pdata,4,0);
3260         pdata += 8;
3261
3262         SIVAL(pdata,0,psbuf->st_nlink);             /* number of hard links */
3263         SIVAL(pdata,4,0);
3264         pdata += 8;
3265
3266         return pdata;
3267 }
3268
3269 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3270  * the chflags(2) (or equivalent) flags.
3271  *
3272  * XXX: this really should be behind the VFS interface. To do this, we would
3273  * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3274  * Each VFS module could then implement it's own mapping as appropriate for the
3275  * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3276  */
3277 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
3278         info2_flags_map[] =
3279 {
3280 #ifdef UF_NODUMP
3281     { UF_NODUMP, EXT_DO_NOT_BACKUP },
3282 #endif
3283
3284 #ifdef UF_IMMUTABLE
3285     { UF_IMMUTABLE, EXT_IMMUTABLE },
3286 #endif
3287
3288 #ifdef UF_APPEND
3289     { UF_APPEND, EXT_OPEN_APPEND_ONLY },
3290 #endif
3291
3292 #ifdef UF_HIDDEN
3293     { UF_HIDDEN, EXT_HIDDEN },
3294 #endif
3295
3296     /* Do not remove. We need to guarantee that this array has at least one
3297      * entry to build on HP-UX.
3298      */
3299     { 0, 0 }
3300
3301 };
3302
3303 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
3304                                 uint32 *smb_fflags, uint32 *smb_fmask)
3305 {
3306 #ifdef HAVE_STAT_ST_FLAGS
3307         int i;
3308
3309         for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3310             *smb_fmask |= info2_flags_map[i].smb_fflag;
3311             if (psbuf->st_flags & info2_flags_map[i].stat_fflag) {
3312                     *smb_fflags |= info2_flags_map[i].smb_fflag;
3313             }
3314         }
3315 #endif /* HAVE_STAT_ST_FLAGS */
3316 }
3317
3318 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
3319                                 const uint32 smb_fflags,
3320                                 const uint32 smb_fmask,
3321                                 int *stat_fflags)
3322 {
3323 #ifdef HAVE_STAT_ST_FLAGS
3324         uint32 max_fmask = 0;
3325         int i;
3326
3327         *stat_fflags = psbuf->st_flags;
3328
3329         /* For each flags requested in smb_fmask, check the state of the
3330          * corresponding flag in smb_fflags and set or clear the matching
3331          * stat flag.
3332          */
3333
3334         for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3335             max_fmask |= info2_flags_map[i].smb_fflag;
3336             if (smb_fmask & info2_flags_map[i].smb_fflag) {
3337                     if (smb_fflags & info2_flags_map[i].smb_fflag) {
3338                             *stat_fflags |= info2_flags_map[i].stat_fflag;
3339                     } else {
3340                             *stat_fflags &= ~info2_flags_map[i].stat_fflag;
3341                     }
3342             }
3343         }
3344
3345         /* If smb_fmask is asking to set any bits that are not supported by
3346          * our flag mappings, we should fail.
3347          */
3348         if ((smb_fmask & max_fmask) != smb_fmask) {
3349                 return False;
3350         }
3351
3352         return True;
3353 #else
3354         return False;
3355 #endif /* HAVE_STAT_ST_FLAGS */
3356 }
3357
3358
3359 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
3360  * of file flags and birth (create) time.
3361  */
3362 static char *store_file_unix_basic_info2(connection_struct *conn,
3363                                 char *pdata,
3364                                 files_struct *fsp,
3365                                 const SMB_STRUCT_STAT *psbuf)
3366 {
3367         uint32 file_flags = 0;
3368         uint32 flags_mask = 0;
3369
3370         pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
3371
3372         /* Create (birth) time 64 bit */
3373         put_long_date_timespec(pdata, get_create_timespec(psbuf, False));
3374         pdata += 8;
3375
3376         map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
3377         SIVAL(pdata, 0, file_flags); /* flags */
3378         SIVAL(pdata, 4, flags_mask); /* mask */
3379         pdata += 8;
3380
3381         return pdata;
3382 }
3383
3384 /****************************************************************************
3385  Reply to a TRANSACT2_QFILEINFO on a PIPE !
3386 ****************************************************************************/
3387
3388 static void call_trans2qpipeinfo(connection_struct *conn,
3389                                  struct smb_request *req,
3390                                  unsigned int tran_call,
3391                                  char **pparams, int total_params,
3392                                  char **ppdata, int total_data,
3393                                  unsigned int max_data_bytes)
3394 {
3395         char *params = *pparams;
3396         char *pdata = *ppdata;
3397         unsigned int data_size = 0;
3398         unsigned int param_size = 2;
3399         uint16 info_level;
3400         smb_np_struct *p_pipe = NULL;
3401
3402         if (!params) {
3403                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3404                 return;
3405         }
3406
3407         if (total_params < 4) {
3408                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3409                 return;
3410         }
3411
3412         p_pipe = get_rpc_pipe_p(SVAL(params,0));
3413         if (p_pipe == NULL) {
3414                 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
3415                 return;
3416         }
3417
3418         info_level = SVAL(params,2);
3419
3420         *pparams = (char *)SMB_REALLOC(*pparams,2);
3421         if (*pparams == NULL) {
3422                 reply_nterror(req, NT_STATUS_NO_MEMORY);
3423                 return;
3424         }
3425         params = *pparams;
3426         SSVAL(params,0,0);
3427         data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3428         *ppdata = (char *)SMB_REALLOC(*ppdata, data_size); 
3429         if (*ppdata == NULL ) {
3430                 reply_nterror(req, NT_STATUS_NO_MEMORY);
3431                 return;
3432         }
3433         pdata = *ppdata;
3434
3435         switch (info_level) {
3436                 case SMB_FILE_STANDARD_INFORMATION:
3437                         memset(pdata,0,24);
3438                         SOFF_T(pdata,0,4096LL);
3439                         SIVAL(pdata,16,1);
3440                         SIVAL(pdata,20,1);
3441                         data_size = 24;
3442                         break;
3443
3444                 default:
3445                         reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3446                         return;
3447         }
3448
3449         send_trans2_replies(req, params, param_size, *ppdata, data_size,
3450                             max_data_bytes);
3451
3452         return;
3453 }
3454
3455 /****************************************************************************
3456  Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
3457  file name or file id).
3458 ****************************************************************************/
3459
3460 static void call_trans2qfilepathinfo(connection_struct *conn,
3461                                      struct smb_request *req,
3462                                      unsigned int tran_call,
3463                                      char **pparams, int total_params,
3464                                      char **ppdata, int total_data,
3465                                      unsigned int max_data_bytes)
3466 {
3467         char *params = *pparams;
3468         char *pdata = *ppdata;
3469         char *dstart, *dend;
3470         uint16 info_level;
3471         int mode=0;
3472         int nlink;
3473         SMB_OFF_T file_size=0;
3474         SMB_BIG_UINT allocation_size=0;
3475         unsigned int data_size = 0;
3476         unsigned int param_size = 2;
3477         SMB_STRUCT_STAT sbuf;
3478         char *dos_fname = NULL;
3479         char *fname = NULL;
3480         char *fullpathname;
3481         char *base_name;
3482         char *p;
3483         SMB_OFF_T pos = 0;
3484         bool delete_pending = False;
3485         int len;
3486         time_t create_time, mtime, atime;
3487         struct timespec create_time_ts, mtime_ts, atime_ts;
3488         files_struct *fsp = NULL;
3489         struct file_id fileid;
3490         struct ea_list *ea_list = NULL;
3491         uint32 access_mask = 0x12019F; /* Default - GENERIC_EXECUTE mapping from Windows */
3492         char *lock_data = NULL;
3493         TALLOC_CTX *ctx = talloc_tos();
3494
3495         if (!params) {
3496                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3497                 return;
3498         }
3499
3500         ZERO_STRUCT(sbuf);
3501
3502         if (tran_call == TRANSACT2_QFILEINFO) {
3503                 if (total_params < 4) {
3504                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3505                         return;
3506                 }
3507
3508                 if (IS_IPC(conn)) {
3509                         call_trans2qpipeinfo(conn, req, tran_call,
3510                                              pparams, total_params,
3511                                              ppdata, total_data,
3512                                              max_data_bytes);
3513                         return;
3514                 }
3515
3516                 fsp = file_fsp(SVAL(params,0));
3517                 info_level = SVAL(params,2);
3518
3519                 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
3520
3521                 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3522                         reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3523                         return;
3524                 }
3525
3526                 /* Initial check for valid fsp ptr. */
3527                 if (!check_fsp_open(conn, req, fsp, &current_user)) {
3528                         return;
3529                 }
3530
3531                 fname = talloc_strdup(talloc_tos(),fsp->fsp_name);
3532                 if (!fname) {
3533                         reply_nterror(req, NT_STATUS_NO_MEMORY);
3534                         return;
3535                 }
3536
3537                 if(fsp->fake_file_handle) {
3538                         /*
3539                          * This is actually for the QUOTA_FAKE_FILE --metze
3540                          */
3541
3542                         /* We know this name is ok, it's already passed the checks. */
3543
3544                 } else if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
3545                         /*
3546                          * This is actually a QFILEINFO on a directory
3547                          * handle (returned from an NT SMB). NT5.0 seems
3548                          * to do this call. JRA.
3549                          */
3550
3551                         if (INFO_LEVEL_IS_UNIX(info_level)) {
3552                                 /* Always do lstat for UNIX calls. */
3553                                 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
3554                                         DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
3555                                         reply_unixerror(req,ERRDOS,ERRbadpath);
3556                                         return;
3557                                 }
3558                         } else if (SMB_VFS_STAT(conn,fname,&sbuf)) {
3559                                 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
3560                                 reply_unixerror(req, ERRDOS, ERRbadpath);
3561                                 return;
3562                         }
3563
3564                         fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3565                         delete_pending = get_delete_on_close_flag(fileid);
3566                 } else {
3567                         /*
3568                          * Original code - this is an open file.
3569                          */
3570                         if (!check_fsp(conn, req, fsp, &current_user)) {
3571                                 return;
3572                         }
3573
3574                         if (SMB_VFS_FSTAT(fsp,fsp->fh->fd,&sbuf) != 0) {
3575                                 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
3576                                 reply_unixerror(req, ERRDOS, ERRbadfid);
3577                                 return;
3578                         }
3579                         pos = fsp->fh->position_information;
3580                         fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3581                         delete_pending = get_delete_on_close_flag(fileid);
3582                         access_mask = fsp->access_mask;
3583                 }
3584
3585         } else {
3586                 NTSTATUS status = NT_STATUS_OK;
3587
3588                 /* qpathinfo */
3589                 if (total_params < 7) {
3590                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3591                         return;
3592                 }
3593
3594                 info_level = SVAL(params,0);
3595
3596                 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
3597
3598                 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3599                         reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3600                         return;
3601                 }
3602
3603                 srvstr_get_path(ctx, params, req->flags2, &fname, &params[6],
3604                                 total_params - 6,
3605                                 STR_TERMINATE, &status);
3606                 if (!NT_STATUS_IS_OK(status)) {
3607                         reply_nterror(req, status);
3608                         return;
3609                 }
3610
3611                 status = resolve_dfspath(ctx,
3612                                         conn,
3613                                         req->flags2 & FLAGS2_DFS_PATHNAMES,
3614                                         fname,
3615                                         &fname);
3616                 if (!NT_STATUS_IS_OK(status)) {
3617                         if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
3618                                 reply_botherror(req,
3619                                                 NT_STATUS_PATH_NOT_COVERED,
3620                                                 ERRSRV, ERRbadpath);
3621                         }
3622                         reply_nterror(req, status);
3623                         return;
3624                 }
3625
3626                 status = unix_convert(ctx, conn, fname, False, &fname, NULL, &sbuf);
3627                 if (!NT_STATUS_IS_OK(status)) {
3628                         reply_nterror(req, status);
3629                         return;
3630                 }
3631                 status = check_name(conn, fname);
3632                 if (!NT_STATUS_IS_OK(status)) {
3633                         DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,nt_errstr(status)));
3634                         reply_nterror(req, status);
3635                         return;
3636                 }
3637
3638                 if (INFO_LEVEL_IS_UNIX(info_level)) {
3639                         /* Always do lstat for UNIX calls. */
3640                         if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
3641                                 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
3642                                 reply_unixerror(req, ERRDOS, ERRbadpath);
3643                                 return;
3644                         }
3645                 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) {
3646                         DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
3647                         reply_unixerror(req, ERRDOS, ERRbadpath);
3648                         return;
3649                 }
3650
3651                 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3652                 delete_pending = get_delete_on_close_flag(fileid);
3653                 if (delete_pending) {
3654                         reply_nterror(req, NT_STATUS_DELETE_PENDING);
3655                         return;
3656                 }
3657         }
3658
3659         nlink = sbuf.st_nlink;
3660
3661         if ((nlink > 0) && S_ISDIR(sbuf.st_mode)) {
3662                 /* NTFS does not seem to count ".." */
3663                 nlink -= 1;
3664         }
3665
3666         if ((nlink > 0) && delete_pending) {
3667                 nlink -= 1;
3668         }
3669
3670         if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3671                 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3672                 return;
3673         }
3674
3675         DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
3676                 fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
3677
3678         p = strrchr_m(fname,'/');
3679         if (!p)
3680                 base_name = fname;
3681         else
3682                 base_name = p+1;
3683
3684         mode = dos_mode(conn,fname,&sbuf);
3685         if (!mode)
3686                 mode = FILE_ATTRIBUTE_NORMAL;
3687
3688         fullpathname = fname;
3689         if (!(mode & aDIR))
3690                 file_size = get_file_size(sbuf);
3691
3692         /* Pull out any data sent here before we realloc. */
3693         switch (info_level) {
3694                 case SMB_INFO_QUERY_EAS_FROM_LIST:
3695                 {
3696                         /* Pull any EA list from the data portion. */
3697                         uint32 ea_size;
3698
3699                         if (total_data < 4) {
3700                                 reply_nterror(
3701                                         req, NT_STATUS_INVALID_PARAMETER);
3702                                 return;
3703                         }
3704                         ea_size = IVAL(pdata,0);
3705
3706                         if (total_data > 0 && ea_size != total_data) {
3707                                 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
3708 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
3709                                 reply_nterror(
3710                                         req, NT_STATUS_INVALID_PARAMETER);
3711                                 return;
3712                         }
3713
3714                         if (!lp_ea_support(SNUM(conn))) {
3715                                 reply_doserror(req, ERRDOS,
3716                                                ERReasnotsupported);
3717                                 return;
3718                         }
3719
3720                         /* Pull out the list of names. */
3721                         ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
3722                         if (!ea_list) {
3723                                 reply_nterror(
3724                                         req, NT_STATUS_INVALID_PARAMETER);
3725                                 return;
3726                         }
3727                         break;
3728                 }
3729
3730                 case SMB_QUERY_POSIX_LOCK:
3731                 {
3732                         if (fsp == NULL || fsp->fh->fd == -1) {
3733                                 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
3734                                 return;
3735                         }
3736
3737                         if (total_data != POSIX_LOCK_DATA_SIZE) {
3738                                 reply_nterror(
3739                                         req, NT_STATUS_INVALID_PARAMETER);
3740                                 return;
3741                         }
3742
3743                         /* Copy the lock range data. */
3744                         lock_data = (char *)TALLOC_MEMDUP(
3745                                 ctx, pdata, total_data);
3746                         if (!lock_data) {
3747                                 reply_nterror(req, NT_STATUS_NO_MEMORY);
3748                                 return;
3749                         }
3750                 }
3751                 default:
3752                         break;
3753         }
3754
3755         *pparams = (char *)SMB_REALLOC(*pparams,2);
3756         if (*pparams == NULL) {
3757                 reply_nterror(req, NT_STATUS_NO_MEMORY);
3758                 return;
3759         }
3760         params = *pparams;
3761         SSVAL(params,0,0);
3762         data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3763         *ppdata = (char *)SMB_REALLOC(*ppdata, data_size); 
3764         if (*ppdata == NULL ) {
3765                 reply_nterror(req, NT_STATUS_NO_MEMORY);
3766                 return;
3767         }
3768         pdata = *ppdata;
3769         dstart = pdata;
3770         dend = dstart + data_size - 1;
3771
3772         create_time_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
3773         mtime_ts = get_mtimespec(&sbuf);
3774         atime_ts = get_atimespec(&sbuf);
3775
3776         allocation_size = get_allocation_size(conn,fsp,&sbuf);
3777
3778         if (fsp) {
3779                 if (!null_timespec(fsp->pending_modtime)) {
3780                         /* the pending modtime overrides the current modtime */
3781                         mtime_ts = fsp->pending_modtime;
3782                 }
3783         } else {
3784                 files_struct *fsp1;
3785                 /* Do we have this path open ? */
3786                 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3787                 fsp1 = file_find_di_first(fileid);
3788                 if (fsp1 && !null_timespec(fsp1->pending_modtime)) {
3789                         /* the pending modtime overrides the current modtime */
3790                         mtime_ts = fsp1->pending_modtime;
3791                 }
3792                 if (fsp1 && fsp1->initial_allocation_size) {
3793                         allocation_size = get_allocation_size(conn, fsp1, &sbuf);
3794                 }
3795         }
3796
3797         if (lp_dos_filetime_resolution(SNUM(conn))) {
3798                 dos_filetime_timespec(&create_time_ts);
3799                 dos_filetime_timespec(&mtime_ts);
3800                 dos_filetime_timespec(&atime_ts);
3801         }
3802
3803         create_time = convert_timespec_to_time_t(create_time_ts);
3804         mtime = convert_timespec_to_time_t(mtime_ts);
3805         atime = convert_timespec_to_time_t(atime_ts);
3806
3807         /* NT expects the name to be in an exact form of the *full*
3808            filename. See the trans2 torture test */
3809         if (ISDOT(base_name)) {
3810                 dos_fname = talloc_strdup(ctx, "\\");
3811                 if (!dos_fname) {
3812                         reply_nterror(req, NT_STATUS_NO_MEMORY);
3813                         return;
3814                 }
3815         } else {
3816                 dos_fname = talloc_asprintf(ctx,
3817                                 "\\%s",
3818                                 fname);
3819                 if (!dos_fname) {
3820                         reply_nterror(req, NT_STATUS_NO_MEMORY);
3821                         return;
3822                 }
3823                 string_replace(dos_fname, '/', '\\');
3824         }
3825
3826         switch (info_level) {
3827                 case SMB_INFO_STANDARD:
3828                         DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
3829                         data_size = 22;
3830                         srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
3831                         srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
3832                         srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
3833                         SIVAL(pdata,l1_cbFile,(uint32)file_size);
3834                         SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
3835                         SSVAL(pdata,l1_attrFile,mode);
3836                         break;
3837
3838                 case SMB_INFO_QUERY_EA_SIZE:
3839                 {
3840                         unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3841                         DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
3842                         data_size = 26;
3843                         srv_put_dos_date2(pdata,0,create_time);
3844                         srv_put_dos_date2(pdata,4,atime);
3845                         srv_put_dos_date2(pdata,8,mtime); /* write time */
3846                         SIVAL(pdata,12,(uint32)file_size);
3847                         SIVAL(pdata,16,(uint32)allocation_size);
3848                         SSVAL(pdata,20,mode);
3849                         SIVAL(pdata,22,ea_size);
3850                         break;
3851                 }
3852
3853                 case SMB_INFO_IS_NAME_VALID:
3854                         DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
3855                         if (tran_call == TRANSACT2_QFILEINFO) {
3856                                 /* os/2 needs this ? really ?*/
3857                                 reply_doserror(req, ERRDOS, ERRbadfunc);
3858                                 return;
3859                         }
3860                         data_size = 0;
3861                         param_size = 0;
3862                         break;
3863
3864                 case SMB_INFO_QUERY_EAS_FROM_LIST:
3865                 {
3866                         size_t total_ea_len = 0;
3867                         struct ea_list *ea_file_list = NULL;
3868
3869                         DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
3870
3871                         ea_file_list = get_ea_list_from_file(ctx, conn, fsp, fname, &total_ea_len);
3872                         ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
3873
3874                         if (!ea_list || (total_ea_len > data_size)) {
3875                                 data_size = 4;
3876                                 SIVAL(pdata,0,4);   /* EA List Length must be set to 4 if no EA's. */
3877                                 break;
3878                         }
3879
3880                         data_size = fill_ea_buffer(ctx, pdata, data_size, conn, ea_list);
3881                         break;
3882                 }
3883
3884                 case SMB_INFO_QUERY_ALL_EAS:
3885                 {
3886                         /* We have data_size bytes to put EA's into. */
3887                         size_t total_ea_len = 0;
3888
3889                         DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
3890
3891                         ea_list = get_ea_list_from_file(ctx, conn, fsp, fname, &total_ea_len);
3892                         if (!ea_list || (total_ea_len > data_size)) {
3893                                 data_size = 4;
3894                                 SIVAL(pdata,0,4);   /* EA List Length must be set to 4 if no EA's. */
3895                                 break;
3896                         }
3897
3898                         data_size = fill_ea_buffer(ctx, pdata, data_size, conn, ea_list);
3899                         break;
3900                 }
3901
3902                 case SMB_FILE_BASIC_INFORMATION:
3903                 case SMB_QUERY_FILE_BASIC_INFO:
3904
3905                         if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
3906                                 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
3907                                 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
3908                         } else {
3909                                 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
3910                                 data_size = 40;
3911                                 SIVAL(pdata,36,0);
3912                         }
3913                         put_long_date_timespec(pdata,create_time_ts);
3914                         put_long_date_timespec(pdata+8,atime_ts);
3915                         put_long_date_timespec(pdata+16,mtime_ts); /* write time */
3916                         put_long_date_timespec(pdata+24,mtime_ts); /* change time */
3917                         SIVAL(pdata,32,mode);
3918
3919                         DEBUG(5,("SMB_QFBI - "));
3920                         DEBUG(5,("create: %s ", ctime(&create_time)));
3921                         DEBUG(5,("access: %s ", ctime(&atime)));
3922                         DEBUG(5,("write: %s ", ctime(&mtime)));
3923                         DEBUG(5,("change: %s ", ctime(&mtime)));
3924                         DEBUG(5,("mode: %x\n", mode));
3925                         break;
3926
3927                 case SMB_FILE_STANDARD_INFORMATION:
3928                 case SMB_QUERY_FILE_STANDARD_INFO:
3929
3930                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
3931                         data_size = 24;
3932                         SOFF_T(pdata,0,allocation_size);
3933                         SOFF_T(pdata,8,file_size);
3934                         SIVAL(pdata,16,nlink);
3935                         SCVAL(pdata,20,delete_pending?1:0);
3936                         SCVAL(pdata,21,(mode&aDIR)?1:0);
3937                         SSVAL(pdata,22,0); /* Padding. */
3938                         break;
3939
3940                 case SMB_FILE_EA_INFORMATION:
3941                 case SMB_QUERY_FILE_EA_INFO:
3942                 {
3943                         unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3944                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
3945                         data_size = 4;
3946                         SIVAL(pdata,0,ea_size);
3947                         break;
3948                 }
3949
3950                 /* Get the 8.3 name - used if NT SMB was negotiated. */
3951                 case SMB_QUERY_FILE_ALT_NAME_INFO:
3952                 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
3953                 {
3954                         char mangled_name[13];
3955                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
3956                         if (!name_to_8_3(base_name,mangled_name,
3957                                                 True,conn->params)) {
3958                                 reply_nterror(
3959                                         req,
3960                                         NT_STATUS_NO_MEMORY);
3961                         }
3962                         len = srvstr_push(dstart, req->flags2,
3963                                           pdata+4, mangled_name,
3964                                           PTR_DIFF(dend, pdata+4),
3965                                           STR_UNICODE);
3966                         data_size = 4 + len;
3967                         SIVAL(pdata,0,len);
3968                         break;
3969                 }
3970
3971                 case SMB_QUERY_FILE_NAME_INFO:
3972                         /*
3973                           this must be *exactly* right for ACLs on mapped drives to work
3974                          */
3975                         len = srvstr_push(dstart, req->flags2,
3976                                           pdata+4, dos_fname,
3977                                           PTR_DIFF(dend, pdata+4),
3978                                           STR_UNICODE);
3979                         DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
3980                         data_size = 4 + len;
3981                         SIVAL(pdata,0,len);
3982                         break;
3983
3984                 case SMB_FILE_ALLOCATION_INFORMATION:
3985                 case SMB_QUERY_FILE_ALLOCATION_INFO:
3986                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
3987                         data_size = 8;
3988                         SOFF_T(pdata,0,allocation_size);
3989                         break;
3990
3991                 case SMB_FILE_END_OF_FILE_INFORMATION:
3992                 case SMB_QUERY_FILE_END_OF_FILEINFO:
3993                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
3994                         data_size = 8;
3995                         SOFF_T(pdata,0,file_size);
3996                         break;
3997
3998                 case SMB_QUERY_FILE_ALL_INFO:
3999                 case SMB_FILE_ALL_INFORMATION:
4000                 {
4001                         unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4002                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4003                         put_long_date_timespec(pdata,create_time_ts);
4004                         put_long_date_timespec(pdata+8,atime_ts);
4005                         put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4006                         put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4007                         SIVAL(pdata,32,mode);
4008                         SIVAL(pdata,36,0); /* padding. */
4009                         pdata += 40;
4010                         SOFF_T(pdata,0,allocation_size);
4011                         SOFF_T(pdata,8,file_size);
4012                         SIVAL(pdata,16,nlink);
4013                         SCVAL(pdata,20,delete_pending);
4014                         SCVAL(pdata,21,(mode&aDIR)?1:0);
4015                         SSVAL(pdata,22,0);
4016                         pdata += 24;
4017                         SIVAL(pdata,0,ea_size);
4018                         pdata += 4; /* EA info */
4019                         len = srvstr_push(dstart, req->flags2,
4020                                           pdata+4, dos_fname,
4021                                           PTR_DIFF(dend, pdata+4),
4022                                           STR_UNICODE);
4023                         SIVAL(pdata,0,len);
4024                         pdata += 4 + len;
4025                         data_size = PTR_DIFF(pdata,(*ppdata));
4026                         break;
4027                 }
4028                 case SMB_FILE_INTERNAL_INFORMATION:
4029                         /* This should be an index number - looks like
4030                            dev/ino to me :-) 
4031
4032                            I think this causes us to fail the IFSKIT
4033                            BasicFileInformationTest. -tpot */
4034
4035                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4036                         SIVAL(pdata,0,sbuf.st_ino); /* FileIndexLow */
4037                         SIVAL(pdata,4,sbuf.st_dev); /* FileIndexHigh */
4038                         data_size = 8;
4039                         break;
4040
4041                 case SMB_FILE_ACCESS_INFORMATION:
4042                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4043                         SIVAL(pdata,0,access_mask);
4044                         data_size = 4;
4045                         break;
4046
4047                 case SMB_FILE_NAME_INFORMATION:
4048                         /* Pathname with leading '\'. */
4049                         {
4050                                 size_t byte_len;
4051                                 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4052                                 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4053                                 SIVAL(pdata,0,byte_len);
4054                                 data_size = 4 + byte_len;
4055                                 break;
4056                         }
4057
4058                 case SMB_FILE_DISPOSITION_INFORMATION:
4059                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4060                         data_size = 1;
4061                         SCVAL(pdata,0,delete_pending);
4062                         break;
4063
4064                 case SMB_FILE_POSITION_INFORMATION:
4065                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4066                         data_size = 8;
4067                         SOFF_T(pdata,0,pos);
4068                         break;
4069
4070                 case SMB_FILE_MODE_INFORMATION:
4071                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4072                         SIVAL(pdata,0,mode);
4073                         data_size = 4;
4074                         break;
4075
4076                 case SMB_FILE_ALIGNMENT_INFORMATION:
4077                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4078                         SIVAL(pdata,0,0); /* No alignment needed. */
4079                         data_size = 4;
4080                         break;
4081
4082 #if 0
4083                 /*
4084                  * NT4 server just returns "invalid query" to this - if we try to answer
4085                  * it then NTws gets a BSOD! (tridge).
4086                  * W2K seems to want this. JRA.
4087                  */
4088                 case SMB_QUERY_FILE_STREAM_INFO:
4089 #endif
4090                 case SMB_FILE_STREAM_INFORMATION:
4091                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STREAM_INFORMATION\n"));
4092                         if (mode & aDIR) {
4093                                 data_size = 0;
4094                         } else {
4095                                 size_t byte_len = dos_PutUniCode(pdata+24,"::$DATA", (size_t)0xE, False);
4096                                 SIVAL(pdata,0,0); /* ??? */
4097                                 SIVAL(pdata,4,byte_len); /* Byte length of unicode string ::$DATA */
4098                                 SOFF_T(pdata,8,file_size);
4099                                 SOFF_T(pdata,16,allocation_size);
4100                                 data_size = 24 + byte_len;
4101                         }
4102                         break;
4103
4104                 case SMB_QUERY_COMPRESSION_INFO:
4105                 case SMB_FILE_COMPRESSION_INFORMATION:
4106                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4107                         SOFF_T(pdata,0,file_size);
4108                         SIVAL(pdata,8,0); /* ??? */
4109                         SIVAL(pdata,12,0); /* ??? */
4110                         data_size = 16;
4111                         break;
4112
4113                 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4114                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4115                         put_long_date_timespec(pdata,create_time_ts);
4116                         put_long_date_timespec(pdata+8,atime_ts);
4117                         put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4118                         put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4119                         SOFF_T(pdata,32,allocation_size);
4120                         SOFF_T(pdata,40,file_size);
4121                         SIVAL(pdata,48,mode);
4122                         SIVAL(pdata,52,0); /* ??? */
4123                         data_size = 56;
4124                         break;
4125
4126                 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4127                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4128                         SIVAL(pdata,0,mode);
4129                         SIVAL(pdata,4,0);
4130                         data_size = 8;
4131                         break;
4132
4133                 /*
4134                  * CIFS UNIX Extensions.
4135                  */
4136
4137                 case SMB_QUERY_FILE_UNIX_BASIC:
4138
4139                         pdata = store_file_unix_basic(conn, pdata, fsp, &sbuf);
4140                         data_size = PTR_DIFF(pdata,(*ppdata));
4141
4142                         {
4143                                 int i;
4144                                 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
4145
4146                                 for (i=0; i<100; i++)
4147                                         DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4148                                 DEBUG(4,("\n"));
4149                         }
4150
4151                         break;
4152
4153                 case SMB_QUERY_FILE_UNIX_INFO2:
4154
4155                         pdata = store_file_unix_basic_info2(conn, pdata, fsp, &sbuf);
4156                         data_size = PTR_DIFF(pdata,(*ppdata));
4157
4158                         {
4159                                 int i;
4160                                 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4161
4162                                 for (i=0; i<100; i++)
4163                                         DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4164                                 DEBUG(4,("\n"));
4165                         }
4166
4167                         break;
4168
4169                 case SMB_QUERY_FILE_UNIX_LINK:
4170                         {
4171                                 char *buffer = TALLOC_ARRAY(ctx, char, 1024);
4172
4173                                 if (!buffer) {
4174                                         reply_nterror(req, NT_STATUS_NO_MEMORY);
4175                                         return;
4176                                 }
4177
4178                                 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4179 #ifdef S_ISLNK
4180                                 if(!S_ISLNK(sbuf.st_mode)) {
4181                                         reply_unixerror(req, ERRSRV,
4182                                                         ERRbadlink);
4183                                         return;
4184                                 }
4185 #else
4186                                 reply_unixerror(req, ERRDOS, ERRbadlink);
4187                                 return;
4188 #endif
4189                                 len = SMB_VFS_READLINK(conn,fullpathname,
4190                                                 buffer, 1023);
4191                                 if (len == -1) {
4192                                         reply_unixerror(req, ERRDOS,
4193                                                         ERRnoaccess);
4194                                         return;
4195                                 }
4196                                 buffer[len] = 0;
4197                                 len = srvstr_push(dstart, req->flags2,
4198                                                   pdata, buffer,
4199                                                   PTR_DIFF(dend, pdata),
4200                                                   STR_TERMINATE);
4201                                 pdata += len;
4202                                 data_size = PTR_DIFF(pdata,(*ppdata));
4203
4204                                 break;
4205                         }
4206
4207 #if defined(HAVE_POSIX_ACLS)
4208                 case SMB_QUERY_POSIX_ACL:
4209                         {
4210                                 SMB_ACL_T file_acl = NULL;
4211                                 SMB_ACL_T def_acl = NULL;
4212                                 uint16 num_file_acls = 0;
4213                                 uint16 num_def_acls = 0;
4214
4215                                 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
4216                                         file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp, fsp->fh->fd);
4217                                 } else {
4218                                         file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
4219                                 }
4220
4221                                 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4222                                         DEBUG(5,("call_trans2qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
4223                                                 fname ));
4224                                         reply_nterror(
4225                                                 req,
4226                                                 NT_STATUS_NOT_IMPLEMENTED);
4227                                         return;
4228                                 }
4229
4230                                 if (S_ISDIR(sbuf.st_mode)) {
4231                                         if (fsp && fsp->is_directory) {
4232                                                 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT);
4233                                         } else {
4234                                                 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT);
4235                                         }
4236                                         def_acl = free_empty_sys_acl(conn, def_acl);
4237                                 }
4238
4239                                 num_file_acls = count_acl_entries(conn, file_acl);
4240                                 num_def_acls = count_acl_entries(conn, def_acl);
4241
4242                                 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4243                                         DEBUG(5,("call_trans2qfilepathinfo: data_size too small (%u) need %u\n",
4244                                                 data_size,
4245                                                 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4246                                                         SMB_POSIX_ACL_HEADER_SIZE) ));
4247                                         if (file_acl) {
4248                                                 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4249                                         }
4250                                         if (def_acl) {
4251                                                 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4252                                         }
4253                                         reply_nterror(
4254                                                 req,
4255                                                 NT_STATUS_BUFFER_TOO_SMALL);
4256                                         return;
4257                                 }
4258
4259                                 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4260                                 SSVAL(pdata,2,num_file_acls);
4261                                 SSVAL(pdata,4,num_def_acls);
4262                                 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
4263                                         if (file_acl) {
4264                                                 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4265                                         }
4266                                         if (def_acl) {
4267                                                 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4268                                         }
4269                                         reply_nterror(
4270                                                 req, NT_STATUS_INTERNAL_ERROR);
4271                                         return;
4272                                 }
4273                                 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
4274                                         if (file_acl) {
4275                                                 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4276                                         }
4277                                         if (def_acl) {
4278                                                 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4279                                         }
4280                                         reply_nterror(
4281                                                 req,
4282                                                 NT_STATUS_INTERNAL_ERROR);
4283                                         return;
4284                                 }
4285
4286                                 if (file_acl) {
4287                                         SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4288                                 }
4289                                 if (def_acl) {
4290                                         SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4291                                 }
4292                                 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
4293                                 break;
4294                         }
4295 #endif
4296
4297
4298                 case SMB_QUERY_POSIX_LOCK:
4299                 {
4300                         NTSTATUS status = NT_STATUS_INVALID_LEVEL;
4301                         SMB_BIG_UINT count;
4302                         SMB_BIG_UINT offset;
4303                         uint32 lock_pid;
4304                         enum brl_type lock_type;
4305
4306                         if (total_data != POSIX_LOCK_DATA_SIZE) {
4307                                 reply_nterror(
4308                                         req, NT_STATUS_INVALID_PARAMETER);
4309                                 return;
4310                         }
4311
4312                         switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4313                                 case POSIX_LOCK_TYPE_READ:
4314                                         lock_type = READ_LOCK;
4315                                         break;
4316                                 case POSIX_LOCK_TYPE_WRITE:
4317                                         lock_type = WRITE_LOCK;
4318                                         break;
4319                                 case POSIX_LOCK_TYPE_UNLOCK:
4320                                 default:
4321                                         /* There's no point in asking for an unlock... */
4322                                         reply_nterror(
4323                                                 req,
4324                                                 NT_STATUS_INVALID_PARAMETER);
4325                                         return;
4326                         }
4327
4328                         lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4329 #if defined(HAVE_LONGLONG)
4330                         offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4331                                         ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4332                         count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4333                                         ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4334 #else /* HAVE_LONGLONG */
4335                         offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4336                         count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4337 #endif /* HAVE_LONGLONG */
4338
4339                         status = query_lock(fsp,
4340                                         &lock_pid,
4341                                         &count,
4342                                         &offset,
4343                                         &lock_type,
4344                                         POSIX_LOCK);
4345
4346                         if (ERROR_WAS_LOCK_DENIED(status)) {
4347                                 /* Here we need to report who has it locked... */
4348                                 data_size = POSIX_LOCK_DATA_SIZE;
4349
4350                                 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
4351                                 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
4352                                 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, lock_pid);
4353 #if defined(HAVE_LONGLONG)
4354                                 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
4355                                 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
4356                                 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
4357                                 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
4358 #else /* HAVE_LONGLONG */
4359                                 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
4360                                 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
4361 #endif /* HAVE_LONGLONG */
4362
4363                         } else if (NT_STATUS_IS_OK(status)) {
4364                                 /* For success we just return a copy of what we sent
4365                                    with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4366                                 data_size = POSIX_LOCK_DATA_SIZE;
4367                                 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
4368                                 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
4369                         } else {
4370                                 reply_nterror(req, status);
4371                                 return;
4372                         }
4373                         break;
4374                 }
4375
4376                 default:
4377                         reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4378                         return;
4379         }
4380
4381         send_trans2_replies(req, params, param_size, *ppdata, data_size,
4382                             max_data_bytes);
4383
4384         return;
4385 }
4386
4387 /****************************************************************************
4388  Set a hard link (called by UNIX extensions and by NT rename with HARD link
4389  code.
4390 ****************************************************************************/
4391
4392 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
4393                 connection_struct *conn,
4394                 const char *oldname_in,
4395                 const char *newname_in)
4396 {
4397         SMB_STRUCT_STAT sbuf1, sbuf2;
4398         char *last_component_oldname = NULL;
4399         char *last_component_newname = NULL;
4400         char *oldname = NULL;
4401         char *newname = NULL;
4402         NTSTATUS status = NT_STATUS_OK;
4403
4404         ZERO_STRUCT(sbuf1);
4405         ZERO_STRUCT(sbuf2);
4406
4407         status = unix_convert(ctx, conn, oldname_in, False, &oldname,
4408                         &last_component_oldname, &sbuf1);
4409         if (!NT_STATUS_IS_OK(status)) {
4410                 return status;
4411         }
4412
4413         status = check_name(conn, oldname);
4414         if (!NT_STATUS_IS_OK(status)) {
4415                 return status;
4416         }
4417
4418         /* source must already exist. */
4419         if (!VALID_STAT(sbuf1)) {
4420                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4421         }
4422
4423         status = unix_convert(ctx, conn, newname_in, False, &newname,
4424                         &last_component_newname, &sbuf2);
4425         if (!NT_STATUS_IS_OK(status)) {
4426                 return status;
4427         }
4428
4429         status = check_name(conn, newname);
4430         if (!NT_STATUS_IS_OK(status)) {
4431                 return status;
4432         }
4433
4434         /* Disallow if newname already exists. */
4435         if (VALID_STAT(sbuf2)) {
4436                 return NT_STATUS_OBJECT_NAME_COLLISION;
4437         }
4438
4439         /* No links from a directory. */
4440         if (S_ISDIR(sbuf1.st_mode)) {
4441                 return NT_STATUS_FILE_IS_A_DIRECTORY;
4442         }
4443
4444         /* Ensure this is within the share. */
4445         status = check_reduced_name(conn, oldname);
4446         if (!NT_STATUS_IS_OK(status)) {
4447                 return status;
4448         }
4449
4450         DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
4451
4452         if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
4453                 status = map_nt_error_from_unix(errno);
4454                 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
4455                                 nt_errstr(status), newname, oldname));
4456         }
4457
4458         return status;
4459 }
4460
4461 /****************************************************************************
4462  Deal with setting the time from any of the setfilepathinfo functions.
4463 ****************************************************************************/
4464
4465 static NTSTATUS smb_set_file_time(connection_struct *conn,
4466                                 files_struct *fsp,
4467                                 const char *fname,
4468                                 const SMB_STRUCT_STAT *psbuf,
4469                                 struct timespec ts[2],
4470                                 bool setting_write_time)
4471 {
4472         uint32 action =
4473                 FILE_NOTIFY_CHANGE_LAST_ACCESS
4474                 |FILE_NOTIFY_CHANGE_LAST_WRITE;
4475
4476         if (!VALID_STAT(*psbuf)) {
4477                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4478         }
4479
4480         /* get some defaults (no modifications) if any info is zero or -1. */
4481         if (null_timespec(ts[0])) {
4482                 ts[0] = get_atimespec(psbuf);
4483                 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
4484         }
4485
4486         if (null_timespec(ts[1])) {
4487                 ts[1] = get_mtimespec(psbuf);
4488                 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4489         }
4490
4491         if (!setting_write_time) {
4492                 /* ts[1] comes from change time, not write time. */
4493                 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4494         }
4495
4496         DEBUG(6,("smb_set_file_time: actime: %s " , time_to_asc(convert_timespec_to_time_t(ts[0])) ));
4497         DEBUG(6,("smb_set_file_time: modtime: %s ", time_to_asc(convert_timespec_to_time_t(ts[1])) ));
4498
4499         /*
4500          * Try and set the times of this file if
4501          * they are different from the current values.
4502          */
4503
4504         {
4505                 struct timespec mts = get_mtimespec(psbuf);
4506                 struct timespec ats = get_atimespec(psbuf);
4507                 if ((timespec_compare(&ts[0], &ats) == 0) && (timespec_compare(&ts[1], &mts) == 0)) {
4508                         return NT_STATUS_OK;
4509                 }
4510         }
4511
4512         if(fsp != NULL) {
4513                 /*
4514                  * This was a setfileinfo on an open file.
4515                  * NT does this a lot. We also need to 
4516                  * set the time here, as it can be read by 
4517                  * FindFirst/FindNext and with the patch for bug #2045
4518                  * in smbd/fileio.c it ensures that this timestamp is
4519                  * kept sticky even after a write. We save the request
4520                  * away and will set it on file close and after a write. JRA.
4521                  */
4522
4523                 if (!null_timespec(ts[1])) {
4524                         DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
4525                                 time_to_asc(convert_timespec_to_time_t(ts[1])) ));
4526                         fsp_set_pending_modtime(fsp, ts[1]);
4527                 }
4528
4529         }
4530         DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
4531
4532         if(file_ntimes(conn, fname, ts)!=0) {
4533                 return map_nt_error_from_unix(errno);
4534         }
4535         notify_fname(conn, NOTIFY_ACTION_MODIFIED, action, fname);
4536
4537         return NT_STATUS_OK;
4538 }
4539
4540 /****************************************************************************
4541  Deal with setting the dosmode from any of the setfilepathinfo functions.
4542 ****************************************************************************/
4543
4544 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
4545                                 const char *fname,
4546                                 SMB_STRUCT_STAT *psbuf,
4547                                 uint32 dosmode)
4548 {
4549         if (!VALID_STAT(*psbuf)) {
4550                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4551         }
4552
4553         if (dosmode) {
4554                 if (S_ISDIR(psbuf->st_mode)) {
4555                         dosmode |= aDIR;
4556                 } else {
4557                         dosmode &= ~aDIR;
4558                 }
4559         }
4560
4561         DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
4562
4563         /* check the mode isn't different, before changing it */
4564         if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, psbuf))) {
4565
4566                 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode 0x%x\n",
4567                                         fname, (unsigned int)dosmode ));
4568
4569                 if(file_set_dosmode(conn, fname, dosmode, psbuf, NULL, false)) {
4570                         DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of %s failed (%s)\n",
4571                                                 fname, strerror(errno)));
4572                         return map_nt_error_from_unix(errno);
4573                 }
4574         }
4575         return NT_STATUS_OK;
4576 }
4577
4578 /****************************************************************************
4579  Deal with setting the size from any of the setfilepathinfo functions.
4580 ****************************************************************************/
4581
4582 static NTSTATUS smb_set_file_size(connection_struct *conn,
4583                                   struct smb_request *req,
4584                                 files_struct *fsp,
4585                                 const char *fname,
4586                                 SMB_STRUCT_STAT *psbuf,
4587                                 SMB_OFF_T size)
4588 {
4589         NTSTATUS status = NT_STATUS_OK;
4590         files_struct *new_fsp = NULL;
4591
4592         if (!VALID_STAT(*psbuf)) {
4593                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4594         }
4595
4596         DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
4597
4598         if (size == get_file_size(*psbuf)) {
4599                 return NT_STATUS_OK;
4600         }
4601
4602         DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
4603                 fname, (double)size ));
4604
4605         if (fsp && fsp->fh->fd != -1) {
4606                 /* Handle based call. */
4607                 if (vfs_set_filelen(fsp, size) == -1) {
4608                         return map_nt_error_from_unix(errno);
4609                 }
4610                 return NT_STATUS_OK;
4611         }
4612
4613         status = open_file_ntcreate(conn, req, fname, psbuf,
4614                                 FILE_WRITE_DATA,
4615                                 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4616                                 FILE_OPEN,
4617                                 0,
4618                                 FILE_ATTRIBUTE_NORMAL,
4619                                 FORCE_OPLOCK_BREAK_TO_NONE,
4620                                 NULL, &new_fsp);
4621         
4622         if (!NT_STATUS_IS_OK(status)) {
4623                 /* NB. We check for open_was_deferred in the caller. */
4624                 return status;
4625         }
4626
4627         if (vfs_set_filelen(new_fsp, size) == -1) {
4628                 status = map_nt_error_from_unix(errno);
4629                 close_file(new_fsp,NORMAL_CLOSE);
4630                 return status;
4631         }
4632
4633         close_file(new_fsp,NORMAL_CLOSE);
4634         return NT_STATUS_OK;
4635 }
4636
4637 /****************************************************************************
4638  Deal with SMB_INFO_SET_EA.
4639 ****************************************************************************/
4640
4641 static NTSTATUS smb_info_set_ea(connection_struct *conn,
4642                                 const char *pdata,
4643                                 int total_data,
4644                                 files_struct *fsp,
4645                                 const char *fname)
4646 {
4647         struct ea_list *ea_list = NULL;
4648         TALLOC_CTX *ctx = NULL;
4649         NTSTATUS status = NT_STATUS_OK;
4650
4651         if (total_data < 10) {
4652
4653                 /* OS/2 workplace shell seems to send SET_EA requests of "null"
4654                    length. They seem to have no effect. Bug #3212. JRA */
4655
4656                 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
4657                         /* We're done. We only get EA info in this call. */
4658                         return NT_STATUS_OK;
4659                 }
4660
4661                 return NT_STATUS_INVALID_PARAMETER;
4662         }
4663
4664         if (IVAL(pdata,0) > total_data) {
4665                 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
4666                         IVAL(pdata,0), (unsigned int)total_data));
4667                 return NT_STATUS_INVALID_PARAMETER;
4668         }
4669
4670         ctx = talloc_init("SMB_INFO_SET_EA");
4671         if (!ctx) {
4672                 return NT_STATUS_NO_MEMORY;
4673         }
4674         ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
4675         if (!ea_list) {
4676                 talloc_destroy(ctx);
4677                 return NT_STATUS_INVALID_PARAMETER;
4678         }
4679         status = set_ea(conn, fsp, fname, ea_list);
4680         talloc_destroy(ctx);
4681
4682         return status;
4683 }
4684
4685 /****************************************************************************
4686  Deal with SMB_SET_FILE_DISPOSITION_INFO.
4687 ****************************************************************************/
4688
4689 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
4690                                 const char *pdata,
4691                                 int total_data,
4692                                 files_struct *fsp,
4693                                 const char *fname,
4694                                 SMB_STRUCT_STAT *psbuf)
4695 {
4696         NTSTATUS status = NT_STATUS_OK;
4697         bool delete_on_close;
4698         uint32 dosmode = 0;
4699
4700         if (total_data < 1) {
4701                 return NT_STATUS_INVALID_PARAMETER;
4702         }
4703
4704         if (fsp == NULL) {
4705                 return NT_STATUS_INVALID_HANDLE;
4706         }
4707
4708         delete_on_close = (CVAL(pdata,0) ? True : False);
4709         dosmode = dos_mode(conn, fname, psbuf);
4710
4711         DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
4712                 "delete_on_close = %u\n",
4713                 fsp->fsp_name,
4714                 (unsigned int)dosmode,
4715                 (unsigned int)delete_on_close ));
4716
4717         status = can_set_delete_on_close(fsp, delete_on_close, dosmode);
4718  
4719         if (!NT_STATUS_IS_OK(status)) {
4720                 return status;
4721         }
4722
4723         /* The set is across all open files on this dev/inode pair. */
4724         if (!set_delete_on_close(fsp, delete_on_close, &current_user.ut)) {
4725                 return NT_STATUS_ACCESS_DENIED;
4726         }
4727         return NT_STATUS_OK;
4728 }
4729
4730 /****************************************************************************
4731  Deal with SMB_FILE_POSITION_INFORMATION.
4732 ****************************************************************************/
4733
4734 static NTSTATUS smb_file_position_information(connection_struct *conn,
4735                                 const char *pdata,
4736                                 int total_data,
4737                                 files_struct *fsp)
4738 {
4739         SMB_BIG_UINT position_information;
4740
4741         if (total_data < 8) {
4742                 return NT_STATUS_INVALID_PARAMETER;
4743         }
4744
4745         if (fsp == NULL) {
4746                 /* Ignore on pathname based set. */
4747                 return NT_STATUS_OK;
4748         }
4749
4750         position_information = (SMB_BIG_UINT)IVAL(pdata,0);
4751 #ifdef LARGE_SMB_OFF_T
4752         position_information |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
4753 #else /* LARGE_SMB_OFF_T */
4754         if (IVAL(pdata,4) != 0) {
4755                 /* more than 32 bits? */
4756                 return NT_STATUS_INVALID_PARAMETER;
4757         }
4758 #endif /* LARGE_SMB_OFF_T */
4759
4760         DEBUG(10,("smb_file_position_information: Set file position information for file %s to %.0f\n",
4761                 fsp->fsp_name, (double)position_information ));
4762         fsp->fh->position_information = position_information;
4763         return NT_STATUS_OK;
4764 }
4765
4766 /****************************************************************************
4767  Deal with SMB_FILE_MODE_INFORMATION.
4768 ****************************************************************************/
4769
4770 static NTSTATUS smb_file_mode_information(connection_struct *conn,
4771                                 const char *pdata,
4772                                 int total_data)
4773 {
4774         uint32 mode;
4775
4776         if (total_data < 4) {
4777                 return NT_STATUS_INVALID_PARAMETER;
4778         }
4779         mode = IVAL(pdata,0);
4780         if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
4781                 return NT_STATUS_INVALID_PARAMETER;
4782         }
4783         return NT_STATUS_OK;
4784 }
4785
4786 /****************************************************************************
4787  Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
4788 ****************************************************************************/
4789
4790 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
4791                                        struct smb_request *req,
4792                                        const char *pdata,
4793                                        int total_data,
4794                                        const char *fname)
4795 {
4796         char *link_target = NULL;
4797         const char *newname = fname;
4798         NTSTATUS status = NT_STATUS_OK;
4799         TALLOC_CTX *ctx = talloc_tos();
4800
4801         /* Set a symbolic link. */
4802         /* Don't allow this if follow links is false. */
4803
4804         if (total_data == 0) {
4805                 return NT_STATUS_INVALID_PARAMETER;
4806         }
4807
4808         if (!lp_symlinks(SNUM(conn))) {
4809                 return NT_STATUS_ACCESS_DENIED;
4810         }
4811
4812         srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
4813                     total_data, STR_TERMINATE);
4814
4815         if (!link_target) {
4816                 return NT_STATUS_INVALID_PARAMETER;
4817         }
4818
4819         /* !widelinks forces the target path to be within the share. */
4820         /* This means we can interpret the target as a pathname. */
4821         if (!lp_widelinks(SNUM(conn))) {
4822                 char *rel_name = NULL;
4823                 char *last_dirp = NULL;
4824
4825                 if (*link_target == '/') {
4826                         /* No absolute paths allowed. */
4827                         return NT_STATUS_ACCESS_DENIED;
4828                 }
4829                 rel_name = talloc_strdup(ctx,newname);
4830                 if (!rel_name) {
4831                         return NT_STATUS_NO_MEMORY;
4832                 }
4833                 last_dirp = strrchr_m(rel_name, '/');
4834                 if (last_dirp) {
4835                         last_dirp[1] = '\0';
4836                 } else {
4837                         rel_name = talloc_strdup(ctx,"./");
4838                         if (!rel_name) {
4839                                 return NT_STATUS_NO_MEMORY;
4840                         }
4841                 }
4842                 rel_name = talloc_asprintf_append(rel_name,
4843                                 "%s",
4844                                 link_target);
4845                 if (!rel_name) {
4846                         return NT_STATUS_NO_MEMORY;
4847                 }
4848
4849                 status = check_name(conn, rel_name);
4850                 if (!NT_STATUS_IS_OK(status)) {
4851                         return status;
4852                 }
4853         }
4854
4855         DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
4856                         newname, link_target ));
4857
4858         if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
4859                 return map_nt_error_from_unix(errno);
4860         }
4861
4862         return NT_STATUS_OK;
4863 }
4864
4865 /****************************************************************************
4866  Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
4867 ****************************************************************************/
4868
4869 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
4870                                         struct smb_request *req,
4871                                         const char *pdata, int total_data,
4872                                         const char *fname)
4873 {
4874         char *oldname = NULL;
4875         TALLOC_CTX *ctx = talloc_tos();
4876         NTSTATUS status = NT_STATUS_OK;
4877
4878         /* Set a hard link. */
4879         if (total_data == 0) {
4880                 return NT_STATUS_INVALID_PARAMETER;
4881         }
4882
4883         srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
4884                         total_data, STR_TERMINATE, &status);
4885         if (!NT_STATUS_IS_OK(status)) {
4886                 return status;
4887         }
4888
4889         status = resolve_dfspath(ctx, conn,
4890                                 req->flags2 & FLAGS2_DFS_PATHNAMES,
4891                                 oldname,
4892                                 &oldname);
4893         if (!NT_STATUS_IS_OK(status)) {
4894                 return status;
4895         }
4896
4897         DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
4898                 fname, oldname));
4899
4900         return hardlink_internals(ctx, conn, oldname, fname);
4901 }
4902
4903 /****************************************************************************
4904  Deal with SMB_FILE_RENAME_INFORMATION.
4905 ****************************************************************************/
4906
4907 static NTSTATUS smb_file_rename_information(connection_struct *conn,
4908                                             struct smb_request *req,
4909                                             const char *pdata,
4910                                             int total_data,
4911                                             files_struct *fsp,
4912                                             const char *fname)
4913 {
4914         bool overwrite;
4915         uint32 root_fid;
4916         uint32 len;
4917         char *newname = NULL;
4918         char *base_name = NULL;
4919         bool dest_has_wcard = False;
4920         NTSTATUS status = NT_STATUS_OK;
4921         char *p;
4922         TALLOC_CTX *ctx = talloc_tos();
4923
4924         if (total_data < 13) {
4925                 return NT_STATUS_INVALID_PARAMETER;
4926         }
4927
4928         overwrite = (CVAL(pdata,0) ? True : False);
4929         root_fid = IVAL(pdata,4);
4930         len = IVAL(pdata,8);
4931
4932         if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
4933                 return NT_STATUS_INVALID_PARAMETER;
4934         }
4935
4936         srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
4937                               len, 0, &status,
4938                               &dest_has_wcard);
4939         if (!NT_STATUS_IS_OK(status)) {
4940                 return status;
4941         }
4942
4943         DEBUG(10,("smb_file_rename_information: got name |%s|\n",
4944                                 newname));
4945
4946         status = resolve_dfspath_wcard(ctx, conn,
4947                                        req->flags2 & FLAGS2_DFS_PATHNAMES,
4948                                        newname,
4949                                        &newname,
4950                                        &dest_has_wcard);
4951         if (!NT_STATUS_IS_OK(status)) {
4952                 return status;
4953         }
4954
4955         /* Check the new name has no '/' characters. */
4956         if (strchr_m(newname, '/')) {
4957                 return NT_STATUS_NOT_SUPPORTED;
4958         }
4959
4960         /* Create the base directory. */
4961         base_name = talloc_strdup(ctx, fname);
4962         if (!base_name) {
4963                 return NT_STATUS_NO_MEMORY;
4964         }
4965         p = strrchr_m(base_name, '/');
4966         if (p) {
4967                 p[1] = '\0';
4968         } else {
4969                 base_name = talloc_strdup(ctx, "./");
4970                 if (!base_name) {
4971                         return NT_STATUS_NO_MEMORY;
4972                 }
4973         }
4974         /* Append the new name. */
4975         base_name = talloc_asprintf_append(base_name,
4976                         "%s",
4977                         newname);
4978         if (!base_name) {
4979                 return NT_STATUS_NO_MEMORY;
4980         }
4981
4982         if (fsp) {
4983                 SMB_STRUCT_STAT sbuf;
4984                 char *newname_last_component = NULL;
4985
4986                 ZERO_STRUCT(sbuf);
4987
4988                 status = unix_convert(ctx, conn, newname, False,
4989                                         &newname,
4990                                         &newname_last_component,
4991                                         &sbuf);
4992
4993                 /* If an error we expect this to be
4994                  * NT_STATUS_OBJECT_PATH_NOT_FOUND */
4995
4996                 if (!NT_STATUS_IS_OK(status)
4997                     && !NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
4998                                         status)) {
4999                         return status;
5000                 }
5001
5002                 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
5003                         fsp->fnum, fsp->fsp_name, base_name ));
5004                 status = rename_internals_fsp(conn, fsp, base_name,
5005                                               newname_last_component, 0,
5006                                               overwrite);
5007         } else {
5008                 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
5009                         fname, base_name ));
5010                 status = rename_internals(ctx, conn, req, fname, base_name, 0,
5011                                           overwrite, False, dest_has_wcard);
5012         }
5013
5014         return status;
5015 }
5016
5017 /****************************************************************************
5018  Deal with SMB_SET_POSIX_ACL.
5019 ****************************************************************************/
5020
5021 #if defined(HAVE_POSIX_ACLS)
5022 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
5023                                 const char *pdata,
5024                                 int total_data,
5025                                 files_struct *fsp,
5026                                 const char *fname,
5027                                 SMB_STRUCT_STAT *psbuf)
5028 {
5029         uint16 posix_acl_version;
5030         uint16 num_file_acls;
5031         uint16 num_def_acls;
5032         bool valid_file_acls = True;
5033         bool valid_def_acls = True;
5034
5035         if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
5036                 return NT_STATUS_INVALID_PARAMETER;
5037         }
5038         posix_acl_version = SVAL(pdata,0);
5039         num_file_acls = SVAL(pdata,2);
5040         num_def_acls = SVAL(pdata,4);
5041
5042         if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5043                 valid_file_acls = False;
5044                 num_file_acls = 0;
5045         }
5046
5047         if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5048                 valid_def_acls = False;
5049                 num_def_acls = 0;
5050         }
5051
5052         if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
5053                 return NT_STATUS_INVALID_PARAMETER;
5054         }
5055
5056         if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
5057                         (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
5058                 return NT_STATUS_INVALID_PARAMETER;
5059         }
5060
5061         DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
5062                 fname ? fname : fsp->fsp_name,
5063                 (unsigned int)num_file_acls,
5064                 (unsigned int)num_def_acls));
5065
5066         if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
5067                         pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
5068                 return map_nt_error_from_unix(errno);
5069         }
5070
5071         if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, psbuf, num_def_acls,
5072                         pdata + SMB_POSIX_ACL_HEADER_SIZE +
5073                         (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
5074                 return map_nt_error_from_unix(errno);
5075         }
5076         return NT_STATUS_OK;
5077 }
5078 #endif
5079
5080 /****************************************************************************
5081  Deal with SMB_SET_POSIX_LOCK.
5082 ****************************************************************************/
5083
5084 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
5085                                 const uint8 *inbuf,
5086                                 int length,
5087                                 const char *pdata,
5088                                 int total_data,
5089                                 files_struct *fsp)
5090 {
5091         SMB_BIG_UINT count;
5092         SMB_BIG_UINT offset;
5093         uint32 lock_pid;
5094         bool blocking_lock = False;
5095         enum brl_type lock_type;
5096         NTSTATUS status = NT_STATUS_OK;
5097
5098         if (fsp == NULL || fsp->fh->fd == -1) {
5099                 return NT_STATUS_INVALID_HANDLE;
5100         }
5101
5102         if (total_data != POSIX_LOCK_DATA_SIZE) {
5103                 return NT_STATUS_INVALID_PARAMETER;
5104         }
5105
5106         switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5107                 case POSIX_LOCK_TYPE_READ:
5108                         lock_type = READ_LOCK;
5109                         break;
5110                 case POSIX_LOCK_TYPE_WRITE:
5111                         /* Return the right POSIX-mappable error code for files opened read-only. */
5112                         if (!fsp->can_write) {
5113                                 return NT_STATUS_INVALID_HANDLE;
5114                         }
5115                         lock_type = WRITE_LOCK;
5116                         break;
5117                 case POSIX_LOCK_TYPE_UNLOCK:
5118                         lock_type = UNLOCK_LOCK;
5119                         break;
5120                 default:
5121                         return NT_STATUS_INVALID_PARAMETER;
5122         }
5123
5124         if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
5125                 blocking_lock = False;
5126         } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
5127                 blocking_lock = True;
5128         } else {
5129                 return NT_STATUS_INVALID_PARAMETER;
5130         }
5131
5132         if (!lp_blocking_locks(SNUM(conn))) { 
5133                 blocking_lock = False;
5134         }
5135
5136         lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5137 #if defined(HAVE_LONGLONG)
5138         offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
5139                         ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
5140         count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
5141                         ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
5142 #else /* HAVE_LONGLONG */
5143         offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
5144         count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5145 #endif /* HAVE_LONGLONG */
5146
5147         DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
5148                         "lock_pid = %u, count = %.0f, offset = %.0f\n",
5149                 fsp->fsp_name,
5150                 (unsigned int)lock_type,
5151                 (unsigned int)lock_pid,
5152                 (double)count,
5153                 (double)offset ));
5154
5155         if (lock_type == UNLOCK_LOCK) {
5156                 status = do_unlock(smbd_messaging_context(),
5157                                 fsp,
5158                                 lock_pid,
5159                                 count,
5160                                 offset,
5161                                 POSIX_LOCK);
5162         } else {
5163                 uint32 block_smbpid;
5164
5165                 struct byte_range_lock *br_lck = do_lock(smbd_messaging_context(),
5166                                                         fsp,
5167                                                         lock_pid,
5168                                                         count,
5169                                                         offset,
5170                                                         lock_type,
5171                                                         POSIX_LOCK,
5172                                                         blocking_lock,
5173                                                         &status,
5174                                                         &block_smbpid);
5175
5176                 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
5177                         /*
5178                          * A blocking lock was requested. Package up
5179                          * this smb into a queued request and push it
5180                          * onto the blocking lock queue.
5181                          */
5182                         if(push_blocking_lock_request(br_lck,
5183                                                 (char *)inbuf, length,
5184                                                 fsp,
5185                                                 -1, /* infinite timeout. */
5186                                                 0,
5187                                                 lock_pid,
5188                                                 lock_type,
5189                                                 POSIX_LOCK,
5190                                                 offset,
5191                                                 count,
5192                                                 block_smbpid)) {
5193                                 TALLOC_FREE(br_lck);
5194                                 return status;
5195                         }
5196                 }
5197                 TALLOC_FREE(br_lck);
5198         }
5199
5200         return status;
5201 }
5202
5203 /****************************************************************************
5204  Deal with SMB_INFO_STANDARD.
5205 ****************************************************************************/
5206
5207 static NTSTATUS smb_set_info_standard(connection_struct *conn,
5208                                         const char *pdata,
5209                                         int total_data,
5210                                         files_struct *fsp,
5211                                         const char *fname,
5212                                         const SMB_STRUCT_STAT *psbuf)
5213 {
5214         struct timespec ts[2];
5215
5216         if (total_data < 12) {
5217                 return NT_STATUS_INVALID_PARAMETER;
5218         }
5219
5220         /* access time */
5221         ts[0] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastAccess));
5222         /* write time */
5223         ts[1] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastWrite));
5224
5225         DEBUG(10,("smb_set_info_standard: file %s\n",
5226                 fname ? fname : fsp->fsp_name ));
5227
5228         return smb_set_file_time(conn,
5229                                 fsp,
5230                                 fname,
5231                                 psbuf,
5232                                 ts,
5233                                 true);
5234 }
5235
5236 /****************************************************************************
5237  Deal with SMB_SET_FILE_BASIC_INFO.
5238 ****************************************************************************/
5239
5240 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
5241                                         const char *pdata,
5242                                         int total_data,
5243                                         files_struct *fsp,
5244                                         const char *fname,
5245                                         SMB_STRUCT_STAT *psbuf)
5246 {
5247         /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
5248         struct timespec write_time;
5249         struct timespec changed_time;
5250         uint32 dosmode = 0;
5251         struct timespec ts[2];
5252         NTSTATUS status = NT_STATUS_OK;
5253         bool setting_write_time = true;
5254
5255         if (total_data < 36) {
5256                 return NT_STATUS_INVALID_PARAMETER;
5257         }
5258
5259         /* Set the attributes */
5260         dosmode = IVAL(pdata,32);
5261         status = smb_set_file_dosmode(conn,
5262                                         fname,
5263                                         psbuf,
5264                                         dosmode);
5265         if (!NT_STATUS_IS_OK(status)) {
5266                 return status;
5267         }
5268
5269         /* Ignore create time at offset pdata. */
5270
5271         /* access time */
5272         ts[0] = interpret_long_date(pdata+8);
5273
5274         write_time = interpret_long_date(pdata+16);
5275         changed_time = interpret_long_date(pdata+24);
5276
5277         /* mtime */
5278         ts[1] = timespec_min(&write_time, &changed_time);
5279
5280         if ((timespec_compare(&write_time, &ts[1]) == 1) && !null_timespec(write_time)) {
5281                 ts[1] = write_time;
5282         }
5283
5284         /* Prefer a defined time to an undefined one. */
5285         if (null_timespec(ts[1])) {
5286                 if (null_timespec(write_time)) {
5287                         ts[1] = changed_time;
5288                         setting_write_time = false;
5289                 } else {
5290                         ts[1] = write_time;
5291                 }
5292         }
5293
5294         DEBUG(10,("smb_set_file_basic_info: file %s\n",
5295                 fname ? fname : fsp->fsp_name ));
5296
5297         return smb_set_file_time(conn,
5298                                 fsp,
5299                                 fname,
5300                                 psbuf,
5301                                 ts,
5302                                 setting_write_time);
5303 }
5304
5305 /****************************************************************************
5306  Deal with SMB_SET_FILE_ALLOCATION_INFO.
5307 ****************************************************************************/
5308
5309 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
5310                                              struct smb_request *req,
5311                                         const char *pdata,
5312                                         int total_data,
5313                                         files_struct *fsp,
5314                                         const char *fname,
5315                                         SMB_STRUCT_STAT *psbuf)
5316 {
5317         SMB_BIG_UINT allocation_size = 0;
5318         NTSTATUS status = NT_STATUS_OK;
5319         files_struct *new_fsp = NULL;
5320
5321         if (!VALID_STAT(*psbuf)) {
5322                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5323         }
5324
5325         if (total_data < 8) {
5326                 return NT_STATUS_INVALID_PARAMETER;
5327         }
5328
5329         allocation_size = (SMB_BIG_UINT)IVAL(pdata,0);
5330 #ifdef LARGE_SMB_OFF_T
5331         allocation_size |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
5332 #else /* LARGE_SMB_OFF_T */
5333         if (IVAL(pdata,4) != 0) {
5334                 /* more than 32 bits? */
5335                 return NT_STATUS_INVALID_PARAMETER;
5336         }
5337 #endif /* LARGE_SMB_OFF_T */
5338
5339         DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for file %s to %.0f\n",
5340                         fname, (double)allocation_size ));
5341
5342         if (allocation_size) {
5343                 allocation_size = smb_roundup(conn, allocation_size);
5344         }
5345
5346         DEBUG(10,("smb_set_file_allocation_info: file %s : setting new allocation size to %.0f\n",
5347                         fname, (double)allocation_size ));
5348
5349         if (fsp && fsp->fh->fd != -1) {
5350                 /* Open file handle. */
5351                 /* Only change if needed. */
5352                 if (allocation_size != get_file_size(*psbuf)) {
5353                         if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
5354                                 return map_nt_error_from_unix(errno);
5355                         }
5356                 }
5357                 /* But always update the time. */
5358                 if (null_timespec(fsp->pending_modtime)) {
5359                         /*
5360                          * This is equivalent to a write. Ensure it's seen immediately
5361                          * if there are no pending writes.
5362                          */
5363                         set_filetime(fsp->conn, fsp->fsp_name,
5364                                         timespec_current());
5365                 }
5366                 return NT_STATUS_OK;
5367         }
5368
5369         /* Pathname or stat or directory file. */
5370
5371         status = open_file_ntcreate(conn, req, fname, psbuf,
5372                                 FILE_WRITE_DATA,
5373                                 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5374                                 FILE_OPEN,
5375                                 0,
5376                                 FILE_ATTRIBUTE_NORMAL,
5377                                 FORCE_OPLOCK_BREAK_TO_NONE,
5378                                 NULL, &new_fsp);
5379
5380         if (!NT_STATUS_IS_OK(status)) {
5381                 /* NB. We check for open_was_deferred in the caller. */
5382                 return status;
5383         }
5384
5385         /* Only change if needed. */
5386         if (allocation_size != get_file_size(*psbuf)) {
5387                 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
5388                         status = map_nt_error_from_unix(errno);
5389                         close_file(new_fsp,NORMAL_CLOSE);
5390                         return status;
5391                 }
5392         }
5393
5394         /* Changing the allocation size should set the last mod time. */
5395         /* Don't need to call set_filetime as this will be flushed on
5396          * close. */
5397
5398         fsp_set_pending_modtime(new_fsp, timespec_current());
5399
5400         close_file(new_fsp,NORMAL_CLOSE);
5401         return NT_STATUS_OK;
5402 }
5403
5404 /****************************************************************************
5405  Deal with SMB_SET_FILE_END_OF_FILE_INFO.
5406 ****************************************************************************/
5407
5408 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
5409                                               struct smb_request *req,
5410                                         const char *pdata,
5411                                         int total_data,
5412                                         files_struct *fsp,
5413                                         const char *fname,
5414                                         SMB_STRUCT_STAT *psbuf)
5415 {
5416         SMB_OFF_T size;
5417
5418         if (total_data < 8) {
5419                 return NT_STATUS_INVALID_PARAMETER;
5420         }
5421
5422         size = IVAL(pdata,0);
5423 #ifdef LARGE_SMB_OFF_T
5424         size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5425 #else /* LARGE_SMB_OFF_T */
5426         if (IVAL(pdata,4) != 0) {
5427                 /* more than 32 bits? */
5428                 return NT_STATUS_INVALID_PARAMETER;
5429         }
5430 #endif /* LARGE_SMB_OFF_T */
5431         DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
5432                 "file %s to %.0f\n", fname, (double)size ));
5433
5434         return smb_set_file_size(conn, req,
5435                                 fsp,
5436                                 fname,
5437                                 psbuf,
5438                                 size);
5439 }
5440
5441 /****************************************************************************
5442  Allow a UNIX info mknod.
5443 ****************************************************************************/
5444
5445 static NTSTATUS smb_unix_mknod(connection_struct *conn,
5446                                         const char *pdata,
5447                                         int total_data,
5448                                         const char *fname,
5449                                         SMB_STRUCT_STAT *psbuf)
5450 {
5451         uint32 file_type = IVAL(pdata,56);
5452 #if defined(HAVE_MAKEDEV)
5453         uint32 dev_major = IVAL(pdata,60);
5454         uint32 dev_minor = IVAL(pdata,68);
5455 #endif
5456         SMB_DEV_T dev = (SMB_DEV_T)0;
5457         uint32 raw_unixmode = IVAL(pdata,84);
5458         NTSTATUS status;
5459         mode_t unixmode;
5460
5461         if (total_data < 100) {
5462                 return NT_STATUS_INVALID_PARAMETER;
5463         }
5464
5465         status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_FILE, &unixmode);
5466         if (!NT_STATUS_IS_OK(status)) {
5467                 return status;
5468         }
5469
5470 #if defined(HAVE_MAKEDEV)
5471         dev = makedev(dev_major, dev_minor);
5472 #endif
5473
5474         switch (file_type) {
5475 #if defined(S_IFIFO)
5476                 case UNIX_TYPE_FIFO:
5477                         unixmode |= S_IFIFO;
5478                         break;
5479 #endif
5480 #if defined(S_IFSOCK)
5481                 case UNIX_TYPE_SOCKET:
5482                         unixmode |= S_IFSOCK;
5483                         break;
5484 #endif
5485 #if defined(S_IFCHR)
5486                 case UNIX_TYPE_CHARDEV:
5487                         unixmode |= S_IFCHR;
5488                         break;
5489 #endif
5490 #if defined(S_IFBLK)
5491                 case UNIX_TYPE_BLKDEV:
5492                         unixmode |= S_IFBLK;
5493                         break;
5494 #endif
5495                 default:
5496                         return NT_STATUS_INVALID_PARAMETER;
5497         }
5498
5499         DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
5500 0%o for file %s\n", (double)dev, (unsigned int)unixmode, fname ));
5501
5502         /* Ok - do the mknod. */
5503         if (SMB_VFS_MKNOD(conn, fname, unixmode, dev) != 0) {
5504                 return map_nt_error_from_unix(errno);
5505         }
5506
5507         /* If any of the other "set" calls fail we
5508          * don't want to end up with a half-constructed mknod.
5509          */
5510
5511         if (lp_inherit_perms(SNUM(conn))) {
5512                 inherit_access_acl(
5513                         conn, parent_dirname(fname),
5514                         fname, unixmode);
5515         }
5516
5517         if (SMB_VFS_STAT(conn, fname, psbuf) != 0) {
5518                 status = map_nt_error_from_unix(errno);
5519                 SMB_VFS_UNLINK(conn,fname);
5520                 return status;
5521         }
5522         return NT_STATUS_OK;
5523 }
5524
5525 /****************************************************************************
5526  Deal with SMB_SET_FILE_UNIX_BASIC.
5527 ****************************************************************************/
5528
5529 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
5530                                         struct smb_request *req,
5531                                         const char *pdata,
5532                                         int total_data,
5533                                         files_struct *fsp,
5534                                         const char *fname,
5535                                         SMB_STRUCT_STAT *psbuf)
5536 {
5537         struct timespec ts[2];
5538         uint32 raw_unixmode;
5539         mode_t unixmode;
5540         SMB_OFF_T size = 0;
5541         uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
5542         gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
5543         NTSTATUS status = NT_STATUS_OK;
5544         bool delete_on_fail = False;
5545         enum perm_type ptype;
5546
5547         if (total_data < 100) {
5548                 return NT_STATUS_INVALID_PARAMETER;
5549         }
5550
5551         if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
5552            IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
5553                 size=IVAL(pdata,0); /* first 8 Bytes are size */
5554 #ifdef LARGE_SMB_OFF_T
5555                 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5556 #else /* LARGE_SMB_OFF_T */
5557                 if (IVAL(pdata,4) != 0) {
5558                         /* more than 32 bits? */
5559                         return NT_STATUS_INVALID_PARAMETER;
5560                 }
5561 #endif /* LARGE_SMB_OFF_T */
5562         }
5563
5564         ts[0] = interpret_long_date(pdata+24); /* access_time */
5565         ts[1] = interpret_long_date(pdata+32); /* modification_time */
5566         set_owner = (uid_t)IVAL(pdata,40);
5567         set_grp = (gid_t)IVAL(pdata,48);
5568         raw_unixmode = IVAL(pdata,84);
5569
5570         if (VALID_STAT(*psbuf)) {
5571                 if (S_ISDIR(psbuf->st_mode)) {
5572                         ptype = PERM_EXISTING_DIR;
5573                 } else {
5574                         ptype = PERM_EXISTING_FILE;
5575                 }
5576         } else {
5577                 ptype = PERM_NEW_FILE;
5578         }
5579
5580         status = unix_perms_from_wire(conn, psbuf, raw_unixmode, ptype, &unixmode);
5581         if (!NT_STATUS_IS_OK(status)) {
5582                 return status;
5583         }
5584
5585         DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = %s \
5586 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
5587                 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
5588
5589         if (!VALID_STAT(*psbuf)) {
5590                 /*
5591                  * The only valid use of this is to create character and block
5592                  * devices, and named pipes. This is deprecated (IMHO) and 
5593                  * a new info level should be used for mknod. JRA.
5594                  */
5595
5596                 status = smb_unix_mknod(conn,
5597                                         pdata,
5598                                         total_data,
5599                                         fname,
5600                                         psbuf);
5601                 if (!NT_STATUS_IS_OK(status)) {
5602                         return status;
5603                 }
5604
5605                 /* Ensure we don't try and change anything else. */
5606                 raw_unixmode = SMB_MODE_NO_CHANGE;
5607                 size = get_file_size(*psbuf);
5608                 ts[0] = get_atimespec(psbuf);
5609                 ts[1] = get_mtimespec(psbuf);
5610                 /* 
5611                  * We continue here as we might want to change the 
5612                  * owner uid/gid.
5613                  */
5614                 delete_on_fail = True;
5615         }
5616
5617 #if 1
5618         /* Horrible backwards compatibility hack as an old server bug
5619          * allowed a CIFS client bug to remain unnoticed :-(. JRA.
5620          * */
5621
5622         if (!size) {
5623                 size = get_file_size(*psbuf);
5624         }
5625 #endif
5626
5627         /*
5628          * Deal with the UNIX specific mode set.
5629          */
5630
5631         if (raw_unixmode != SMB_MODE_NO_CHANGE) {
5632                 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
5633                         (unsigned int)unixmode, fname ));
5634                 if (SMB_VFS_CHMOD(conn, fname, unixmode) != 0) {
5635                         return map_nt_error_from_unix(errno);
5636                 }
5637         }
5638
5639         /*
5640          * Deal with the UNIX specific uid set.
5641          */
5642
5643         if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (psbuf->st_uid != set_owner)) {
5644                 int ret;
5645
5646                 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing owner %u for path %s\n",
5647                         (unsigned int)set_owner, fname ));
5648
5649                 if (S_ISLNK(psbuf->st_mode)) {
5650                         ret = SMB_VFS_LCHOWN(conn, fname, set_owner, (gid_t)-1);
5651                 } else {
5652                         ret = SMB_VFS_CHOWN(conn, fname, set_owner, (gid_t)-1);
5653                 }
5654
5655                 if (ret != 0) {
5656                         status = map_nt_error_from_unix(errno);
5657                         if (delete_on_fail) {
5658                                 SMB_VFS_UNLINK(conn,fname);
5659                         }
5660                         return status;
5661                 }
5662         }
5663
5664         /*
5665          * Deal with the UNIX specific gid set.
5666          */
5667
5668         if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (psbuf->st_gid != set_grp)) {
5669                 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
5670                         (unsigned int)set_owner, fname ));
5671                 if (SMB_VFS_CHOWN(conn, fname, (uid_t)-1, set_grp) != 0) {
5672                         status = map_nt_error_from_unix(errno);
5673                         if (delete_on_fail) {
5674                                 SMB_VFS_UNLINK(conn,fname);
5675                         }
5676                         return status;
5677                 }
5678         }
5679
5680         /* Deal with any size changes. */
5681
5682         status = smb_set_file_size(conn, req,
5683                                 fsp,
5684                                 fname,
5685                                 psbuf,
5686                                 size);
5687         if (!NT_STATUS_IS_OK(status)) {
5688                 return status;
5689         }
5690
5691         /* Deal with any time changes. */
5692
5693         return smb_set_file_time(conn,
5694                                 fsp,
5695                                 fname,
5696                                 psbuf,
5697                                 ts,
5698                                 true);
5699 }
5700
5701 /****************************************************************************
5702  Deal with SMB_SET_FILE_UNIX_INFO2.
5703 ****************************************************************************/
5704
5705 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
5706                                         struct smb_request *req,
5707                                         const char *pdata,
5708                                         int total_data,
5709                                         files_struct *fsp,
5710                                         const char *fname,
5711                                         SMB_STRUCT_STAT *psbuf)
5712 {
5713         NTSTATUS status;
5714         uint32 smb_fflags;
5715         uint32 smb_fmask;
5716
5717         if (total_data < 116) {
5718                 return NT_STATUS_INVALID_PARAMETER;
5719         }
5720
5721         /* Start by setting all the fields that are common between UNIX_BASIC
5722          * and UNIX_INFO2.
5723          */
5724         status = smb_set_file_unix_basic(conn, req, pdata, total_data,
5725                                 fsp, fname, psbuf);
5726         if (!NT_STATUS_IS_OK(status)) {
5727                 return status;
5728         }
5729
5730         smb_fflags = IVAL(pdata, 108);
5731         smb_fmask = IVAL(pdata, 112);
5732
5733         /* NB: We should only attempt to alter the file flags if the client
5734          * sends a non-zero mask.
5735          */
5736         if (smb_fmask != 0) {
5737                 int stat_fflags = 0;
5738
5739                 if (!map_info2_flags_to_sbuf(psbuf, smb_fflags, smb_fmask,
5740                             &stat_fflags)) {
5741                         /* Client asked to alter a flag we don't understand. */
5742                         return NT_STATUS_INVALID_PARAMETER;
5743                 }
5744
5745                 if (fsp && fsp->fh->fd != -1) {
5746                         /* XXX: we should be  using SMB_VFS_FCHFLAGS here. */
5747                         return NT_STATUS_NOT_SUPPORTED;
5748                 } else {
5749                         if (SMB_VFS_CHFLAGS(conn, fname, stat_fflags) != 0) {
5750                                 return map_nt_error_from_unix(errno);
5751                         }
5752                 }
5753         }
5754
5755         /* XXX: need to add support for changing the create_time here. You
5756          * can do this for paths on Darwin with setattrlist(2). The right way
5757          * to hook this up is probably by extending the VFS utimes interface.
5758          */
5759
5760         return NT_STATUS_OK;
5761 }
5762
5763 /****************************************************************************
5764  Create a directory with POSIX semantics.
5765 ****************************************************************************/
5766
5767 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
5768                                 struct smb_request *req,
5769                                 char **ppdata,
5770                                 int total_data,
5771                                 const char *fname,
5772                                 SMB_STRUCT_STAT *psbuf,
5773                                 int *pdata_return_size)
5774 {
5775         NTSTATUS status = NT_STATUS_OK;
5776         uint32 raw_unixmode = 0;
5777         uint32 mod_unixmode = 0;
5778         mode_t unixmode = (mode_t)0;
5779         files_struct *fsp = NULL;
5780         uint16 info_level_return = 0;
5781         int info;
5782         char *pdata = *ppdata;
5783
5784         if (total_data < 18) {
5785                 return NT_STATUS_INVALID_PARAMETER;
5786         }
5787
5788         raw_unixmode = IVAL(pdata,8);
5789         /* Next 4 bytes are not yet defined. */
5790
5791         status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_DIR, &unixmode);
5792         if (!NT_STATUS_IS_OK(status)) {
5793                 return status;
5794         }
5795
5796         mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
5797
5798         DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
5799                 fname, (unsigned int)unixmode ));
5800
5801         status = open_directory(conn, req,
5802                                 fname,
5803                                 psbuf,
5804                                 FILE_READ_ATTRIBUTES, /* Just a stat open */
5805                                 FILE_SHARE_NONE, /* Ignored for stat opens */
5806                                 FILE_CREATE,
5807                                 0,
5808                                 mod_unixmode,
5809                                 &info,
5810                                 &fsp);
5811
5812         if (NT_STATUS_IS_OK(status)) {
5813                 close_file(fsp, NORMAL_CLOSE);
5814         }
5815
5816         info_level_return = SVAL(pdata,16);
5817  
5818         if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
5819                 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
5820         } else if (info_level_return ==  SMB_QUERY_FILE_UNIX_INFO2) {
5821                 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
5822         } else {
5823                 *pdata_return_size = 12;
5824         }
5825
5826         /* Realloc the data size */
5827         *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
5828         if (*ppdata == NULL) {
5829                 *pdata_return_size = 0;
5830                 return NT_STATUS_NO_MEMORY;
5831         }
5832         pdata = *ppdata;
5833
5834         SSVAL(pdata,0,NO_OPLOCK_RETURN);
5835         SSVAL(pdata,2,0); /* No fnum. */
5836         SIVAL(pdata,4,info); /* Was directory created. */
5837
5838         switch (info_level_return) {
5839                 case SMB_QUERY_FILE_UNIX_BASIC:
5840                         SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
5841                         SSVAL(pdata,10,0); /* Padding. */
5842                         store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
5843                         break;
5844                 case SMB_QUERY_FILE_UNIX_INFO2:
5845                         SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
5846                         SSVAL(pdata,10,0); /* Padding. */
5847                         store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
5848                         break;
5849                 default:
5850                         SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
5851                         SSVAL(pdata,10,0); /* Padding. */
5852                         break;
5853         }
5854
5855         return status;
5856 }
5857
5858 /****************************************************************************
5859  Open/Create a file with POSIX semantics.
5860 ****************************************************************************/
5861
5862 static NTSTATUS smb_posix_open(connection_struct *conn,
5863                                struct smb_request *req,
5864                                 char **ppdata,
5865                                 int total_data,
5866                                 const char *fname,
5867                                 SMB_STRUCT_STAT *psbuf,
5868                                 int *pdata_return_size)
5869 {
5870         bool extended_oplock_granted = False;
5871         char *pdata = *ppdata;
5872         uint32 flags = 0;
5873         uint32 wire_open_mode = 0;
5874         uint32 raw_unixmode = 0;
5875         uint32 mod_unixmode = 0;
5876         uint32 create_disp = 0;
5877         uint32 access_mask = 0;
5878         uint32 create_options = 0;
5879         NTSTATUS status = NT_STATUS_OK;
5880         mode_t unixmode = (mode_t)0;
5881         files_struct *fsp = NULL;
5882         int oplock_request = 0;
5883         int info = 0;
5884         uint16 info_level_return = 0;
5885
5886         if (total_data < 18) {
5887                 return NT_STATUS_INVALID_PARAMETER;
5888         }
5889
5890         flags = IVAL(pdata,0);
5891         oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
5892         if (oplock_request) {
5893                 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
5894         }
5895
5896         wire_open_mode = IVAL(pdata,4);
5897
5898         if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
5899                 return smb_posix_mkdir(conn, req,
5900                                         ppdata,
5901                                         total_data,
5902                                         fname,
5903                                         psbuf,
5904                                         pdata_return_size);
5905         }
5906
5907         switch (wire_open_mode & SMB_ACCMODE) {
5908                 case SMB_O_RDONLY:
5909                         access_mask = FILE_READ_DATA;
5910                         break;
5911                 case SMB_O_WRONLY:
5912                         access_mask = FILE_WRITE_DATA;
5913                         break;
5914                 case SMB_O_RDWR:
5915                         access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
5916                         break;
5917                 default:
5918                         DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
5919                                 (unsigned int)wire_open_mode ));
5920                         return NT_STATUS_INVALID_PARAMETER;
5921         }
5922
5923         wire_open_mode &= ~SMB_ACCMODE;
5924
5925         if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) {
5926                 create_disp = FILE_CREATE;
5927         } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) {
5928                 create_disp = FILE_OVERWRITE_IF;
5929         } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
5930                 create_disp = FILE_OPEN_IF;
5931         } else {
5932                 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
5933                         (unsigned int)wire_open_mode ));
5934                 return NT_STATUS_INVALID_PARAMETER;
5935         }
5936
5937         raw_unixmode = IVAL(pdata,8);
5938         /* Next 4 bytes are not yet defined. */
5939
5940         status = unix_perms_from_wire(conn,
5941                                 psbuf,
5942                                 raw_unixmode,
5943                                 VALID_STAT(*psbuf) ? PERM_EXISTING_FILE : PERM_NEW_FILE,
5944                                 &unixmode);
5945
5946         if (!NT_STATUS_IS_OK(status)) {
5947                 return status;
5948         }
5949
5950         mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
5951
5952         if (wire_open_mode & SMB_O_SYNC) {
5953                 create_options |= FILE_WRITE_THROUGH;
5954         }
5955         if (wire_open_mode & SMB_O_APPEND) {
5956                 access_mask |= FILE_APPEND_DATA;
5957         }
5958         if (wire_open_mode & SMB_O_DIRECT) {
5959                 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
5960         }
5961
5962         DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
5963                 fname,
5964                 (unsigned int)wire_open_mode,
5965                 (unsigned int)unixmode ));
5966
5967         status = open_file_ntcreate(conn, req,
5968                                 fname,
5969                                 psbuf,
5970                                 access_mask,
5971                                 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5972                                 create_disp,
5973                                 0,              /* no create options yet. */
5974                                 mod_unixmode,
5975                                 oplock_request,
5976                                 &info,
5977                                 &fsp);
5978
5979         if (!NT_STATUS_IS_OK(status)) {
5980                 return status;
5981         }
5982
5983         if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
5984                 extended_oplock_granted = True;
5985         }
5986
5987         if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
5988                 extended_oplock_granted = True;
5989         }
5990
5991         info_level_return = SVAL(pdata,16);
5992  
5993         /* Allocate the correct return size. */
5994
5995         if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
5996                 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
5997         } else if (info_level_return ==  SMB_QUERY_FILE_UNIX_INFO2) {
5998                 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
5999         } else {
6000                 *pdata_return_size = 12;
6001         }
6002
6003         /* Realloc the data size */
6004         *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6005         if (*ppdata == NULL) {
6006                 close_file(fsp,ERROR_CLOSE);
6007                 *pdata_return_size = 0;
6008                 return NT_STATUS_NO_MEMORY;
6009         }
6010         pdata = *ppdata;
6011
6012         if (extended_oplock_granted) {
6013                 if (flags & REQUEST_BATCH_OPLOCK) {
6014                         SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
6015                 } else {
6016                         SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
6017                 }
6018         } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
6019                 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
6020         } else {
6021                 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6022         }
6023
6024         SSVAL(pdata,2,fsp->fnum);
6025         SIVAL(pdata,4,info); /* Was file created etc. */
6026
6027         switch (info_level_return) {
6028                 case SMB_QUERY_FILE_UNIX_BASIC:
6029                         SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6030                         SSVAL(pdata,10,0); /* padding. */
6031                         store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
6032                         break;
6033                 case SMB_QUERY_FILE_UNIX_INFO2:
6034                         SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6035                         SSVAL(pdata,10,0); /* padding. */
6036                         store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
6037                         break;
6038                 default:
6039                         SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6040                         SSVAL(pdata,10,0); /* padding. */
6041                         break;
6042         }
6043         return NT_STATUS_OK;
6044 }
6045
6046 /****************************************************************************
6047  Delete a file with POSIX semantics.
6048 ****************************************************************************/
6049
6050 static NTSTATUS smb_posix_unlink(connection_struct *conn,
6051                                  struct smb_request *req,
6052                                 const char *pdata,
6053                                 int total_data,
6054                                 const char *fname,
6055                                 SMB_STRUCT_STAT *psbuf)
6056 {
6057         NTSTATUS status = NT_STATUS_OK;
6058         files_struct *fsp = NULL;
6059         uint16 flags = 0;
6060         char del = 1;
6061         int info = 0;
6062         int i;
6063         struct share_mode_lock *lck = NULL;
6064
6065         if (total_data < 2) {
6066                 return NT_STATUS_INVALID_PARAMETER;
6067         }
6068
6069         flags = SVAL(pdata,0);
6070
6071         if (!VALID_STAT(*psbuf)) {
6072                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6073         }
6074
6075         if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
6076                         !VALID_STAT_OF_DIR(*psbuf)) {
6077                 return NT_STATUS_NOT_A_DIRECTORY;
6078         }
6079
6080         DEBUG(10,("smb_posix_unlink: %s %s\n",
6081                 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
6082                 fname));
6083
6084         if (VALID_STAT_OF_DIR(*psbuf)) {
6085                 status = open_directory(conn, req,
6086                                         fname,
6087                                         psbuf,
6088                                         DELETE_ACCESS,
6089                                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6090                                         FILE_OPEN,
6091                                         0,
6092                                         FILE_FLAG_POSIX_SEMANTICS|0777,
6093                                         &info,
6094                                         &fsp);
6095         } else {
6096
6097                 status = open_file_ntcreate(conn, req,
6098                                 fname,
6099                                 psbuf,
6100                                 DELETE_ACCESS,
6101                                 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6102                                 FILE_OPEN,
6103                                 0,
6104                                 FILE_FLAG_POSIX_SEMANTICS|0777,
6105                                 0, /* No oplock, but break existing ones. */
6106                                 &info,
6107                                 &fsp);
6108         }
6109
6110         if (!NT_STATUS_IS_OK(status)) {
6111                 return status;
6112         }
6113
6114         /*
6115          * Don't lie to client. If we can't really delete due to
6116          * non-POSIX opens return SHARING_VIOLATION.
6117          */
6118
6119         lck = get_share_mode_lock(NULL, fsp->file_id, NULL, NULL);
6120         if (lck == NULL) {
6121                 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
6122                         "lock for file %s\n", fsp->fsp_name));
6123                 close_file(fsp, NORMAL_CLOSE);
6124                 return NT_STATUS_INVALID_PARAMETER;
6125         }
6126
6127         /*
6128          * See if others still have the file open. If this is the case, then
6129          * don't delete. If all opens are POSIX delete we can set the delete
6130          * on close disposition.
6131          */
6132         for (i=0; i<lck->num_share_modes; i++) {
6133                 struct share_mode_entry *e = &lck->share_modes[i];
6134                 if (is_valid_share_mode_entry(e)) {
6135                         if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
6136                                 continue;
6137                         }
6138                         /* Fail with sharing violation. */
6139                         close_file(fsp, NORMAL_CLOSE);
6140                         TALLOC_FREE(lck);
6141                         return NT_STATUS_SHARING_VIOLATION;
6142                 }
6143         }
6144
6145         /*
6146          * Set the delete on close.
6147          */
6148         status = smb_set_file_disposition_info(conn,
6149                                                 &del,
6150                                                 1,
6151                                                 fsp,
6152                                                 fname,
6153                                                 psbuf);
6154
6155         if (!NT_STATUS_IS_OK(status)) {
6156                 close_file(fsp, NORMAL_CLOSE);
6157                 TALLOC_FREE(lck);
6158                 return status;
6159         }
6160         TALLOC_FREE(lck);
6161         return close_file(fsp, NORMAL_CLOSE);
6162 }
6163
6164 /****************************************************************************
6165  Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
6166 ****************************************************************************/
6167
6168 static void call_trans2setfilepathinfo(connection_struct *conn,
6169                                        struct smb_request *req,
6170                                        unsigned int tran_call,
6171                                        char **pparams, int total_params,
6172                                        char **ppdata, int total_data,
6173                                        unsigned int max_data_bytes)
6174 {
6175         char *params = *pparams;
6176         char *pdata = *ppdata;
6177         uint16 info_level;
6178         SMB_STRUCT_STAT sbuf;
6179         char *fname = NULL;
6180         files_struct *fsp = NULL;
6181         NTSTATUS status = NT_STATUS_OK;
6182         int data_return_size = 0;
6183         TALLOC_CTX *ctx = talloc_tos();
6184
6185         if (!params) {
6186                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6187                 return;
6188         }
6189
6190         ZERO_STRUCT(sbuf);
6191
6192         if (tran_call == TRANSACT2_SETFILEINFO) {
6193                 if (total_params < 4) {
6194                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6195                         return;
6196                 }
6197
6198                 fsp = file_fsp(SVAL(params,0));
6199                 /* Basic check for non-null fsp. */
6200                 if (!check_fsp_open(conn, req, fsp, &current_user)) {
6201                         return;
6202                 }
6203                 info_level = SVAL(params,2);
6204
6205                 fname = talloc_strdup(talloc_tos(),fsp->fsp_name);
6206                 if (!fname) {
6207                         reply_nterror(req, NT_STATUS_NO_MEMORY);
6208                         return;
6209                 }
6210
6211                 if(fsp->is_directory || fsp->fh->fd == -1) {
6212                         /*
6213                          * This is actually a SETFILEINFO on a directory
6214                          * handle (returned from an NT SMB). NT5.0 seems
6215                          * to do this call. JRA.
6216                          */
6217                         if (INFO_LEVEL_IS_UNIX(info_level)) {
6218                                 /* Always do lstat for UNIX calls. */
6219                                 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
6220                                         DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
6221                                         reply_unixerror(req,ERRDOS,ERRbadpath);
6222                                         return;
6223                                 }
6224                         } else {
6225                                 if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
6226                                         DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
6227                                         reply_unixerror(req,ERRDOS,ERRbadpath);
6228                                         return;
6229                                 }
6230                         }
6231                 } else if (fsp->print_file) {
6232                         /*
6233                          * Doing a DELETE_ON_CLOSE should cancel a print job.
6234                          */
6235                         if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
6236                                 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
6237
6238                                 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
6239
6240                                 SSVAL(params,0,0);
6241                                 send_trans2_replies(req, params, 2,
6242                                                     *ppdata, 0,
6243                                                     max_data_bytes);
6244                                 return;
6245                         } else {
6246                                 reply_unixerror(req, ERRDOS, ERRbadpath);
6247                                 return;
6248                         }
6249                 } else {
6250                         /*
6251                          * Original code - this is an open file.
6252                          */
6253                         if (!check_fsp(conn, req, fsp, &current_user)) {
6254                                 return;
6255                         }
6256
6257                         if (SMB_VFS_FSTAT(fsp, fsp->fh->fd, &sbuf) != 0) {
6258                                 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
6259                                 reply_unixerror(req, ERRDOS, ERRbadfid);
6260                                 return;
6261                         }
6262                 }
6263         } else {
6264                 /* set path info */
6265                 if (total_params < 7) {
6266                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6267                         return;
6268                 }
6269
6270                 info_level = SVAL(params,0);
6271                 srvstr_get_path(ctx, params, req->flags2, &fname, &params[6],
6272                                 total_params - 6, STR_TERMINATE,
6273                                 &status);
6274                 if (!NT_STATUS_IS_OK(status)) {
6275                         reply_nterror(req, status);
6276                         return;
6277                 }
6278
6279                 status = resolve_dfspath(ctx, conn,
6280                                          req->flags2 & FLAGS2_DFS_PATHNAMES,
6281                                          fname,
6282                                          &fname);
6283                 if (!NT_STATUS_IS_OK(status)) {
6284                         if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6285                                 reply_botherror(req,
6286                                                 NT_STATUS_PATH_NOT_COVERED,
6287                                                 ERRSRV, ERRbadpath);
6288                                 return;
6289                         }
6290                         reply_nterror(req, status);
6291                         return;
6292                 }
6293
6294                 status = unix_convert(ctx, conn, fname, False,
6295                                 &fname, NULL, &sbuf);
6296                 if (!NT_STATUS_IS_OK(status)) {
6297                         reply_nterror(req, status);
6298                         return;
6299                 }
6300
6301                 status = check_name(conn, fname);
6302                 if (!NT_STATUS_IS_OK(status)) {
6303                         reply_nterror(req, status);
6304                         return;
6305                 }
6306
6307                 if (INFO_LEVEL_IS_UNIX(info_level)) {
6308                         /*
6309                          * For CIFS UNIX extensions the target name may not exist.
6310                          */
6311
6312                         /* Always do lstat for UNIX calls. */
6313                         SMB_VFS_LSTAT(conn,fname,&sbuf);
6314
6315                 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf)) {
6316                         DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
6317                         reply_unixerror(req, ERRDOS, ERRbadpath);
6318                         return;
6319                 }
6320         }
6321
6322         if (!CAN_WRITE(conn)) {
6323                 reply_doserror(req, ERRSRV, ERRaccess);
6324                 return;
6325         }
6326
6327         if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
6328                 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6329                 return;
6330         }
6331
6332         DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
6333                 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
6334
6335         /* Realloc the parameter size */
6336         *pparams = (char *)SMB_REALLOC(*pparams,2);
6337         if (*pparams == NULL) {
6338                 reply_nterror(req, NT_STATUS_NO_MEMORY);
6339                 return;
6340         }
6341         params = *pparams;
6342
6343         SSVAL(params,0,0);
6344
6345         if (fsp && !null_timespec(fsp->pending_modtime)) {
6346                 /* the pending modtime overrides the current modtime */
6347                 set_mtimespec(&sbuf, fsp->pending_modtime);
6348         }
6349
6350         switch (info_level) {
6351
6352                 case SMB_INFO_STANDARD:
6353                 {
6354                         status = smb_set_info_standard(conn,
6355                                         pdata,
6356                                         total_data,
6357                                         fsp,
6358                                         fname,
6359                                         &sbuf);
6360                         break;
6361                 }
6362
6363                 case SMB_INFO_SET_EA:
6364                 {
6365                         status = smb_info_set_ea(conn,
6366                                                 pdata,
6367                                                 total_data,
6368                                                 fsp,
6369                                                 fname);
6370                         break;
6371                 }
6372
6373                 case SMB_SET_FILE_BASIC_INFO:
6374                 case SMB_FILE_BASIC_INFORMATION:
6375                 {
6376                         status = smb_set_file_basic_info(conn,
6377                                                         pdata,
6378                                                         total_data,
6379                                                         fsp,
6380                                                         fname,
6381                                                         &sbuf);
6382                         break;
6383                 }
6384
6385                 case SMB_FILE_ALLOCATION_INFORMATION:
6386                 case SMB_SET_FILE_ALLOCATION_INFO:
6387                 {
6388                         status = smb_set_file_allocation_info(conn, req,
6389                                                                 pdata,
6390                                                                 total_data,
6391                                                                 fsp,
6392                                                                 fname,
6393                                                                 &sbuf);
6394                         break;
6395                 }
6396
6397                 case SMB_FILE_END_OF_FILE_INFORMATION:
6398                 case SMB_SET_FILE_END_OF_FILE_INFO:
6399                 {
6400                         status = smb_set_file_end_of_file_info(conn, req,
6401                                                                 pdata,
6402                                                                 total_data,
6403                                                                 fsp,
6404                                                                 fname,
6405                                                                 &sbuf);
6406                         break;
6407                 }
6408
6409                 case SMB_FILE_DISPOSITION_INFORMATION:
6410                 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
6411                 {
6412 #if 0
6413                         /* JRA - We used to just ignore this on a path ? 
6414                          * Shouldn't this be invalid level on a pathname
6415                          * based call ?
6416                          */
6417                         if (tran_call != TRANSACT2_SETFILEINFO) {
6418                                 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6419                         }
6420 #endif
6421                         status = smb_set_file_disposition_info(conn,
6422                                                 pdata,
6423                                                 total_data,
6424                                                 fsp,
6425                                                 fname,
6426                                                 &sbuf);
6427                         break;
6428                 }
6429
6430                 case SMB_FILE_POSITION_INFORMATION:
6431                 {
6432                         status = smb_file_position_information(conn,
6433                                                 pdata,
6434                                                 total_data,
6435                                                 fsp);
6436                         break;
6437                 }
6438
6439                 /* From tridge Samba4 : 
6440                  * MODE_INFORMATION in setfileinfo (I have no
6441                  * idea what "mode information" on a file is - it takes a value of 0,
6442                  * 2, 4 or 6. What could it be?).
6443                  */
6444
6445                 case SMB_FILE_MODE_INFORMATION:
6446                 {
6447                         status = smb_file_mode_information(conn,
6448                                                 pdata,
6449                                                 total_data);
6450                         break;
6451                 }
6452
6453                 /*
6454                  * CIFS UNIX extensions.
6455                  */
6456
6457                 case SMB_SET_FILE_UNIX_BASIC:
6458                 {
6459                         status = smb_set_file_unix_basic(conn, req,
6460                                                         pdata,
6461                                                         total_data,
6462                                                         fsp,
6463                                                         fname,
6464                                                         &sbuf);
6465                         break;
6466                 }
6467
6468                 case SMB_SET_FILE_UNIX_INFO2:
6469                 {
6470                         status = smb_set_file_unix_info2(conn, req,
6471                                                         pdata,
6472                                                         total_data,
6473                                                         fsp,
6474                                                         fname,
6475                                                         &sbuf);
6476                         break;
6477                 }
6478
6479                 case SMB_SET_FILE_UNIX_LINK:
6480                 {
6481                         if (tran_call != TRANSACT2_SETPATHINFO) {
6482                                 /* We must have a pathname for this. */
6483                                 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6484                                 return;
6485                         }
6486                         status = smb_set_file_unix_link(conn, req, pdata,
6487                                                         total_data, fname);
6488                         break;
6489                 }
6490
6491                 case SMB_SET_FILE_UNIX_HLINK:
6492                 {
6493                         if (tran_call != TRANSACT2_SETPATHINFO) {
6494                                 /* We must have a pathname for this. */
6495                                 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6496                                 return;
6497                         }
6498                         status = smb_set_file_unix_hlink(conn, req,
6499                                                          pdata, total_data,
6500                                                          fname);
6501                         break;
6502                 }
6503
6504                 case SMB_FILE_RENAME_INFORMATION:
6505                 {
6506                         status = smb_file_rename_information(conn, req,
6507                                                              pdata, total_data,
6508                                                              fsp, fname);
6509                         break;
6510                 }
6511
6512 #if defined(HAVE_POSIX_ACLS)
6513                 case SMB_SET_POSIX_ACL:
6514                 {
6515                         status = smb_set_posix_acl(conn,
6516                                                 pdata,
6517                                                 total_data,
6518                                                 fsp,
6519                                                 fname,
6520                                                 &sbuf);
6521                         break;
6522                 }
6523 #endif
6524
6525                 case SMB_SET_POSIX_LOCK:
6526                 {
6527                         if (tran_call != TRANSACT2_SETFILEINFO) {
6528                                 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6529                                 return;
6530                         }
6531                         status = smb_set_posix_lock(conn, req->inbuf,
6532                                                     smb_len(req->inbuf) + 4,
6533                                                     pdata, total_data, fsp);
6534                         break;
6535                 }
6536
6537                 case SMB_POSIX_PATH_OPEN:
6538                 {
6539                         if (tran_call != TRANSACT2_SETPATHINFO) {
6540                                 /* We must have a pathname for this. */
6541                                 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6542                                 return;
6543                         }
6544
6545                         status = smb_posix_open(conn, req,
6546                                                 ppdata,
6547                                                 total_data,
6548                                                 fname,
6549                                                 &sbuf,
6550                                                 &data_return_size);
6551                         break;
6552                 }
6553
6554                 case SMB_POSIX_PATH_UNLINK:
6555                 {
6556                         if (tran_call != TRANSACT2_SETPATHINFO) {
6557                                 /* We must have a pathname for this. */
6558                                 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6559                                 return;
6560                         }
6561
6562                         status = smb_posix_unlink(conn, req,
6563                                                 pdata,
6564                                                 total_data,
6565                                                 fname,
6566                                                 &sbuf);
6567                         break;
6568                 }
6569
6570                 default:
6571                         reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6572                         return;
6573         }
6574
6575         
6576         if (!NT_STATUS_IS_OK(status)) {
6577                 if (open_was_deferred(req->mid)) {
6578                         /* We have re-scheduled this call. */
6579                         return;
6580                 }
6581                 if (blocking_lock_was_deferred(req->mid)) {
6582                         /* We have re-scheduled this call. */
6583                         return;
6584                 }
6585                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6586                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6587                                         ERRSRV, ERRbadpath);
6588                         return;
6589                 }
6590                 if (info_level == SMB_POSIX_PATH_OPEN) {
6591                         reply_openerror(req, status);
6592                         return;
6593                 }
6594
6595                 reply_nterror(req, status);
6596                 return;
6597         }
6598
6599         SSVAL(params,0,0);
6600         send_trans2_replies(req, params, 2, *ppdata, data_return_size,
6601                             max_data_bytes);
6602   
6603         return;
6604 }
6605
6606 /****************************************************************************
6607  Reply to a TRANS2_MKDIR (make directory with extended attributes).
6608 ****************************************************************************/
6609
6610 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
6611                              char **pparams, int total_params,
6612                              char **ppdata, int total_data,
6613                              unsigned int max_data_bytes)
6614 {
6615         char *params = *pparams;
6616         char *pdata = *ppdata;
6617         char *directory = NULL;
6618         SMB_STRUCT_STAT sbuf;
6619         NTSTATUS status = NT_STATUS_OK;
6620         struct ea_list *ea_list = NULL;
6621         TALLOC_CTX *ctx = talloc_tos();
6622
6623         if (!CAN_WRITE(conn)) {
6624                 reply_doserror(req, ERRSRV, ERRaccess);
6625                 return;
6626         }
6627
6628         if (total_params < 5) {
6629                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6630                 return;
6631         }
6632
6633         srvstr_get_path(ctx, params, req->flags2, &directory, &params[4],
6634                         total_params - 4, STR_TERMINATE,
6635                         &status);
6636         if (!NT_STATUS_IS_OK(status)) {
6637                 reply_nterror(req, status);
6638                 return;
6639         }
6640
6641         DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
6642
6643         status = unix_convert(ctx, conn, directory, False, &directory, NULL, &sbuf);
6644         if (!NT_STATUS_IS_OK(status)) {
6645                 reply_nterror(req, status);
6646                 return;
6647         }
6648
6649         status = check_name(conn, directory);
6650         if (!NT_STATUS_IS_OK(status)) {
6651                 DEBUG(5,("call_trans2mkdir error (%s)\n", nt_errstr(status)));
6652                 reply_nterror(req, status);
6653                 return;
6654         }
6655
6656         /* Any data in this call is an EA list. */
6657         if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
6658                 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
6659                 return;
6660         }
6661
6662         /*
6663          * OS/2 workplace shell seems to send SET_EA requests of "null"
6664          * length (4 bytes containing IVAL 4).
6665          * They seem to have no effect. Bug #3212. JRA.
6666          */
6667
6668         if (total_data != 4) {
6669                 if (total_data < 10) {
6670                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6671                         return;
6672                 }
6673
6674                 if (IVAL(pdata,0) > total_data) {
6675                         DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
6676                                 IVAL(pdata,0), (unsigned int)total_data));
6677                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6678                         return;
6679                 }
6680
6681                 ea_list = read_ea_list(talloc_tos(), pdata + 4,
6682                                        total_data - 4);
6683                 if (!ea_list) {
6684                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6685                         return;
6686                 }
6687         } else if (IVAL(pdata,0) != 4) {
6688                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6689                 return;
6690         }
6691
6692         status = create_directory(conn, directory);
6693
6694         if (!NT_STATUS_IS_OK(status)) {
6695                 reply_nterror(req, status);
6696                 return;
6697         }
6698   
6699         /* Try and set any given EA. */
6700         if (ea_list) {
6701                 status = set_ea(conn, NULL, directory, ea_list);
6702                 if (!NT_STATUS_IS_OK(status)) {
6703                         reply_nterror(req, status);
6704                         return;
6705                 }
6706         }
6707
6708         /* Realloc the parameter and data sizes */
6709         *pparams = (char *)SMB_REALLOC(*pparams,2);
6710         if(*pparams == NULL) {
6711                 reply_nterror(req, NT_STATUS_NO_MEMORY);
6712                 return;
6713         }
6714         params = *pparams;
6715
6716         SSVAL(params,0,0);
6717
6718         send_trans2_replies(req, params, 2, *ppdata, 0, max_data_bytes);
6719   
6720         return;
6721 }
6722
6723 /****************************************************************************
6724  Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
6725  We don't actually do this - we just send a null response.
6726 ****************************************************************************/
6727
6728 static void call_trans2findnotifyfirst(connection_struct *conn,
6729                                        struct smb_request *req,
6730                                        char **pparams, int total_params,
6731                                        char **ppdata, int total_data,
6732                                        unsigned int max_data_bytes)
6733 {
6734         static uint16 fnf_handle = 257;
6735         char *params = *pparams;
6736         uint16 info_level;
6737
6738         if (total_params < 6) {
6739                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6740                 return;
6741         }
6742
6743         info_level = SVAL(params,4);
6744         DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
6745
6746         switch (info_level) {
6747                 case 1:
6748                 case 2:
6749                         break;
6750                 default:
6751                         reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6752                         return;
6753         }
6754
6755         /* Realloc the parameter and data sizes */
6756         *pparams = (char *)SMB_REALLOC(*pparams,6);
6757         if (*pparams == NULL) {
6758                 reply_nterror(req, NT_STATUS_NO_MEMORY);
6759                 return;
6760         }
6761         params = *pparams;
6762
6763         SSVAL(params,0,fnf_handle);
6764         SSVAL(params,2,0); /* No changes */
6765         SSVAL(params,4,0); /* No EA errors */
6766
6767         fnf_handle++;
6768
6769         if(fnf_handle == 0)
6770                 fnf_handle = 257;
6771
6772         send_trans2_replies(req, params, 6, *ppdata, 0, max_data_bytes);
6773   
6774         return;
6775 }
6776
6777 /****************************************************************************
6778  Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for 
6779  changes). Currently this does nothing.
6780 ****************************************************************************/
6781
6782 static void call_trans2findnotifynext(connection_struct *conn,
6783                                       struct smb_request *req,
6784                                       char **pparams, int total_params,
6785                                       char **ppdata, int total_data,
6786                                       unsigned int max_data_bytes)
6787 {
6788         char *params = *pparams;
6789
6790         DEBUG(3,("call_trans2findnotifynext\n"));
6791
6792         /* Realloc the parameter and data sizes */
6793         *pparams = (char *)SMB_REALLOC(*pparams,4);
6794         if (*pparams == NULL) {
6795                 reply_nterror(req, NT_STATUS_NO_MEMORY);
6796                 return;
6797         }
6798         params = *pparams;
6799
6800         SSVAL(params,0,0); /* No changes */
6801         SSVAL(params,2,0); /* No EA errors */
6802
6803         send_trans2_replies(req, params, 4, *ppdata, 0, max_data_bytes);
6804   
6805         return;
6806 }
6807
6808 /****************************************************************************
6809  Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
6810 ****************************************************************************/
6811
6812 static void call_trans2getdfsreferral(connection_struct *conn,
6813                                       struct smb_request *req,
6814                                       char **pparams, int total_params,
6815                                       char **ppdata, int total_data,
6816                                       unsigned int max_data_bytes)
6817 {
6818         char *params = *pparams;
6819         char *pathname = NULL;
6820         int reply_size = 0;
6821         int max_referral_level;
6822         NTSTATUS status = NT_STATUS_OK;
6823         TALLOC_CTX *ctx = talloc_tos();
6824
6825         DEBUG(10,("call_trans2getdfsreferral\n"));
6826
6827         if (total_params < 3) {
6828                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6829                 return;
6830         }
6831
6832         max_referral_level = SVAL(params,0);
6833
6834         if(!lp_host_msdfs()) {
6835                 reply_doserror(req, ERRDOS, ERRbadfunc);
6836                 return;
6837         }
6838
6839         srvstr_pull_talloc(ctx, params, req->flags2, &pathname, &params[2],
6840                     total_params - 2, STR_TERMINATE);
6841         if (!pathname) {
6842                 reply_nterror(req, NT_STATUS_NOT_FOUND);
6843                 return;
6844         }
6845         if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
6846                                             ppdata,&status)) < 0) {
6847                 reply_nterror(req, status);
6848                 return;
6849         }
6850
6851         SSVAL(req->inbuf, smb_flg2,
6852               SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
6853         send_trans2_replies(req,0,0,*ppdata,reply_size, max_data_bytes);
6854
6855         return;
6856 }
6857
6858 #define LMCAT_SPL       0x53
6859 #define LMFUNC_GETJOBID 0x60
6860
6861 /****************************************************************************
6862  Reply to a TRANS2_IOCTL - used for OS/2 printing.
6863 ****************************************************************************/
6864
6865 static void call_trans2ioctl(connection_struct *conn,
6866                              struct smb_request *req,
6867                              char **pparams, int total_params,
6868                              char **ppdata, int total_data,
6869                              unsigned int max_data_bytes)
6870 {
6871         char *pdata = *ppdata;
6872         files_struct *fsp = file_fsp(SVAL(req->inbuf,smb_vwv15));
6873
6874         /* check for an invalid fid before proceeding */
6875
6876         if (!fsp) {
6877                 reply_doserror(req, ERRDOS, ERRbadfid);
6878                 return;
6879         }
6880
6881         if ((SVAL(req->inbuf,(smb_setup+4)) == LMCAT_SPL)
6882             && (SVAL(req->inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
6883                 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
6884                 if (*ppdata == NULL) {
6885                         reply_nterror(req, NT_STATUS_NO_MEMORY);
6886                         return;
6887                 }
6888                 pdata = *ppdata;
6889
6890                 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
6891                         CAN ACCEPT THIS IN UNICODE. JRA. */
6892
6893                 SSVAL(pdata,0,fsp->rap_print_jobid);                     /* Job number */
6894                 srvstr_push(pdata, req->flags2, pdata + 2,
6895                             global_myname(), 15,
6896                             STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
6897                 srvstr_push(pdata, req->flags2, pdata+18,
6898                             lp_servicename(SNUM(conn)), 13,
6899                             STR_ASCII|STR_TERMINATE); /* Service name */
6900                 send_trans2_replies(req, *pparams, 0, *ppdata, 32,
6901                                     max_data_bytes);
6902                 return;
6903         }
6904
6905         DEBUG(2,("Unknown TRANS2_IOCTL\n"));
6906         reply_doserror(req, ERRSRV, ERRerror);
6907 }
6908
6909 /****************************************************************************
6910  Reply to a SMBfindclose (stop trans2 directory search).
6911 ****************************************************************************/
6912
6913 void reply_findclose(connection_struct *conn, struct smb_request *req)
6914 {
6915         int dptr_num;
6916
6917         START_PROFILE(SMBfindclose);
6918
6919         if (req->wct < 1) {
6920                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6921                 END_PROFILE(SMBfindclose);
6922                 return;
6923         }
6924
6925         dptr_num = SVALS(req->inbuf,smb_vwv0);
6926
6927         DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
6928
6929         dptr_close(&dptr_num);
6930
6931         reply_outbuf(req, 0, 0);
6932
6933         DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
6934
6935         END_PROFILE(SMBfindclose);
6936         return;
6937 }
6938
6939 /****************************************************************************
6940  Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
6941 ****************************************************************************/
6942
6943 void reply_findnclose(connection_struct *conn, struct smb_request *req)
6944 {
6945         int dptr_num;
6946
6947         START_PROFILE(SMBfindnclose);
6948
6949         if (req->wct < 1) {
6950                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6951                 END_PROFILE(SMBfindnclose);
6952                 return;
6953         }
6954         
6955         dptr_num = SVAL(req->inbuf,smb_vwv0);
6956
6957         DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
6958
6959         /* We never give out valid handles for a 
6960            findnotifyfirst - so any dptr_num is ok here. 
6961            Just ignore it. */
6962
6963         reply_outbuf(req, 0, 0);
6964
6965         DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
6966
6967         END_PROFILE(SMBfindnclose);
6968         return;
6969 }
6970
6971 static void handle_trans2(connection_struct *conn, struct smb_request *req,
6972                           struct trans_state *state)
6973 {
6974         if (Protocol >= PROTOCOL_NT1) {
6975                 req->flags2 |= 0x40; /* IS_LONG_NAME */
6976                 SSVAL(req->inbuf,smb_flg2,req->flags2);
6977         }
6978
6979         /* Now we must call the relevant TRANS2 function */
6980         switch(state->call)  {
6981         case TRANSACT2_OPEN:
6982         {
6983                 START_PROFILE(Trans2_open);
6984                 call_trans2open(conn, req,
6985                                 &state->param, state->total_param,
6986                                 &state->data, state->total_data,
6987                                 state->max_data_return);
6988                 END_PROFILE(Trans2_open);
6989                 break;
6990         }
6991
6992         case TRANSACT2_FINDFIRST:
6993         {
6994                 START_PROFILE(Trans2_findfirst);
6995                 call_trans2findfirst(conn, req,
6996                                      &state->param, state->total_param,
6997                                      &state->data, state->total_data,
6998                                      state->max_data_return);
6999                 END_PROFILE(Trans2_findfirst);
7000                 break;
7001         }
7002
7003         case TRANSACT2_FINDNEXT:
7004         {
7005                 START_PROFILE(Trans2_findnext);
7006                 call_trans2findnext(conn, req,
7007                                     &state->param, state->total_param,
7008                                     &state->data, state->total_data,
7009                                     state->max_data_return);
7010                 END_PROFILE(Trans2_findnext);
7011                 break;
7012         }
7013
7014         case TRANSACT2_QFSINFO:
7015         {
7016                 START_PROFILE(Trans2_qfsinfo);
7017                 call_trans2qfsinfo(conn, req,
7018                                    &state->param, state->total_param,
7019                                    &state->data, state->total_data,
7020                                    state->max_data_return);
7021                 END_PROFILE(Trans2_qfsinfo);
7022             break;
7023         }
7024
7025         case TRANSACT2_SETFSINFO:
7026         {
7027                 START_PROFILE(Trans2_setfsinfo);
7028                 call_trans2setfsinfo(conn, req,
7029                                      &state->param, state->total_param,
7030                                      &state->data, state->total_data,
7031                                      state->max_data_return);
7032                 END_PROFILE(Trans2_setfsinfo);
7033                 break;
7034         }
7035
7036         case TRANSACT2_QPATHINFO:
7037         case TRANSACT2_QFILEINFO:
7038         {
7039                 START_PROFILE(Trans2_qpathinfo);
7040                 call_trans2qfilepathinfo(conn, req, state->call,
7041                                          &state->param, state->total_param,
7042                                          &state->data, state->total_data,
7043                                          state->max_data_return);
7044                 END_PROFILE(Trans2_qpathinfo);
7045                 break;
7046         }
7047
7048         case TRANSACT2_SETPATHINFO:
7049         case TRANSACT2_SETFILEINFO:
7050         {
7051                 START_PROFILE(Trans2_setpathinfo);
7052                 call_trans2setfilepathinfo(conn, req, state->call,
7053                                            &state->param, state->total_param,
7054                                            &state->data, state->total_data,
7055                                            state->max_data_return);
7056                 END_PROFILE(Trans2_setpathinfo);
7057                 break;
7058         }
7059
7060         case TRANSACT2_FINDNOTIFYFIRST:
7061         {
7062                 START_PROFILE(Trans2_findnotifyfirst);
7063                 call_trans2findnotifyfirst(conn, req,
7064                                            &state->param, state->total_param,
7065                                            &state->data, state->total_data,
7066                                            state->max_data_return);
7067                 END_PROFILE(Trans2_findnotifyfirst);
7068                 break;
7069         }
7070
7071         case TRANSACT2_FINDNOTIFYNEXT:
7072         {
7073                 START_PROFILE(Trans2_findnotifynext);
7074                 call_trans2findnotifynext(conn, req,
7075                                           &state->param, state->total_param,
7076                                           &state->data, state->total_data,
7077                                           state->max_data_return);
7078                 END_PROFILE(Trans2_findnotifynext);
7079                 break;
7080         }
7081
7082         case TRANSACT2_MKDIR:
7083         {
7084                 START_PROFILE(Trans2_mkdir);
7085                 call_trans2mkdir(conn, req,
7086                                  &state->param, state->total_param,
7087                                  &state->data, state->total_data,
7088                                  state->max_data_return);
7089                 END_PROFILE(Trans2_mkdir);
7090                 break;
7091         }
7092
7093         case TRANSACT2_GET_DFS_REFERRAL:
7094         {
7095                 START_PROFILE(Trans2_get_dfs_referral);
7096                 call_trans2getdfsreferral(conn, req,
7097                                           &state->param, state->total_param,
7098                                           &state->data, state->total_data,
7099                                           state->max_data_return);
7100                 END_PROFILE(Trans2_get_dfs_referral);
7101                 break;
7102         }
7103
7104         case TRANSACT2_IOCTL:
7105         {
7106                 START_PROFILE(Trans2_ioctl);
7107                 call_trans2ioctl(conn, req,
7108                                  &state->param, state->total_param,
7109                                  &state->data, state->total_data,
7110                                  state->max_data_return);
7111                 END_PROFILE(Trans2_ioctl);
7112                 break;
7113         }
7114
7115         default:
7116                 /* Error in request */
7117                 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
7118                 reply_doserror(req, ERRSRV,ERRerror);
7119         }
7120 }
7121
7122 /****************************************************************************
7123  Reply to a SMBtrans2.
7124  ****************************************************************************/
7125
7126 void reply_trans2(connection_struct *conn, struct smb_request *req)
7127 {
7128         unsigned int dsoff;
7129         unsigned int dscnt;
7130         unsigned int psoff;
7131         unsigned int pscnt;
7132         unsigned int tran_call;
7133         int size;
7134         struct trans_state *state;
7135         NTSTATUS result;
7136
7137         START_PROFILE(SMBtrans2);
7138
7139         if (req->wct < 14) {
7140                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7141                 END_PROFILE(SMBtrans2);
7142                 return;
7143         }
7144
7145         dsoff = SVAL(req->inbuf, smb_dsoff);
7146         dscnt = SVAL(req->inbuf, smb_dscnt);
7147         psoff = SVAL(req->inbuf, smb_psoff);
7148         pscnt = SVAL(req->inbuf, smb_pscnt);
7149         tran_call = SVAL(req->inbuf, smb_setup0);
7150         size = smb_len(req->inbuf) + 4;
7151
7152         result = allow_new_trans(conn->pending_trans, req->mid);
7153         if (!NT_STATUS_IS_OK(result)) {
7154                 DEBUG(2, ("Got invalid trans2 request: %s\n",
7155                           nt_errstr(result)));
7156                 reply_nterror(req, result);
7157                 END_PROFILE(SMBtrans2);
7158                 return;
7159         }
7160
7161         if (IS_IPC(conn) && (tran_call != TRANSACT2_OPEN)
7162             && (tran_call != TRANSACT2_GET_DFS_REFERRAL)
7163             && (tran_call != TRANSACT2_QFILEINFO)) {
7164                 reply_doserror(req, ERRSRV, ERRaccess);
7165                 END_PROFILE(SMBtrans2);
7166                 return;
7167         }
7168
7169         if ((state = TALLOC_P(conn->mem_ctx, struct trans_state)) == NULL) {
7170                 DEBUG(0, ("talloc failed\n"));
7171                 reply_nterror(req, NT_STATUS_NO_MEMORY);
7172                 END_PROFILE(SMBtrans2);
7173                 return;
7174         }
7175
7176         state->cmd = SMBtrans2;
7177
7178         state->mid = req->mid;
7179         state->vuid = req->vuid;
7180         state->setup_count = SVAL(req->inbuf, smb_suwcnt);
7181         state->setup = NULL;
7182         state->total_param = SVAL(req->inbuf, smb_tpscnt);
7183         state->param = NULL;
7184         state->total_data =  SVAL(req->inbuf, smb_tdscnt);
7185         state->data = NULL;
7186         state->max_param_return = SVAL(req->inbuf, smb_mprcnt);
7187         state->max_data_return  = SVAL(req->inbuf, smb_mdrcnt);
7188         state->max_setup_return = SVAL(req->inbuf, smb_msrcnt);
7189         state->close_on_completion = BITSETW(req->inbuf+smb_vwv5,0);
7190         state->one_way = BITSETW(req->inbuf+smb_vwv5,1);
7191
7192         state->call = tran_call;
7193
7194         /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
7195            is so as a sanity check */
7196         if (state->setup_count != 1) {
7197                 /*
7198                  * Need to have rc=0 for ioctl to get job id for OS/2.
7199                  *  Network printing will fail if function is not successful.
7200                  *  Similar function in reply.c will be used if protocol
7201                  *  is LANMAN1.0 instead of LM1.2X002.
7202                  *  Until DosPrintSetJobInfo with PRJINFO3 is supported,
7203                  *  outbuf doesn't have to be set(only job id is used).
7204                  */
7205                 if ( (state->setup_count == 4)
7206                      && (tran_call == TRANSACT2_IOCTL)
7207                      && (SVAL(req->inbuf,(smb_setup+4)) == LMCAT_SPL)
7208                      && (SVAL(req->inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
7209                         DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
7210                 } else {
7211                         DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
7212                         DEBUG(2,("Transaction is %d\n",tran_call));
7213                         TALLOC_FREE(state);
7214                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7215                         END_PROFILE(SMBtrans2);
7216                         return;
7217                 }
7218         }
7219
7220         if ((dscnt > state->total_data) || (pscnt > state->total_param))
7221                 goto bad_param;
7222
7223         if (state->total_data) {
7224                 /* Can't use talloc here, the core routines do realloc on the
7225                  * params and data. */
7226                 state->data = (char *)SMB_MALLOC(state->total_data);
7227                 if (state->data == NULL) {
7228                         DEBUG(0,("reply_trans2: data malloc fail for %u "
7229                                  "bytes !\n", (unsigned int)state->total_data));
7230                         TALLOC_FREE(state);
7231                         reply_nterror(req, NT_STATUS_NO_MEMORY);
7232                         END_PROFILE(SMBtrans2);
7233                         return;
7234                 }
7235                 if ((dsoff+dscnt < dsoff) || (dsoff+dscnt < dscnt))
7236                         goto bad_param;
7237                 if ((smb_base(req->inbuf)+dsoff+dscnt
7238                      > (char *)req->inbuf + size) ||
7239                     (smb_base(req->inbuf)+dsoff+dscnt < smb_base(req->inbuf)))
7240                         goto bad_param;
7241
7242                 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
7243         }
7244
7245         if (state->total_param) {
7246                 /* Can't use talloc here, the core routines do realloc on the
7247                  * params and data. */
7248                 state->param = (char *)SMB_MALLOC(state->total_param);
7249                 if (state->param == NULL) {
7250                         DEBUG(0,("reply_trans: param malloc fail for %u "
7251                                  "bytes !\n", (unsigned int)state->total_param));
7252                         SAFE_FREE(state->data);
7253                         TALLOC_FREE(state);
7254                         reply_nterror(req, NT_STATUS_NO_MEMORY);
7255                         END_PROFILE(SMBtrans2);
7256                         return;
7257                 } 
7258                 if ((psoff+pscnt < psoff) || (psoff+pscnt < pscnt))
7259                         goto bad_param;
7260                 if ((smb_base(req->inbuf)+psoff+pscnt
7261                      > (char *)req->inbuf + size) ||
7262                     (smb_base(req->inbuf)+psoff+pscnt < smb_base(req->inbuf)))
7263                         goto bad_param;
7264
7265                 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
7266         }
7267
7268         state->received_data  = dscnt;
7269         state->received_param = pscnt;
7270
7271         if ((state->received_param == state->total_param) &&
7272             (state->received_data == state->total_data)) {
7273
7274                 handle_trans2(conn, req, state);
7275
7276                 SAFE_FREE(state->data);
7277                 SAFE_FREE(state->param);
7278                 TALLOC_FREE(state);
7279                 END_PROFILE(SMBtrans2);
7280                 return;
7281         }
7282
7283         DLIST_ADD(conn->pending_trans, state);
7284
7285         /* We need to send an interim response then receive the rest
7286            of the parameter/data bytes */
7287         reply_outbuf(req, 0, 0);
7288         show_msg((char *)req->outbuf);
7289         END_PROFILE(SMBtrans2);
7290         return;
7291
7292   bad_param:
7293
7294         DEBUG(0,("reply_trans2: invalid trans parameters\n"));
7295         SAFE_FREE(state->data);
7296         SAFE_FREE(state->param);
7297         TALLOC_FREE(state);
7298         END_PROFILE(SMBtrans2);
7299         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7300 }
7301
7302
7303 /****************************************************************************
7304  Reply to a SMBtranss2
7305  ****************************************************************************/
7306
7307 void reply_transs2(connection_struct *conn, struct smb_request *req)
7308 {
7309         unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
7310         struct trans_state *state;
7311         int size;
7312
7313         START_PROFILE(SMBtranss2);
7314
7315         show_msg((char *)req->inbuf);
7316
7317         if (req->wct < 8) {
7318                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7319                 END_PROFILE(SMBtranss2);
7320                 return;
7321         }
7322
7323         size = smb_len(req->inbuf)+4;
7324
7325         for (state = conn->pending_trans; state != NULL;
7326              state = state->next) {
7327                 if (state->mid == req->mid) {
7328                         break;
7329                 }
7330         }
7331
7332         if ((state == NULL) || (state->cmd != SMBtrans2)) {
7333                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7334                 END_PROFILE(SMBtranss2);
7335                 return;
7336         }
7337
7338         /* Revise state->total_param and state->total_data in case they have
7339            changed downwards */
7340
7341         if (SVAL(req->inbuf, smb_tpscnt) < state->total_param)
7342                 state->total_param = SVAL(req->inbuf, smb_tpscnt);
7343         if (SVAL(req->inbuf, smb_tdscnt) < state->total_data)
7344                 state->total_data = SVAL(req->inbuf, smb_tdscnt);
7345
7346         pcnt = SVAL(req->inbuf, smb_spscnt);
7347         poff = SVAL(req->inbuf, smb_spsoff);
7348         pdisp = SVAL(req->inbuf, smb_spsdisp);
7349
7350         dcnt = SVAL(req->inbuf, smb_sdscnt);
7351         doff = SVAL(req->inbuf, smb_sdsoff);
7352         ddisp = SVAL(req->inbuf, smb_sdsdisp);
7353
7354         state->received_param += pcnt;
7355         state->received_data += dcnt;
7356                 
7357         if ((state->received_data > state->total_data) ||
7358             (state->received_param > state->total_param))
7359                 goto bad_param;
7360
7361         if (pcnt) {
7362                 if (pdisp+pcnt > state->total_param)
7363                         goto bad_param;
7364                 if ((pdisp+pcnt < pdisp) || (pdisp+pcnt < pcnt))
7365                         goto bad_param;
7366                 if (pdisp > state->total_param)
7367                         goto bad_param;
7368                 if ((smb_base(req->inbuf) + poff + pcnt
7369                      > (char *)req->inbuf + size) ||
7370                     (smb_base(req->inbuf) + poff + pcnt < smb_base(req->inbuf)))
7371                         goto bad_param;
7372                 if (state->param + pdisp < state->param)
7373                         goto bad_param;
7374
7375                 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,
7376                        pcnt);
7377         }
7378
7379         if (dcnt) {
7380                 if (ddisp+dcnt > state->total_data)
7381                         goto bad_param;
7382                 if ((ddisp+dcnt < ddisp) || (ddisp+dcnt < dcnt))
7383                         goto bad_param;
7384                 if (ddisp > state->total_data)
7385                         goto bad_param;
7386                 if ((smb_base(req->inbuf) + doff + dcnt
7387                      > (char *)req->inbuf + size) ||
7388                     (smb_base(req->inbuf) + doff + dcnt < smb_base(req->inbuf)))
7389                         goto bad_param;
7390                 if (state->data + ddisp < state->data)
7391                         goto bad_param;
7392
7393                 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,
7394                        dcnt);      
7395         }
7396
7397         if ((state->received_param < state->total_param) ||
7398             (state->received_data < state->total_data)) {
7399                 END_PROFILE(SMBtranss2);
7400                 return;
7401         }
7402
7403         /*
7404          * construct_reply_common will copy smb_com from inbuf to
7405          * outbuf. SMBtranss2 is wrong here.
7406          */
7407         SCVAL(req->inbuf,smb_com,SMBtrans2);
7408
7409         handle_trans2(conn, req, state);
7410
7411         DLIST_REMOVE(conn->pending_trans, state);
7412         SAFE_FREE(state->data);
7413         SAFE_FREE(state->param);
7414         TALLOC_FREE(state);
7415
7416         END_PROFILE(SMBtranss2);
7417         return;
7418
7419   bad_param:
7420
7421         DEBUG(0,("reply_transs2: invalid trans parameters\n"));
7422         DLIST_REMOVE(conn->pending_trans, state);
7423         SAFE_FREE(state->data);
7424         SAFE_FREE(state->param);
7425         TALLOC_FREE(state);
7426         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7427         END_PROFILE(SMBtranss2);
7428         return;
7429 }