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