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