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