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