s3: smbd: Remove the ucf_flags parameter from extract_snapshot_token().
[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                 struct files_struct *old_dirfsp,
4245                 const struct smb_filename *smb_fname_old,
4246                 struct files_struct *new_dirfsp,
4247                 struct smb_filename *smb_fname_new)
4248 {
4249         NTSTATUS status = NT_STATUS_OK;
4250         int ret;
4251         bool ok;
4252         struct smb_filename *parent_fname_old = NULL;
4253         struct smb_filename *base_name_old = NULL;
4254         struct smb_filename *parent_fname_new = NULL;
4255         struct smb_filename *base_name_new = NULL;
4256
4257         /* source must already exist. */
4258         if (!VALID_STAT(smb_fname_old->st)) {
4259                 status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
4260                 goto out;
4261         }
4262
4263         /* No links from a directory. */
4264         if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
4265                 status = NT_STATUS_FILE_IS_A_DIRECTORY;
4266                 goto out;
4267         }
4268
4269         /* Setting a hardlink to/from a stream isn't currently supported. */
4270         ok = is_ntfs_stream_smb_fname(smb_fname_old);
4271         if (ok) {
4272                 DBG_DEBUG("Old name has streams\n");
4273                 status = NT_STATUS_INVALID_PARAMETER;
4274                 goto out;
4275         }
4276         ok = is_ntfs_stream_smb_fname(smb_fname_new);
4277         if (ok) {
4278                 DBG_DEBUG("New name has streams\n");
4279                 status = NT_STATUS_INVALID_PARAMETER;
4280                 goto out;
4281         }
4282
4283         status = parent_pathref(talloc_tos(),
4284                                 conn->cwd_fsp,
4285                                 smb_fname_old,
4286                                 &parent_fname_old,
4287                                 &base_name_old);
4288         if (!NT_STATUS_IS_OK(status)) {
4289                 goto out;
4290         }
4291
4292         status = parent_pathref(talloc_tos(),
4293                                 conn->cwd_fsp,
4294                                 smb_fname_new,
4295                                 &parent_fname_new,
4296                                 &base_name_new);
4297         if (!NT_STATUS_IS_OK(status)) {
4298                 goto out;
4299         }
4300
4301         if (VALID_STAT(smb_fname_new->st)) {
4302                 if (overwrite_if_exists) {
4303                         if (S_ISDIR(smb_fname_new->st.st_ex_mode)) {
4304                                 status = NT_STATUS_FILE_IS_A_DIRECTORY;
4305                                 goto out;
4306                         }
4307                         status = unlink_internals(conn,
4308                                                 req,
4309                                                 FILE_ATTRIBUTE_NORMAL,
4310                                                 NULL, /* new_dirfsp */
4311                                                 smb_fname_new);
4312                         if (!NT_STATUS_IS_OK(status)) {
4313                                 goto out;
4314                         }
4315                 } else {
4316                         /* Disallow if newname already exists. */
4317                         status = NT_STATUS_OBJECT_NAME_COLLISION;
4318                         goto out;
4319                 }
4320         }
4321
4322         DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
4323                   smb_fname_old->base_name, smb_fname_new->base_name));
4324
4325         ret = SMB_VFS_LINKAT(conn,
4326                         parent_fname_old->fsp,
4327                         base_name_old,
4328                         parent_fname_new->fsp,
4329                         base_name_new,
4330                         0);
4331
4332         if (ret != 0) {
4333                 status = map_nt_error_from_unix(errno);
4334                 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
4335                          nt_errstr(status), smb_fname_old->base_name,
4336                          smb_fname_new->base_name));
4337         }
4338
4339   out:
4340
4341         TALLOC_FREE(parent_fname_old);
4342         TALLOC_FREE(parent_fname_new);
4343         return status;
4344 }
4345
4346 /****************************************************************************
4347  Deal with setting the time from any of the setfilepathinfo functions.
4348  NOTE !!!! The check for FILE_WRITE_ATTRIBUTES access must be done *before*
4349  calling this function.
4350 ****************************************************************************/
4351
4352 NTSTATUS smb_set_file_time(connection_struct *conn,
4353                            files_struct *fsp,
4354                            struct smb_filename *smb_fname,
4355                            struct smb_file_time *ft,
4356                            bool setting_write_time)
4357 {
4358         struct files_struct *set_fsp = NULL;
4359         struct timeval_buf tbuf[4];
4360         uint32_t action =
4361                 FILE_NOTIFY_CHANGE_LAST_ACCESS
4362                 |FILE_NOTIFY_CHANGE_LAST_WRITE
4363                 |FILE_NOTIFY_CHANGE_CREATION;
4364         int ret;
4365
4366         if (!VALID_STAT(smb_fname->st)) {
4367                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4368         }
4369
4370         if (fsp == NULL) {
4371                 /* A symlink */
4372                 return NT_STATUS_OK;
4373         }
4374
4375         set_fsp = metadata_fsp(fsp);
4376
4377         /* get some defaults (no modifications) if any info is zero or -1. */
4378         if (is_omit_timespec(&ft->create_time)) {
4379                 action &= ~FILE_NOTIFY_CHANGE_CREATION;
4380         }
4381
4382         if (is_omit_timespec(&ft->atime)) {
4383                 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
4384         }
4385
4386         if (is_omit_timespec(&ft->mtime)) {
4387                 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4388         }
4389
4390         if (!setting_write_time) {
4391                 /* ft->mtime comes from change time, not write time. */
4392                 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4393         }
4394
4395         /* Ensure the resolution is the correct for
4396          * what we can store on this filesystem. */
4397
4398         round_timespec(conn->ts_res, &ft->create_time);
4399         round_timespec(conn->ts_res, &ft->ctime);
4400         round_timespec(conn->ts_res, &ft->atime);
4401         round_timespec(conn->ts_res, &ft->mtime);
4402
4403         DBG_DEBUG("smb_set_filetime: actime: %s\n ",
4404                   timespec_string_buf(&ft->atime, true, &tbuf[0]));
4405         DBG_DEBUG("smb_set_filetime: modtime: %s\n ",
4406                   timespec_string_buf(&ft->mtime, true, &tbuf[1]));
4407         DBG_DEBUG("smb_set_filetime: ctime: %s\n ",
4408                   timespec_string_buf(&ft->ctime, true, &tbuf[2]));
4409         DBG_DEBUG("smb_set_file_time: createtime: %s\n ",
4410                   timespec_string_buf(&ft->create_time, true, &tbuf[3]));
4411
4412         if (setting_write_time) {
4413                 /*
4414                  * This was a Windows setfileinfo on an open file.
4415                  * NT does this a lot. We also need to 
4416                  * set the time here, as it can be read by 
4417                  * FindFirst/FindNext and with the patch for bug #2045
4418                  * in smbd/fileio.c it ensures that this timestamp is
4419                  * kept sticky even after a write. We save the request
4420                  * away and will set it on file close and after a write. JRA.
4421                  */
4422
4423                 DBG_DEBUG("setting pending modtime to %s\n",
4424                           timespec_string_buf(&ft->mtime, true, &tbuf[0]));
4425
4426                 if (set_fsp != NULL) {
4427                         set_sticky_write_time_fsp(set_fsp, ft->mtime);
4428                 } else {
4429                         set_sticky_write_time_path(
4430                                 vfs_file_id_from_sbuf(conn, &smb_fname->st),
4431                                 ft->mtime);
4432                 }
4433         }
4434
4435         DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
4436
4437         ret = file_ntimes(conn, set_fsp, ft);
4438         if (ret != 0) {
4439                 return map_nt_error_from_unix(errno);
4440         }
4441
4442         notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
4443                      smb_fname->base_name);
4444         return NT_STATUS_OK;
4445 }
4446
4447 /****************************************************************************
4448  Deal with setting the dosmode from any of the setfilepathinfo functions.
4449  NB. The check for FILE_WRITE_ATTRIBUTES access on this path must have been
4450  done before calling this function.
4451 ****************************************************************************/
4452
4453 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
4454                                      struct files_struct *fsp,
4455                                      uint32_t dosmode)
4456 {
4457         struct files_struct *dos_fsp = NULL;
4458         uint32_t current_dosmode;
4459         int ret;
4460
4461         if (!VALID_STAT(fsp->fsp_name->st)) {
4462                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4463         }
4464
4465         dos_fsp = metadata_fsp(fsp);
4466
4467         if (dosmode != 0) {
4468                 if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
4469                         dosmode |= FILE_ATTRIBUTE_DIRECTORY;
4470                 } else {
4471                         dosmode &= ~FILE_ATTRIBUTE_DIRECTORY;
4472                 }
4473         }
4474
4475         DBG_DEBUG("dosmode: 0x%" PRIx32 "\n", dosmode);
4476
4477         /* check the mode isn't different, before changing it */
4478         if (dosmode == 0) {
4479                 return NT_STATUS_OK;
4480         }
4481         current_dosmode = fdos_mode(dos_fsp);
4482         if (dosmode == current_dosmode) {
4483                 return NT_STATUS_OK;
4484         }
4485
4486         DBG_DEBUG("file %s : setting dos mode 0x%" PRIx32 "\n",
4487                   fsp_str_dbg(dos_fsp), dosmode);
4488
4489         ret = file_set_dosmode(conn, dos_fsp->fsp_name, dosmode, NULL, false);
4490         if (ret != 0) {
4491                 DBG_WARNING("file_set_dosmode of %s failed: %s\n",
4492                             fsp_str_dbg(dos_fsp), strerror(errno));
4493                 return map_nt_error_from_unix(errno);
4494         }
4495
4496         return NT_STATUS_OK;
4497 }
4498
4499 /****************************************************************************
4500  Deal with setting the size from any of the setfilepathinfo functions.
4501 ****************************************************************************/
4502
4503 static NTSTATUS smb_set_file_size(connection_struct *conn,
4504                                   struct smb_request *req,
4505                                   files_struct *fsp,
4506                                   struct smb_filename *smb_fname,
4507                                   const SMB_STRUCT_STAT *psbuf,
4508                                   off_t size,
4509                                   bool fail_after_createfile)
4510 {
4511         NTSTATUS status = NT_STATUS_OK;
4512         files_struct *new_fsp = NULL;
4513
4514         if (!VALID_STAT(*psbuf)) {
4515                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4516         }
4517
4518         DBG_INFO("size: %"PRIu64", file_size_stat=%"PRIu64"\n",
4519                  (uint64_t)size,
4520                  get_file_size_stat(psbuf));
4521
4522         if (size == get_file_size_stat(psbuf)) {
4523                 if (fsp == NULL) {
4524                         return NT_STATUS_OK;
4525                 }
4526                 if (!fsp->fsp_flags.modified) {
4527                         return NT_STATUS_OK;
4528                 }
4529                 trigger_write_time_update_immediate(fsp);
4530                 return NT_STATUS_OK;
4531         }
4532
4533         DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
4534                   smb_fname_str_dbg(smb_fname), (double)size));
4535
4536         if (fsp &&
4537             !fsp->fsp_flags.is_pathref &&
4538             fsp_get_io_fd(fsp) != -1)
4539         {
4540                 /* Handle based call. */
4541                 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
4542                         return NT_STATUS_ACCESS_DENIED;
4543                 }
4544
4545                 if (vfs_set_filelen(fsp, size) == -1) {
4546                         return map_nt_error_from_unix(errno);
4547                 }
4548                 trigger_write_time_update_immediate(fsp);
4549                 return NT_STATUS_OK;
4550         }
4551
4552         status = SMB_VFS_CREATE_FILE(
4553                 conn,                                   /* conn */
4554                 req,                                    /* req */
4555                 NULL,                                   /* dirfsp */
4556                 smb_fname,                              /* fname */
4557                 FILE_WRITE_DATA,                        /* access_mask */
4558                 (FILE_SHARE_READ | FILE_SHARE_WRITE |   /* share_access */
4559                     FILE_SHARE_DELETE),
4560                 FILE_OPEN,                              /* create_disposition*/
4561                 0,                                      /* create_options */
4562                 FILE_ATTRIBUTE_NORMAL,                  /* file_attributes */
4563                 0,                                      /* oplock_request */
4564                 NULL,                                   /* lease */
4565                 0,                                      /* allocation_size */
4566                 0,                                      /* private_flags */
4567                 NULL,                                   /* sd */
4568                 NULL,                                   /* ea_list */
4569                 &new_fsp,                               /* result */
4570                 NULL,                                   /* pinfo */
4571                 NULL, NULL);                            /* create context */
4572
4573         if (!NT_STATUS_IS_OK(status)) {
4574                 /* NB. We check for open_was_deferred in the caller. */
4575                 return status;
4576         }
4577
4578         /* See RAW-SFILEINFO-END-OF-FILE */
4579         if (fail_after_createfile) {
4580                 close_file_free(req, &new_fsp, NORMAL_CLOSE);
4581                 return NT_STATUS_INVALID_LEVEL;
4582         }
4583
4584         if (vfs_set_filelen(new_fsp, size) == -1) {
4585                 status = map_nt_error_from_unix(errno);
4586                 close_file_free(req, &new_fsp, NORMAL_CLOSE);
4587                 return status;
4588         }
4589
4590         trigger_write_time_update_immediate(new_fsp);
4591         close_file_free(req, &new_fsp, NORMAL_CLOSE);
4592         return NT_STATUS_OK;
4593 }
4594
4595 /****************************************************************************
4596  Deal with SMB_INFO_SET_EA.
4597 ****************************************************************************/
4598
4599 static NTSTATUS smb_info_set_ea(connection_struct *conn,
4600                                 const char *pdata,
4601                                 int total_data,
4602                                 files_struct *fsp,
4603                                 struct smb_filename *smb_fname)
4604 {
4605         struct ea_list *ea_list = NULL;
4606         TALLOC_CTX *ctx = NULL;
4607         NTSTATUS status = NT_STATUS_OK;
4608
4609         if (total_data < 10) {
4610
4611                 /* OS/2 workplace shell seems to send SET_EA requests of "null"
4612                    length. They seem to have no effect. Bug #3212. JRA */
4613
4614                 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
4615                         /* We're done. We only get EA info in this call. */
4616                         return NT_STATUS_OK;
4617                 }
4618
4619                 return NT_STATUS_INVALID_PARAMETER;
4620         }
4621
4622         if (IVAL(pdata,0) > total_data) {
4623                 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
4624                         IVAL(pdata,0), (unsigned int)total_data));
4625                 return NT_STATUS_INVALID_PARAMETER;
4626         }
4627
4628         ctx = talloc_tos();
4629         ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
4630         if (!ea_list) {
4631                 return NT_STATUS_INVALID_PARAMETER;
4632         }
4633
4634         if (fsp == NULL) {
4635                 /*
4636                  * The only way fsp can be NULL here is if
4637                  * smb_fname points at a symlink and
4638                  * and we're in POSIX context.
4639                  * Ensure this is the case.
4640                  *
4641                  * In this case we cannot set the EA.
4642                  */
4643                 SMB_ASSERT(smb_fname->flags & SMB_FILENAME_POSIX_PATH);
4644                 return NT_STATUS_ACCESS_DENIED;
4645         }
4646
4647         status = set_ea(conn, fsp, ea_list);
4648
4649         return status;
4650 }
4651
4652 /****************************************************************************
4653  Deal with SMB_FILE_FULL_EA_INFORMATION set.
4654 ****************************************************************************/
4655
4656 static NTSTATUS smb_set_file_full_ea_info(connection_struct *conn,
4657                                 const char *pdata,
4658                                 int total_data,
4659                                 files_struct *fsp)
4660 {
4661         struct ea_list *ea_list = NULL;
4662         NTSTATUS status;
4663
4664         if (fsp == NULL) {
4665                 return NT_STATUS_INVALID_HANDLE;
4666         }
4667
4668         if (!lp_ea_support(SNUM(conn))) {
4669                 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
4670                         "EA's not supported.\n",
4671                         (unsigned int)total_data));
4672                 return NT_STATUS_EAS_NOT_SUPPORTED;
4673         }
4674
4675         if (total_data < 10) {
4676                 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
4677                         "too small.\n",
4678                         (unsigned int)total_data));
4679                 return NT_STATUS_INVALID_PARAMETER;
4680         }
4681
4682         ea_list = read_nttrans_ea_list(talloc_tos(),
4683                                 pdata,
4684                                 total_data);
4685
4686         if (!ea_list) {
4687                 return NT_STATUS_INVALID_PARAMETER;
4688         }
4689
4690         status = set_ea(conn, fsp, ea_list);
4691
4692         DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
4693                 smb_fname_str_dbg(fsp->fsp_name),
4694                 nt_errstr(status) ));
4695
4696         return status;
4697 }
4698
4699
4700 /****************************************************************************
4701  Deal with SMB_SET_FILE_DISPOSITION_INFO.
4702 ****************************************************************************/
4703
4704 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
4705                                 const char *pdata,
4706                                 int total_data,
4707                                 files_struct *fsp,
4708                                 struct smb_filename *smb_fname)
4709 {
4710         NTSTATUS status = NT_STATUS_OK;
4711         bool delete_on_close;
4712         uint32_t dosmode = 0;
4713
4714         if (total_data < 1) {
4715                 return NT_STATUS_INVALID_PARAMETER;
4716         }
4717
4718         if (fsp == NULL) {
4719                 return NT_STATUS_INVALID_HANDLE;
4720         }
4721
4722         delete_on_close = (CVAL(pdata,0) ? True : False);
4723         dosmode = fdos_mode(fsp);
4724
4725         DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
4726                 "delete_on_close = %u\n",
4727                 smb_fname_str_dbg(smb_fname),
4728                 (unsigned int)dosmode,
4729                 (unsigned int)delete_on_close ));
4730
4731         if (delete_on_close) {
4732                 status = can_set_delete_on_close(fsp, dosmode);
4733                 if (!NT_STATUS_IS_OK(status)) {
4734                         return status;
4735                 }
4736         }
4737
4738         /* The set is across all open files on this dev/inode pair. */
4739         if (!set_delete_on_close(fsp, delete_on_close,
4740                                  conn->session_info->security_token,
4741                                  conn->session_info->unix_token)) {
4742                 return NT_STATUS_ACCESS_DENIED;
4743         }
4744         return NT_STATUS_OK;
4745 }
4746
4747 /****************************************************************************
4748  Deal with SMB_FILE_POSITION_INFORMATION.
4749 ****************************************************************************/
4750
4751 static NTSTATUS smb_file_position_information(connection_struct *conn,
4752                                 const char *pdata,
4753                                 int total_data,
4754                                 files_struct *fsp)
4755 {
4756         uint64_t position_information;
4757
4758         if (total_data < 8) {
4759                 return NT_STATUS_INVALID_PARAMETER;
4760         }
4761
4762         if (fsp == NULL) {
4763                 /* Ignore on pathname based set. */
4764                 return NT_STATUS_OK;
4765         }
4766
4767         position_information = (uint64_t)IVAL(pdata,0);
4768         position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
4769
4770         DEBUG(10,("smb_file_position_information: Set file position "
4771                   "information for file %s to %.0f\n", fsp_str_dbg(fsp),
4772                   (double)position_information));
4773         fh_set_position_information(fsp->fh, position_information);
4774         return NT_STATUS_OK;
4775 }
4776
4777 /****************************************************************************
4778  Deal with SMB_FILE_MODE_INFORMATION.
4779 ****************************************************************************/
4780
4781 static NTSTATUS smb_file_mode_information(connection_struct *conn,
4782                                 const char *pdata,
4783                                 int total_data)
4784 {
4785         uint32_t mode;
4786
4787         if (total_data < 4) {
4788                 return NT_STATUS_INVALID_PARAMETER;
4789         }
4790         mode = IVAL(pdata,0);
4791         if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
4792                 return NT_STATUS_INVALID_PARAMETER;
4793         }
4794         return NT_STATUS_OK;
4795 }
4796
4797 /****************************************************************************
4798  Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
4799 ****************************************************************************/
4800
4801 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
4802                                        struct smb_request *req,
4803                                        const char *pdata,
4804                                        int total_data,
4805                                        struct smb_filename *new_smb_fname)
4806 {
4807         char *link_target = NULL;
4808         struct smb_filename target_fname;
4809         TALLOC_CTX *ctx = talloc_tos();
4810         NTSTATUS status;
4811         int ret;
4812         struct smb_filename *parent_fname = NULL;
4813         struct smb_filename *base_name = NULL;
4814
4815         /* Set a symbolic link. */
4816         /* Don't allow this if follow links is false. */
4817
4818         if (total_data == 0) {
4819                 return NT_STATUS_INVALID_PARAMETER;
4820         }
4821
4822         if (!lp_follow_symlinks(SNUM(conn))) {
4823                 return NT_STATUS_ACCESS_DENIED;
4824         }
4825
4826         srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
4827                     total_data, STR_TERMINATE);
4828
4829         if (!link_target) {
4830                 return NT_STATUS_INVALID_PARAMETER;
4831         }
4832
4833         target_fname = (struct smb_filename) {
4834                 .base_name = link_target,
4835         };
4836
4837         /* Removes @GMT tokens if any */
4838         status = canonicalize_snapshot_path(&target_fname, UCF_GMT_PATHNAME, 0);
4839         if (!NT_STATUS_IS_OK(status)) {
4840                 return status;
4841         }
4842
4843         DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
4844                         new_smb_fname->base_name, link_target ));
4845
4846         status = parent_pathref(talloc_tos(),
4847                                 conn->cwd_fsp,
4848                                 new_smb_fname,
4849                                 &parent_fname,
4850                                 &base_name);
4851         if (!NT_STATUS_IS_OK(status)) {
4852                 return status;
4853         }
4854
4855         ret = SMB_VFS_SYMLINKAT(conn,
4856                         &target_fname,
4857                         parent_fname->fsp,
4858                         base_name);
4859         if (ret != 0) {
4860                 TALLOC_FREE(parent_fname);
4861                 return map_nt_error_from_unix(errno);
4862         }
4863
4864         TALLOC_FREE(parent_fname);
4865         return NT_STATUS_OK;
4866 }
4867
4868 /****************************************************************************
4869  Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
4870 ****************************************************************************/
4871
4872 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
4873                                         struct smb_request *req,
4874                                         const char *pdata, int total_data,
4875                                         struct smb_filename *smb_fname_new)
4876 {
4877         char *oldname = NULL;
4878         struct files_struct *src_dirfsp = NULL;
4879         struct smb_filename *smb_fname_old = NULL;
4880         uint32_t ucf_flags = ucf_flags_from_smb_request(req);
4881         NTTIME old_twrp = 0;
4882         TALLOC_CTX *ctx = talloc_tos();
4883         NTSTATUS status = NT_STATUS_OK;
4884
4885         /* Set a hard link. */
4886         if (total_data == 0) {
4887                 return NT_STATUS_INVALID_PARAMETER;
4888         }
4889
4890         if (req->posix_pathnames) {
4891                 srvstr_get_path_posix(ctx,
4892                         pdata,
4893                         req->flags2,
4894                         &oldname,
4895                         pdata,
4896                         total_data,
4897                         STR_TERMINATE,
4898                         &status);
4899         } else {
4900                 srvstr_get_path(ctx,
4901                         pdata,
4902                         req->flags2,
4903                         &oldname,
4904                         pdata,
4905                         total_data,
4906                         STR_TERMINATE,
4907                         &status);
4908         }
4909         if (!NT_STATUS_IS_OK(status)) {
4910                 return status;
4911         }
4912
4913         DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
4914                 smb_fname_str_dbg(smb_fname_new), oldname));
4915
4916         if (ucf_flags & UCF_GMT_PATHNAME) {
4917                 extract_snapshot_token(oldname, &old_twrp);
4918         }
4919         status = filename_convert_dirfsp(ctx,
4920                                          conn,
4921                                          oldname,
4922                                          ucf_flags,
4923                                          old_twrp,
4924                                          &src_dirfsp,
4925                                          &smb_fname_old);
4926         if (!NT_STATUS_IS_OK(status)) {
4927                 return status;
4928         }
4929
4930         return hardlink_internals(ctx,
4931                                   conn,
4932                                   req,
4933                                   false,
4934                                   src_dirfsp,
4935                                   smb_fname_old,
4936                                   NULL, /* new_dirfsp */
4937                                   smb_fname_new);
4938 }
4939
4940 /****************************************************************************
4941  Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
4942 ****************************************************************************/
4943
4944 static NTSTATUS smb2_file_rename_information(connection_struct *conn,
4945                                             struct smb_request *req,
4946                                             const char *pdata,
4947                                             int total_data,
4948                                             files_struct *fsp,
4949                                             struct smb_filename *smb_fname_src)
4950 {
4951         bool overwrite;
4952         uint32_t len;
4953         char *newname = NULL;
4954         struct files_struct *dst_dirfsp = NULL;
4955         struct smb_filename *smb_fname_dst = NULL;
4956         const char *dst_original_lcomp = NULL;
4957         uint32_t ucf_flags = ucf_flags_from_smb_request(req);
4958         NTTIME dst_twrp = 0;
4959         NTSTATUS status = NT_STATUS_OK;
4960         TALLOC_CTX *ctx = talloc_tos();
4961
4962         if (!fsp) {
4963                 return NT_STATUS_INVALID_HANDLE;
4964         }
4965
4966         if (total_data < 20) {
4967                 return NT_STATUS_INVALID_PARAMETER;
4968         }
4969
4970         overwrite = (CVAL(pdata,0) ? True : False);
4971         len = IVAL(pdata,16);
4972
4973         if (len > (total_data - 20) || (len == 0)) {
4974                 return NT_STATUS_INVALID_PARAMETER;
4975         }
4976
4977         if (req->posix_pathnames) {
4978                 srvstr_get_path_posix(ctx,
4979                                 pdata,
4980                                 req->flags2,
4981                                 &newname,
4982                                 &pdata[20],
4983                                 len,
4984                                 STR_TERMINATE,
4985                                 &status);
4986         } else {
4987                 srvstr_get_path(ctx,
4988                                 pdata,
4989                                 req->flags2,
4990                                 &newname,
4991                                 &pdata[20],
4992                                 len,
4993                                 STR_TERMINATE,
4994                                 &status);
4995         }
4996         if (!NT_STATUS_IS_OK(status)) {
4997                 return status;
4998         }
4999
5000         DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
5001                                 newname));
5002
5003         if (newname[0] == ':') {
5004                 /* Create an smb_fname to call rename_internals_fsp() with. */
5005                 smb_fname_dst = synthetic_smb_fname(talloc_tos(),
5006                                         fsp->base_fsp->fsp_name->base_name,
5007                                         newname,
5008                                         NULL,
5009                                         fsp->base_fsp->fsp_name->twrp,
5010                                         fsp->base_fsp->fsp_name->flags);
5011                 if (smb_fname_dst == NULL) {
5012                         status = NT_STATUS_NO_MEMORY;
5013                         goto out;
5014                 }
5015         } else {
5016                 if (ucf_flags & UCF_GMT_PATHNAME) {
5017                         extract_snapshot_token(newname, &dst_twrp);
5018                 }
5019                 status = filename_convert_dirfsp(ctx,
5020                                                  conn,
5021                                                  newname,
5022                                                  ucf_flags,
5023                                                  dst_twrp,
5024                                                  &dst_dirfsp,
5025                                                  &smb_fname_dst);
5026                 if (!NT_STATUS_IS_OK(status)) {
5027                         goto out;
5028                 }
5029         }
5030
5031         /*
5032          * Set the original last component, since
5033          * rename_internals_fsp() requires it.
5034          */
5035         dst_original_lcomp = get_original_lcomp(smb_fname_dst,
5036                                         conn,
5037                                         newname,
5038                                         ucf_flags);
5039         if (dst_original_lcomp == NULL) {
5040                 status = NT_STATUS_NO_MEMORY;
5041                 goto out;
5042         }
5043
5044         DEBUG(10,("smb2_file_rename_information: "
5045                   "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
5046                   fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
5047                   smb_fname_str_dbg(smb_fname_dst)));
5048         status = rename_internals_fsp(conn,
5049                                 fsp,
5050                                 NULL, /* dst_dirfsp */
5051                                 smb_fname_dst,
5052                                 dst_original_lcomp,
5053                                 (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM),
5054                                 overwrite);
5055
5056  out:
5057         TALLOC_FREE(smb_fname_dst);
5058         return status;
5059 }
5060
5061 static NTSTATUS smb_file_link_information(connection_struct *conn,
5062                                             struct smb_request *req,
5063                                             const char *pdata,
5064                                             int total_data,
5065                                             files_struct *fsp,
5066                                             struct smb_filename *smb_fname_src)
5067 {
5068         bool overwrite;
5069         uint32_t len;
5070         char *newname = NULL;
5071         struct files_struct *dst_dirfsp = NULL;
5072         struct smb_filename *smb_fname_dst = NULL;
5073         NTSTATUS status = NT_STATUS_OK;
5074         uint32_t ucf_flags = ucf_flags_from_smb_request(req);
5075         NTTIME dst_twrp = 0;
5076         TALLOC_CTX *ctx = talloc_tos();
5077
5078         if (!fsp) {
5079                 return NT_STATUS_INVALID_HANDLE;
5080         }
5081
5082         if (total_data < 20) {
5083                 return NT_STATUS_INVALID_PARAMETER;
5084         }
5085
5086         overwrite = (CVAL(pdata,0) ? true : false);
5087         len = IVAL(pdata,16);
5088
5089         if (len > (total_data - 20) || (len == 0)) {
5090                 return NT_STATUS_INVALID_PARAMETER;
5091         }
5092
5093         if (smb_fname_src->flags & SMB_FILENAME_POSIX_PATH) {
5094                 srvstr_get_path_posix(ctx,
5095                                 pdata,
5096                                 req->flags2,
5097                                 &newname,
5098                                 &pdata[20],
5099                                 len,
5100                                 STR_TERMINATE,
5101                                 &status);
5102                 ucf_flags |= UCF_POSIX_PATHNAMES;
5103         } else {
5104                 srvstr_get_path(ctx,
5105                                 pdata,
5106                                 req->flags2,
5107                                 &newname,
5108                                 &pdata[20],
5109                                 len,
5110                                 STR_TERMINATE,
5111                                 &status);
5112         }
5113         if (!NT_STATUS_IS_OK(status)) {
5114                 return status;
5115         }
5116
5117         DEBUG(10,("smb_file_link_information: got name |%s|\n",
5118                                 newname));
5119
5120         if (ucf_flags & UCF_GMT_PATHNAME) {
5121                 extract_snapshot_token(newname, &dst_twrp);
5122         }
5123         status = filename_convert_dirfsp(ctx,
5124                                          conn,
5125                                          newname,
5126                                          ucf_flags,
5127                                          dst_twrp,
5128                                          &dst_dirfsp,
5129                                          &smb_fname_dst);
5130         if (!NT_STATUS_IS_OK(status)) {
5131                 return status;
5132         }
5133
5134         if (fsp->base_fsp) {
5135                 /* No stream names. */
5136                 return NT_STATUS_NOT_SUPPORTED;
5137         }
5138
5139         DEBUG(10,("smb_file_link_information: "
5140                   "SMB_FILE_LINK_INFORMATION (%s) %s -> %s\n",
5141                   fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
5142                   smb_fname_str_dbg(smb_fname_dst)));
5143         status = hardlink_internals(ctx,
5144                                 conn,
5145                                 req,
5146                                 overwrite,
5147                                 NULL, /* src_dirfsp */
5148                                 fsp->fsp_name,
5149                                 dst_dirfsp, /* dst_dirfsp */
5150                                 smb_fname_dst);
5151
5152         TALLOC_FREE(smb_fname_dst);
5153         return status;
5154 }
5155
5156 /****************************************************************************
5157  Deal with SMB_FILE_RENAME_INFORMATION.
5158 ****************************************************************************/
5159
5160 static NTSTATUS smb_file_rename_information(connection_struct *conn,
5161                                             struct smb_request *req,
5162                                             const char *pdata,
5163                                             int total_data,
5164                                             files_struct *fsp,
5165                                             struct smb_filename *smb_fname_src)
5166 {
5167         bool overwrite;
5168         uint32_t root_fid;
5169         uint32_t len;
5170         char *newname = NULL;
5171         struct files_struct *dst_dirfsp = NULL;
5172         struct smb_filename *smb_fname_dst = NULL;
5173         const char *dst_original_lcomp = NULL;
5174         NTSTATUS status = NT_STATUS_OK;
5175         char *p;
5176         TALLOC_CTX *ctx = talloc_tos();
5177
5178         if (total_data < 13) {
5179                 return NT_STATUS_INVALID_PARAMETER;
5180         }
5181
5182         overwrite = (CVAL(pdata,0) != 0);
5183         root_fid = IVAL(pdata,4);
5184         len = IVAL(pdata,8);
5185
5186         if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
5187                 return NT_STATUS_INVALID_PARAMETER;
5188         }
5189
5190         if (req->posix_pathnames) {
5191                 srvstr_get_path_posix(ctx,
5192                                 pdata,
5193                                 req->flags2,
5194                                 &newname,
5195                                 &pdata[12],
5196                                 len,
5197                                 0,
5198                                 &status);
5199         } else {
5200                 srvstr_get_path(ctx,
5201                                 pdata,
5202                                 req->flags2,
5203                                 &newname,
5204                                 &pdata[12],
5205                                 len,
5206                                 0,
5207                                 &status);
5208         }
5209         if (!NT_STATUS_IS_OK(status)) {
5210                 return status;
5211         }
5212
5213         DEBUG(10,("smb_file_rename_information: got name |%s|\n",
5214                                 newname));
5215
5216         /* Check the new name has no '/' characters. */
5217         if (strchr_m(newname, '/')) {
5218                 return NT_STATUS_NOT_SUPPORTED;
5219         }
5220
5221         if (fsp && fsp->base_fsp) {
5222                 /* newname must be a stream name. */
5223                 if (newname[0] != ':') {
5224                         return NT_STATUS_NOT_SUPPORTED;
5225                 }
5226
5227                 /* Create an smb_fname to call rename_internals_fsp() with. */
5228                 smb_fname_dst = synthetic_smb_fname(talloc_tos(),
5229                                         fsp->base_fsp->fsp_name->base_name,
5230                                         newname,
5231                                         NULL,
5232                                         fsp->base_fsp->fsp_name->twrp,
5233                                         fsp->base_fsp->fsp_name->flags);
5234                 if (smb_fname_dst == NULL) {
5235                         status = NT_STATUS_NO_MEMORY;
5236                         goto out;
5237                 }
5238
5239                 /*
5240                  * Get the original last component, since
5241                  * rename_internals_fsp() requires it.
5242                  */
5243                 dst_original_lcomp = get_original_lcomp(smb_fname_dst,
5244                                         conn,
5245                                         newname,
5246                                         0);
5247                 if (dst_original_lcomp == NULL) {
5248                         status = NT_STATUS_NO_MEMORY;
5249                         goto out;
5250                 }
5251
5252         } else {
5253                 /*
5254                  * Build up an smb_fname_dst based on the filename passed in.
5255                  * We basically just strip off the last component, and put on
5256                  * the newname instead.
5257                  */
5258                 char *base_name = NULL;
5259                 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
5260                 NTTIME dst_twrp = 0;
5261
5262                 /* newname must *not* be a stream name. */
5263                 if (newname[0] == ':') {
5264                         return NT_STATUS_NOT_SUPPORTED;
5265                 }
5266
5267                 /*
5268                  * Strip off the last component (filename) of the path passed
5269                  * in.
5270                  */
5271                 base_name = talloc_strdup(ctx, smb_fname_src->base_name);
5272                 if (!base_name) {
5273                         return NT_STATUS_NO_MEMORY;
5274                 }
5275                 p = strrchr_m(base_name, '/');
5276                 if (p) {
5277                         p[1] = '\0';
5278                 } else {
5279                         base_name = talloc_strdup(ctx, "");
5280                         if (!base_name) {
5281                                 return NT_STATUS_NO_MEMORY;
5282                         }
5283                 }
5284                 /* Append the new name. */
5285                 base_name = talloc_asprintf_append(base_name,
5286                                 "%s",
5287                                 newname);
5288                 if (!base_name) {
5289                         return NT_STATUS_NO_MEMORY;
5290                 }
5291
5292                 if (ucf_flags & UCF_GMT_PATHNAME) {
5293                         extract_snapshot_token(base_name, &dst_twrp);
5294                 }
5295                 status = filename_convert_dirfsp(ctx,
5296                                          conn,
5297                                          base_name,
5298                                          ucf_flags,
5299                                          dst_twrp,
5300                                          &dst_dirfsp,
5301                                          &smb_fname_dst);
5302
5303                 if (!NT_STATUS_IS_OK(status)) {
5304                         goto out;
5305                 }
5306                 dst_original_lcomp = get_original_lcomp(smb_fname_dst,
5307                                         conn,
5308                                         newname,
5309                                         ucf_flags);
5310                 if (dst_original_lcomp == NULL) {
5311                         status = NT_STATUS_NO_MEMORY;
5312                         goto out;
5313                 }
5314         }
5315
5316         if (fsp != NULL && fsp->fsp_flags.is_fsa) {
5317                 DEBUG(10,("smb_file_rename_information: "
5318                           "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
5319                           fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
5320                           smb_fname_str_dbg(smb_fname_dst)));
5321                 status = rename_internals_fsp(conn,
5322                                         fsp,
5323                                         dst_dirfsp,
5324                                         smb_fname_dst,
5325                                         dst_original_lcomp,
5326                                         0,
5327                                         overwrite);
5328         } else {
5329                 DEBUG(10,("smb_file_rename_information: "
5330                           "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
5331                           smb_fname_str_dbg(smb_fname_src),
5332                           smb_fname_str_dbg(smb_fname_dst)));
5333                 status = rename_internals(ctx,
5334                                         conn,
5335                                         req,
5336                                         NULL, /* src_dirfsp */
5337                                         smb_fname_src,
5338                                         dst_dirfsp,
5339                                         smb_fname_dst,
5340                                         dst_original_lcomp,
5341                                         0,
5342                                         overwrite,
5343                                         FILE_WRITE_ATTRIBUTES);
5344         }
5345  out:
5346         TALLOC_FREE(smb_fname_dst);
5347         return status;
5348 }
5349
5350 /****************************************************************************
5351  Deal with SMB_SET_POSIX_ACL.
5352 ****************************************************************************/
5353
5354 #if defined(HAVE_POSIX_ACLS)
5355 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
5356                                 struct smb_request *req,
5357                                 const char *pdata,
5358                                 int total_data_in,
5359                                 files_struct *fsp,
5360                                 struct smb_filename *smb_fname)
5361 {
5362         uint16_t posix_acl_version;
5363         uint16_t num_file_acls;
5364         uint16_t num_def_acls;
5365         bool valid_file_acls = true;
5366         bool valid_def_acls = true;
5367         NTSTATUS status;
5368         unsigned int size_needed;
5369         unsigned int total_data;
5370         bool close_fsp = false;
5371
5372         if (total_data_in < 0) {
5373                 status = NT_STATUS_INVALID_PARAMETER;
5374                 goto out;
5375         }
5376
5377         total_data = total_data_in;
5378
5379         if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
5380                 status = NT_STATUS_INVALID_PARAMETER;
5381                 goto out;
5382         }
5383         posix_acl_version = SVAL(pdata,0);
5384         num_file_acls = SVAL(pdata,2);
5385         num_def_acls = SVAL(pdata,4);
5386
5387         if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5388                 valid_file_acls = false;
5389                 num_file_acls = 0;
5390         }
5391
5392         if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5393                 valid_def_acls = false;
5394                 num_def_acls = 0;
5395         }
5396
5397         if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
5398                 status = NT_STATUS_INVALID_PARAMETER;
5399                 goto out;
5400         }
5401
5402         /* Wrap checks. */
5403         if (num_file_acls + num_def_acls < num_file_acls) {
5404                 status = NT_STATUS_INVALID_PARAMETER;
5405                 goto out;
5406         }
5407
5408         size_needed = num_file_acls + num_def_acls;
5409
5410         /*
5411          * (size_needed * SMB_POSIX_ACL_ENTRY_SIZE) must be less
5412          * than UINT_MAX, so check by division.
5413          */
5414         if (size_needed > (UINT_MAX/SMB_POSIX_ACL_ENTRY_SIZE)) {
5415                 status = NT_STATUS_INVALID_PARAMETER;
5416                 goto out;
5417         }
5418
5419         size_needed = size_needed*SMB_POSIX_ACL_ENTRY_SIZE;
5420         if (size_needed + SMB_POSIX_ACL_HEADER_SIZE < size_needed) {
5421                 status = NT_STATUS_INVALID_PARAMETER;
5422                 goto out;
5423         }
5424         size_needed += SMB_POSIX_ACL_HEADER_SIZE;
5425
5426         if (total_data < size_needed) {
5427                 status = NT_STATUS_INVALID_PARAMETER;
5428                 goto out;
5429         }
5430
5431         /*
5432          * Ensure we always operate on a file descriptor, not just
5433          * the filename.
5434          */
5435         if (fsp == NULL || !fsp->fsp_flags.is_fsa) {
5436                 uint32_t access_mask = SEC_STD_WRITE_OWNER|
5437                                         SEC_STD_WRITE_DAC|
5438                                         SEC_STD_READ_CONTROL|
5439                                         FILE_READ_ATTRIBUTES|
5440                                         FILE_WRITE_ATTRIBUTES;
5441
5442                 status = get_posix_fsp(conn,
5443                                         req,
5444                                         smb_fname,
5445                                         access_mask,
5446                                         &fsp);
5447
5448                 if (!NT_STATUS_IS_OK(status)) {
5449                         goto out;
5450                 }
5451                 close_fsp = true;
5452         }
5453
5454         /* Here we know fsp != NULL */
5455         SMB_ASSERT(fsp != NULL);
5456
5457         status = refuse_symlink_fsp(fsp);
5458         if (!NT_STATUS_IS_OK(status)) {
5459                 goto out;
5460         }
5461
5462         /* If we have a default acl, this *must* be a directory. */
5463         if (valid_def_acls && !fsp->fsp_flags.is_directory) {
5464                 DBG_INFO("Can't set default acls on "
5465                          "non-directory %s\n",
5466                          fsp_str_dbg(fsp));
5467                 return NT_STATUS_INVALID_HANDLE;
5468         }
5469
5470         DBG_DEBUG("file %s num_file_acls = %"PRIu16", "
5471                   "num_def_acls = %"PRIu16"\n",
5472                   fsp_str_dbg(fsp),
5473                   num_file_acls,
5474                   num_def_acls);
5475
5476         /* Move pdata to the start of the file ACL entries. */
5477         pdata += SMB_POSIX_ACL_HEADER_SIZE;
5478
5479         if (valid_file_acls) {
5480                 status = set_unix_posix_acl(conn,
5481                                         fsp,
5482                                         num_file_acls,
5483                                         pdata);
5484                 if (!NT_STATUS_IS_OK(status)) {
5485                         goto out;
5486                 }
5487         }
5488
5489         /* Move pdata to the start of the default ACL entries. */
5490         pdata += (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE);
5491
5492         if (valid_def_acls) {
5493                 status = set_unix_posix_default_acl(conn,
5494                                         fsp,
5495                                         num_def_acls,
5496                                         pdata);
5497                 if (!NT_STATUS_IS_OK(status)) {
5498                         goto out;
5499                 }
5500         }
5501
5502         status = NT_STATUS_OK;
5503
5504   out:
5505
5506         if (close_fsp) {
5507                 (void)close_file_free(req, &fsp, NORMAL_CLOSE);
5508         }
5509         return status;
5510 }
5511 #endif
5512
5513 /****************************************************************************
5514  Deal with SMB_SET_FILE_BASIC_INFO.
5515 ****************************************************************************/
5516
5517 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
5518                                         const char *pdata,
5519                                         int total_data,
5520                                         files_struct *fsp,
5521                                         struct smb_filename *smb_fname)
5522 {
5523         /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
5524         struct smb_file_time ft;
5525         uint32_t dosmode = 0;
5526         NTSTATUS status = NT_STATUS_OK;
5527
5528         init_smb_file_time(&ft);
5529
5530         if (total_data < 36) {
5531                 return NT_STATUS_INVALID_PARAMETER;
5532         }
5533
5534         if (fsp == NULL) {
5535                 return NT_STATUS_INVALID_HANDLE;
5536         }
5537
5538         status = check_access_fsp(fsp, FILE_WRITE_ATTRIBUTES);
5539         if (!NT_STATUS_IS_OK(status)) {
5540                 return status;
5541         }
5542
5543         /* Set the attributes */
5544         dosmode = IVAL(pdata,32);
5545         status = smb_set_file_dosmode(conn, fsp, dosmode);
5546         if (!NT_STATUS_IS_OK(status)) {
5547                 return status;
5548         }
5549
5550         /* create time */
5551         ft.create_time = pull_long_date_full_timespec(pdata);
5552
5553         /* access time */
5554         ft.atime = pull_long_date_full_timespec(pdata+8);
5555
5556         /* write time. */
5557         ft.mtime = pull_long_date_full_timespec(pdata+16);
5558
5559         /* change time. */
5560         ft.ctime = pull_long_date_full_timespec(pdata+24);
5561
5562         DEBUG(10, ("smb_set_file_basic_info: file %s\n",
5563                    smb_fname_str_dbg(smb_fname)));
5564
5565         status = smb_set_file_time(conn, fsp, smb_fname, &ft, true);
5566         if (!NT_STATUS_IS_OK(status)) {
5567                 return status;
5568         }
5569
5570         if (fsp->fsp_flags.modified) {
5571                 trigger_write_time_update_immediate(fsp);
5572         }
5573         return NT_STATUS_OK;
5574 }
5575
5576 /****************************************************************************
5577  Deal with SMB_INFO_STANDARD.
5578 ****************************************************************************/
5579
5580 static NTSTATUS smb_set_info_standard(connection_struct *conn,
5581                                         const char *pdata,
5582                                         int total_data,
5583                                         files_struct *fsp,
5584                                         struct smb_filename *smb_fname)
5585 {
5586         NTSTATUS status;
5587         struct smb_file_time ft;
5588
5589         init_smb_file_time(&ft);
5590
5591         if (total_data < 12) {
5592                 return NT_STATUS_INVALID_PARAMETER;
5593         }
5594
5595         if (fsp == NULL) {
5596                 return NT_STATUS_INVALID_HANDLE;
5597         }
5598
5599         /* create time */
5600         ft.create_time = time_t_to_full_timespec(srv_make_unix_date2(pdata));
5601         /* access time */
5602         ft.atime = time_t_to_full_timespec(srv_make_unix_date2(pdata+4));
5603         /* write time */
5604         ft.mtime = time_t_to_full_timespec(srv_make_unix_date2(pdata+8));
5605
5606         DEBUG(10,("smb_set_info_standard: file %s\n",
5607                 smb_fname_str_dbg(smb_fname)));
5608
5609         status = check_access_fsp(fsp, FILE_WRITE_ATTRIBUTES);
5610         if (!NT_STATUS_IS_OK(status)) {
5611                 return status;
5612         }
5613
5614         status = smb_set_file_time(conn, fsp, smb_fname, &ft, true);
5615         if (!NT_STATUS_IS_OK(status)) {
5616                 return status;
5617         }
5618
5619         if (fsp->fsp_flags.modified) {
5620                 trigger_write_time_update_immediate(fsp);
5621         }
5622         return NT_STATUS_OK;
5623 }
5624
5625 /****************************************************************************
5626  Deal with SMB_SET_FILE_ALLOCATION_INFO.
5627 ****************************************************************************/
5628
5629 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
5630                                              struct smb_request *req,
5631                                         const char *pdata,
5632                                         int total_data,
5633                                         files_struct *fsp,
5634                                         struct smb_filename *smb_fname)
5635 {
5636         uint64_t allocation_size = 0;
5637         NTSTATUS status = NT_STATUS_OK;
5638         files_struct *new_fsp = NULL;
5639
5640         if (!VALID_STAT(smb_fname->st)) {
5641                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5642         }
5643
5644         if (total_data < 8) {
5645                 return NT_STATUS_INVALID_PARAMETER;
5646         }
5647
5648         allocation_size = (uint64_t)IVAL(pdata,0);
5649         allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
5650         DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
5651                   "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
5652                   (double)allocation_size));
5653
5654         if (allocation_size) {
5655                 allocation_size = smb_roundup(conn, allocation_size);
5656         }
5657
5658         DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
5659                   "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
5660                   (double)allocation_size));
5661
5662         if (fsp &&
5663             !fsp->fsp_flags.is_pathref &&
5664             fsp_get_io_fd(fsp) != -1)
5665         {
5666                 /* Open file handle. */
5667                 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
5668                         return NT_STATUS_ACCESS_DENIED;
5669                 }
5670
5671                 /* Only change if needed. */
5672                 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
5673                         if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
5674                                 return map_nt_error_from_unix(errno);
5675                         }
5676                 }
5677                 /* But always update the time. */
5678                 /*
5679                  * This is equivalent to a write. Ensure it's seen immediately
5680                  * if there are no pending writes.
5681                  */
5682                 trigger_write_time_update_immediate(fsp);
5683                 return NT_STATUS_OK;
5684         }
5685
5686         /* Pathname or stat or directory file. */
5687         status = SMB_VFS_CREATE_FILE(
5688                 conn,                                   /* conn */
5689                 req,                                    /* req */
5690                 NULL,                                   /* dirfsp */
5691                 smb_fname,                              /* fname */
5692                 FILE_WRITE_DATA,                        /* access_mask */
5693                 (FILE_SHARE_READ | FILE_SHARE_WRITE |   /* share_access */
5694                     FILE_SHARE_DELETE),
5695                 FILE_OPEN,                              /* create_disposition*/
5696                 0,                                      /* create_options */
5697                 FILE_ATTRIBUTE_NORMAL,                  /* file_attributes */
5698                 0,                                      /* oplock_request */
5699                 NULL,                                   /* lease */
5700                 0,                                      /* allocation_size */
5701                 0,                                      /* private_flags */
5702                 NULL,                                   /* sd */
5703                 NULL,                                   /* ea_list */
5704                 &new_fsp,                               /* result */
5705                 NULL,                                   /* pinfo */
5706                 NULL, NULL);                            /* create context */
5707
5708         if (!NT_STATUS_IS_OK(status)) {
5709                 /* NB. We check for open_was_deferred in the caller. */
5710                 return status;
5711         }
5712
5713         /* Only change if needed. */
5714         if (allocation_size != get_file_size_stat(&smb_fname->st)) {
5715                 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
5716                         status = map_nt_error_from_unix(errno);
5717                         close_file_free(req, &new_fsp, NORMAL_CLOSE);
5718                         return status;
5719                 }
5720         }
5721
5722         /* Changing the allocation size should set the last mod time. */
5723         /*
5724          * This is equivalent to a write. Ensure it's seen immediately
5725          * if there are no pending writes.
5726          */
5727         trigger_write_time_update_immediate(new_fsp);
5728         close_file_free(req, &new_fsp, NORMAL_CLOSE);
5729         return NT_STATUS_OK;
5730 }
5731
5732 /****************************************************************************
5733  Deal with SMB_SET_FILE_END_OF_FILE_INFO.
5734 ****************************************************************************/
5735
5736 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
5737                                               struct smb_request *req,
5738                                         const char *pdata,
5739                                         int total_data,
5740                                         files_struct *fsp,
5741                                         struct smb_filename *smb_fname,
5742                                         bool fail_after_createfile)
5743 {
5744         off_t size;
5745
5746         if (total_data < 8) {
5747                 return NT_STATUS_INVALID_PARAMETER;
5748         }
5749
5750         size = IVAL(pdata,0);
5751         size |= (((off_t)IVAL(pdata,4)) << 32);
5752         DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
5753                   "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
5754                   (double)size));
5755
5756         return smb_set_file_size(conn, req,
5757                                 fsp,
5758                                 smb_fname,
5759                                 &smb_fname->st,
5760                                 size,
5761                                 fail_after_createfile);
5762 }
5763
5764 /****************************************************************************
5765  Allow a UNIX info mknod.
5766 ****************************************************************************/
5767
5768 static NTSTATUS smb_unix_mknod(connection_struct *conn,
5769                                         const char *pdata,
5770                                         int total_data,
5771                                         const struct smb_filename *smb_fname)
5772 {
5773         uint32_t file_type = IVAL(pdata,56);
5774 #if defined(HAVE_MAKEDEV)
5775         uint32_t dev_major = IVAL(pdata,60);
5776         uint32_t dev_minor = IVAL(pdata,68);
5777 #endif
5778         SMB_DEV_T dev = (SMB_DEV_T)0;
5779         uint32_t raw_unixmode = IVAL(pdata,84);
5780         NTSTATUS status;
5781         mode_t unixmode;
5782         int ret;
5783         struct smb_filename *parent_fname = NULL;
5784         struct smb_filename *base_name = NULL;
5785
5786         if (total_data < 100) {
5787                 return NT_STATUS_INVALID_PARAMETER;
5788         }
5789
5790         status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
5791                                       PERM_NEW_FILE, &unixmode);
5792         if (!NT_STATUS_IS_OK(status)) {
5793                 return status;
5794         }
5795
5796 #if defined(HAVE_MAKEDEV)
5797         dev = makedev(dev_major, dev_minor);
5798 #endif
5799
5800         switch (file_type) {
5801                 /* We can't create other objects here. */
5802                 case UNIX_TYPE_FILE:
5803                 case UNIX_TYPE_DIR:
5804                 case UNIX_TYPE_SYMLINK:
5805                         return NT_STATUS_ACCESS_DENIED;
5806 #if defined(S_IFIFO)
5807                 case UNIX_TYPE_FIFO:
5808                         unixmode |= S_IFIFO;
5809                         break;
5810 #endif
5811 #if defined(S_IFSOCK)
5812                 case UNIX_TYPE_SOCKET:
5813                         unixmode |= S_IFSOCK;
5814                         break;
5815 #endif
5816 #if defined(S_IFCHR)
5817                 case UNIX_TYPE_CHARDEV:
5818                         /* This is only allowed for root. */
5819                         if (get_current_uid(conn) != sec_initial_uid()) {
5820                                 return NT_STATUS_ACCESS_DENIED;
5821                         }
5822                         unixmode |= S_IFCHR;
5823                         break;
5824 #endif
5825 #if defined(S_IFBLK)
5826                 case UNIX_TYPE_BLKDEV:
5827                         if (get_current_uid(conn) != sec_initial_uid()) {
5828                                 return NT_STATUS_ACCESS_DENIED;
5829                         }
5830                         unixmode |= S_IFBLK;
5831                         break;
5832 #endif
5833                 default:
5834                         return NT_STATUS_INVALID_PARAMETER;
5835         }
5836
5837         DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
5838                   "%.0f mode 0%o for file %s\n", (double)dev,
5839                   (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
5840
5841         status = parent_pathref(talloc_tos(),
5842                                 conn->cwd_fsp,
5843                                 smb_fname,
5844                                 &parent_fname,
5845                                 &base_name);
5846         if (!NT_STATUS_IS_OK(status)) {
5847                 return status;
5848         }
5849
5850         /* Ok - do the mknod. */
5851         ret = SMB_VFS_MKNODAT(conn,
5852                         parent_fname->fsp,
5853                         base_name,
5854                         unixmode,
5855                         dev);
5856
5857         if (ret != 0) {
5858                 TALLOC_FREE(parent_fname);
5859                 return map_nt_error_from_unix(errno);
5860         }
5861
5862         /* If any of the other "set" calls fail we
5863          * don't want to end up with a half-constructed mknod.
5864          */
5865
5866         if (lp_inherit_permissions(SNUM(conn))) {
5867                 inherit_access_posix_acl(conn,
5868                                          parent_fname->fsp,
5869                                          smb_fname,
5870                                          unixmode);
5871         }
5872         TALLOC_FREE(parent_fname);
5873
5874         return NT_STATUS_OK;
5875 }
5876
5877 /****************************************************************************
5878  Deal with SMB_SET_FILE_UNIX_BASIC.
5879 ****************************************************************************/
5880
5881 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
5882                                         struct smb_request *req,
5883                                         const char *pdata,
5884                                         int total_data,
5885                                         files_struct *fsp,
5886                                         struct smb_filename *smb_fname)
5887 {
5888         struct smb_file_time ft;
5889         uint32_t raw_unixmode;
5890         mode_t unixmode;
5891         off_t size = 0;
5892         uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
5893         gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
5894         NTSTATUS status = NT_STATUS_OK;
5895         enum perm_type ptype;
5896         files_struct *all_fsps = NULL;
5897         bool modify_mtime = true;
5898         struct file_id id;
5899         SMB_STRUCT_STAT sbuf;
5900
5901         init_smb_file_time(&ft);
5902
5903         if (total_data < 100) {
5904                 return NT_STATUS_INVALID_PARAMETER;
5905         }
5906
5907         if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
5908            IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
5909                 size=IVAL(pdata,0); /* first 8 Bytes are size */
5910                 size |= (((off_t)IVAL(pdata,4)) << 32);
5911         }
5912
5913         ft.atime = pull_long_date_full_timespec(pdata+24); /* access_time */
5914         ft.mtime = pull_long_date_full_timespec(pdata+32); /* modification_time */
5915         set_owner = (uid_t)IVAL(pdata,40);
5916         set_grp = (gid_t)IVAL(pdata,48);
5917         raw_unixmode = IVAL(pdata,84);
5918
5919         if (VALID_STAT(smb_fname->st)) {
5920                 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
5921                         ptype = PERM_EXISTING_DIR;
5922                 } else {
5923                         ptype = PERM_EXISTING_FILE;
5924                 }
5925         } else {
5926                 ptype = PERM_NEW_FILE;
5927         }
5928
5929         status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
5930                                       ptype, &unixmode);
5931         if (!NT_STATUS_IS_OK(status)) {
5932                 return status;
5933         }
5934
5935         DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
5936                   "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
5937                   smb_fname_str_dbg(smb_fname), (double)size,
5938                   (unsigned int)set_owner, (unsigned int)set_grp,
5939                   (int)raw_unixmode));
5940
5941         sbuf = smb_fname->st;
5942
5943         if (!VALID_STAT(sbuf)) {
5944                 /*
5945                  * The only valid use of this is to create character and block
5946                  * devices, and named pipes. This is deprecated (IMHO) and 
5947                  * a new info level should be used for mknod. JRA.
5948                  */
5949
5950                 return smb_unix_mknod(conn,
5951                                         pdata,
5952                                         total_data,
5953                                         smb_fname);
5954         }
5955
5956 #if 1
5957         /* Horrible backwards compatibility hack as an old server bug
5958          * allowed a CIFS client bug to remain unnoticed :-(. JRA.
5959          * */
5960
5961         if (!size) {
5962                 size = get_file_size_stat(&sbuf);
5963         }
5964 #endif
5965
5966         /*
5967          * Deal with the UNIX specific mode set.
5968          */
5969
5970         if (raw_unixmode != SMB_MODE_NO_CHANGE) {
5971                 int ret;
5972
5973                 if (fsp == NULL || S_ISLNK(smb_fname->st.st_ex_mode)) {
5974                         DBG_WARNING("Can't set mode on symlink %s\n",
5975                                 smb_fname_str_dbg(smb_fname));
5976                         return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5977                 }
5978
5979                 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
5980                           "setting mode 0%o for file %s\n",
5981                           (unsigned int)unixmode,
5982                           smb_fname_str_dbg(smb_fname)));
5983                 ret = SMB_VFS_FCHMOD(fsp, unixmode);
5984                 if (ret != 0) {
5985                         return map_nt_error_from_unix(errno);
5986                 }
5987         }
5988
5989         /*
5990          * Deal with the UNIX specific uid set.
5991          */
5992
5993         if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
5994             (sbuf.st_ex_uid != set_owner)) {
5995                 int ret;
5996
5997                 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
5998                           "changing owner %u for path %s\n",
5999                           (unsigned int)set_owner,
6000                           smb_fname_str_dbg(smb_fname)));
6001
6002                 if (fsp &&
6003                     !fsp->fsp_flags.is_pathref &&
6004                     fsp_get_io_fd(fsp) != -1)
6005                 {
6006                         ret = SMB_VFS_FCHOWN(fsp, set_owner, (gid_t)-1);
6007                 } else {
6008                         /*
6009                          * UNIX extensions calls must always operate
6010                          * on symlinks.
6011                          */
6012                         ret = SMB_VFS_LCHOWN(conn, smb_fname,
6013                                              set_owner, (gid_t)-1);
6014                 }
6015
6016                 if (ret != 0) {
6017                         status = map_nt_error_from_unix(errno);
6018                         return status;
6019                 }
6020         }
6021
6022         /*
6023          * Deal with the UNIX specific gid set.
6024          */
6025
6026         if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
6027             (sbuf.st_ex_gid != set_grp)) {
6028                 int ret;
6029
6030                 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6031                           "changing group %u for file %s\n",
6032                           (unsigned int)set_grp,
6033                           smb_fname_str_dbg(smb_fname)));
6034                 if (fsp &&
6035                     !fsp->fsp_flags.is_pathref &&
6036                     fsp_get_io_fd(fsp) != -1)
6037                 {
6038                         ret = SMB_VFS_FCHOWN(fsp, (uid_t)-1, set_grp);
6039                 } else {
6040                         /*
6041                          * UNIX extensions calls must always operate
6042                          * on symlinks.
6043                          */
6044                         ret = SMB_VFS_LCHOWN(conn, smb_fname, (uid_t)-1,
6045                                   set_grp);
6046                 }
6047                 if (ret != 0) {
6048                         status = map_nt_error_from_unix(errno);
6049                         return status;
6050                 }
6051         }
6052
6053         /* Deal with any size changes. */
6054
6055         if (S_ISREG(sbuf.st_ex_mode)) {
6056                 status = smb_set_file_size(conn, req,
6057                                            fsp,
6058                                            smb_fname,
6059                                            &sbuf,
6060                                            size,
6061                                            false);
6062                 if (!NT_STATUS_IS_OK(status)) {
6063                         return status;
6064                 }
6065         }
6066
6067         /* Deal with any time changes. */
6068         if (is_omit_timespec(&ft.mtime) && is_omit_timespec(&ft.atime)) {
6069                 /* No change, don't cancel anything. */
6070                 return status;
6071         }
6072
6073         id = vfs_file_id_from_sbuf(conn, &sbuf);
6074         for(all_fsps = file_find_di_first(conn->sconn, id, true); all_fsps;
6075                         all_fsps = file_find_di_next(all_fsps, true)) {
6076                 /*
6077                  * We're setting the time explicitly for UNIX.
6078                  * Cancel any pending changes over all handles.
6079                  */
6080                 all_fsps->fsp_flags.update_write_time_on_close = false;
6081                 TALLOC_FREE(all_fsps->update_write_time_event);
6082         }
6083
6084         /*
6085          * Override the "setting_write_time"
6086          * parameter here as it almost does what
6087          * we need. Just remember if we modified
6088          * mtime and send the notify ourselves.
6089          */
6090         if (is_omit_timespec(&ft.mtime)) {
6091                 modify_mtime = false;
6092         }
6093
6094         status = smb_set_file_time(conn,
6095                                 fsp,
6096                                 smb_fname,
6097                                 &ft,
6098                                 false);
6099         if (modify_mtime) {
6100                 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
6101                         FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
6102         }
6103         return status;
6104 }
6105
6106 /****************************************************************************
6107  Deal with SMB_SET_FILE_UNIX_INFO2.
6108 ****************************************************************************/
6109
6110 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
6111                                         struct smb_request *req,
6112                                         const char *pdata,
6113                                         int total_data,
6114                                         files_struct *fsp,
6115                                         struct smb_filename *smb_fname)
6116 {
6117         NTSTATUS status;
6118         uint32_t smb_fflags;
6119         uint32_t smb_fmask;
6120
6121         if (total_data < 116) {
6122                 return NT_STATUS_INVALID_PARAMETER;
6123         }
6124
6125         /* Start by setting all the fields that are common between UNIX_BASIC
6126          * and UNIX_INFO2.
6127          */
6128         status = smb_set_file_unix_basic(conn, req, pdata, total_data,
6129                                          fsp, smb_fname);
6130         if (!NT_STATUS_IS_OK(status)) {
6131                 return status;
6132         }
6133
6134         smb_fflags = IVAL(pdata, 108);
6135         smb_fmask = IVAL(pdata, 112);
6136
6137         /* NB: We should only attempt to alter the file flags if the client
6138          * sends a non-zero mask.
6139          */
6140         if (smb_fmask != 0) {
6141                 int stat_fflags = 0;
6142
6143                 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
6144                                              smb_fmask, &stat_fflags)) {
6145                         /* Client asked to alter a flag we don't understand. */
6146                         return NT_STATUS_INVALID_PARAMETER;
6147                 }
6148
6149                 if (fsp == NULL || S_ISLNK(smb_fname->st.st_ex_mode)) {
6150                         DBG_WARNING("Can't change flags on symlink %s\n",
6151                                 smb_fname_str_dbg(smb_fname));
6152                         return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6153                 }
6154                 if (SMB_VFS_FCHFLAGS(fsp, stat_fflags) != 0) {
6155                         return map_nt_error_from_unix(errno);
6156                 }
6157         }
6158
6159         /* XXX: need to add support for changing the create_time here. You
6160          * can do this for paths on Darwin with setattrlist(2). The right way
6161          * to hook this up is probably by extending the VFS utimes interface.
6162          */
6163
6164         return NT_STATUS_OK;
6165 }
6166
6167 /****************************************************************************
6168  Create a directory with POSIX semantics.
6169 ****************************************************************************/
6170
6171 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
6172                                 struct smb_request *req,
6173                                 char **ppdata,
6174                                 int total_data,
6175                                 struct smb_filename *smb_fname,
6176                                 int *pdata_return_size)
6177 {
6178         NTSTATUS status = NT_STATUS_OK;
6179         uint32_t raw_unixmode = 0;
6180         mode_t unixmode = (mode_t)0;
6181         files_struct *fsp = NULL;
6182         uint16_t info_level_return = 0;
6183         int info;
6184         char *pdata = *ppdata;
6185         struct smb2_create_blobs *posx = NULL;
6186
6187         if (total_data < 18) {
6188                 return NT_STATUS_INVALID_PARAMETER;
6189         }
6190
6191         raw_unixmode = IVAL(pdata,8);
6192         /* Next 4 bytes are not yet defined. */
6193
6194         status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6195                                       PERM_NEW_DIR, &unixmode);
6196         if (!NT_STATUS_IS_OK(status)) {
6197                 return status;
6198         }
6199
6200         status = make_smb2_posix_create_ctx(talloc_tos(), &posx, unixmode);
6201         if (!NT_STATUS_IS_OK(status)) {
6202                 DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
6203                             nt_errstr(status));
6204                 return status;
6205         }
6206
6207         DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
6208                   smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
6209
6210         status = SMB_VFS_CREATE_FILE(
6211                 conn,                                   /* conn */
6212                 req,                                    /* req */
6213                 NULL,                                   /* dirfsp */
6214                 smb_fname,                              /* fname */
6215                 FILE_READ_ATTRIBUTES,                   /* access_mask */
6216                 FILE_SHARE_NONE,                        /* share_access */
6217                 FILE_CREATE,                            /* create_disposition*/
6218                 FILE_DIRECTORY_FILE,                    /* create_options */
6219                 0,                                      /* file_attributes */
6220                 0,                                      /* oplock_request */
6221                 NULL,                                   /* lease */
6222                 0,                                      /* allocation_size */
6223                 0,                                      /* private_flags */
6224                 NULL,                                   /* sd */
6225                 NULL,                                   /* ea_list */
6226                 &fsp,                                   /* result */
6227                 &info,                                  /* pinfo */
6228                 posx,                                   /* in_context_blobs */
6229                 NULL);                                  /* out_context_blobs */
6230
6231         TALLOC_FREE(posx);
6232
6233         if (NT_STATUS_IS_OK(status)) {
6234                 close_file_free(req, &fsp, NORMAL_CLOSE);
6235         }
6236
6237         info_level_return = SVAL(pdata,16);
6238  
6239         if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6240                 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6241         } else if (info_level_return ==  SMB_QUERY_FILE_UNIX_INFO2) {
6242                 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6243         } else {
6244                 *pdata_return_size = 12;
6245         }
6246
6247         /* Realloc the data size */
6248         *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6249         if (*ppdata == NULL) {
6250                 *pdata_return_size = 0;
6251                 return NT_STATUS_NO_MEMORY;
6252         }
6253         pdata = *ppdata;
6254
6255         SSVAL(pdata,0,NO_OPLOCK_RETURN);
6256         SSVAL(pdata,2,0); /* No fnum. */
6257         SIVAL(pdata,4,info); /* Was directory created. */
6258
6259         switch (info_level_return) {
6260                 case SMB_QUERY_FILE_UNIX_BASIC:
6261                         SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6262                         SSVAL(pdata,10,0); /* Padding. */
6263                         store_file_unix_basic(conn, pdata + 12, fsp,
6264                                               &smb_fname->st);
6265                         break;
6266                 case SMB_QUERY_FILE_UNIX_INFO2:
6267                         SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6268                         SSVAL(pdata,10,0); /* Padding. */
6269                         store_file_unix_basic_info2(conn, pdata + 12, fsp,
6270                                                     &smb_fname->st);
6271                         break;
6272                 default:
6273                         SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6274                         SSVAL(pdata,10,0); /* Padding. */
6275                         break;
6276         }
6277
6278         return status;
6279 }
6280
6281 /****************************************************************************
6282  Open/Create a file with POSIX semantics.
6283 ****************************************************************************/
6284
6285 #define SMB_O_RDONLY_MAPPING (FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA)
6286 #define SMB_O_WRONLY_MAPPING (FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA)
6287
6288 static NTSTATUS smb_posix_open(connection_struct *conn,
6289                                struct smb_request *req,
6290                                 char **ppdata,
6291                                 int total_data,
6292                                 struct smb_filename *smb_fname,
6293                                 int *pdata_return_size)
6294 {
6295         bool extended_oplock_granted = False;
6296         char *pdata = *ppdata;
6297         uint32_t flags = 0;
6298         uint32_t wire_open_mode = 0;
6299         uint32_t raw_unixmode = 0;
6300         uint32_t attributes = 0;
6301         uint32_t create_disp = 0;
6302         uint32_t access_mask = 0;
6303         uint32_t create_options = FILE_NON_DIRECTORY_FILE;
6304         NTSTATUS status = NT_STATUS_OK;
6305         mode_t unixmode = (mode_t)0;
6306         files_struct *fsp = NULL;
6307         int oplock_request = 0;
6308         int info = 0;
6309         uint16_t info_level_return = 0;
6310         struct smb2_create_blobs *posx = NULL;
6311
6312         if (total_data < 18) {
6313                 return NT_STATUS_INVALID_PARAMETER;
6314         }
6315
6316         flags = IVAL(pdata,0);
6317         oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
6318         if (oplock_request) {
6319                 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
6320         }
6321
6322         wire_open_mode = IVAL(pdata,4);
6323
6324         if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
6325                 return smb_posix_mkdir(conn, req,
6326                                         ppdata,
6327                                         total_data,
6328                                         smb_fname,
6329                                         pdata_return_size);
6330         }
6331
6332         switch (wire_open_mode & SMB_ACCMODE) {
6333                 case SMB_O_RDONLY:
6334                         access_mask = SMB_O_RDONLY_MAPPING;
6335                         break;
6336                 case SMB_O_WRONLY:
6337                         access_mask = SMB_O_WRONLY_MAPPING;
6338                         break;
6339                 case SMB_O_RDWR:
6340                         access_mask = (SMB_O_RDONLY_MAPPING|
6341                                         SMB_O_WRONLY_MAPPING);
6342                         break;
6343                 default:
6344                         DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
6345                                 (unsigned int)wire_open_mode ));
6346                         return NT_STATUS_INVALID_PARAMETER;
6347         }
6348
6349         wire_open_mode &= ~SMB_ACCMODE;
6350
6351         /* First take care of O_CREAT|O_EXCL interactions. */
6352         switch (wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) {
6353                 case (SMB_O_CREAT | SMB_O_EXCL):
6354                         /* File exists fail. File not exist create. */
6355                         create_disp = FILE_CREATE;
6356                         break;
6357                 case SMB_O_CREAT:
6358                         /* File exists open. File not exist create. */
6359                         create_disp = FILE_OPEN_IF;
6360                         break;
6361                 case SMB_O_EXCL:
6362                         /* O_EXCL on its own without O_CREAT is undefined.
6363                            We deliberately ignore it as some versions of
6364                            Linux CIFSFS can send a bare O_EXCL on the
6365                            wire which other filesystems in the kernel
6366                            ignore. See bug 9519 for details. */
6367
6368                         /* Fallthrough. */
6369
6370                 case 0:
6371                         /* File exists open. File not exist fail. */
6372                         create_disp = FILE_OPEN;
6373                         break;
6374                 default:
6375                         DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
6376                                 (unsigned int)wire_open_mode ));
6377                         return NT_STATUS_INVALID_PARAMETER;
6378         }
6379
6380         /* Next factor in the effects of O_TRUNC. */
6381         wire_open_mode &= ~(SMB_O_CREAT | SMB_O_EXCL);
6382
6383         if (wire_open_mode & SMB_O_TRUNC) {
6384                 switch (create_disp) {
6385                         case FILE_CREATE:
6386                                 /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
6387                                 /* Leave create_disp alone as
6388                                    (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
6389                                 */
6390                                 /* File exists fail. File not exist create. */
6391                                 break;
6392                         case FILE_OPEN_IF:
6393                                 /* SMB_O_CREAT | SMB_O_TRUNC */
6394                                 /* File exists overwrite. File not exist create. */
6395                                 create_disp = FILE_OVERWRITE_IF;
6396                                 break;
6397                         case FILE_OPEN:
6398                                 /* SMB_O_TRUNC */
6399                                 /* File exists overwrite. File not exist fail. */
6400                                 create_disp = FILE_OVERWRITE;
6401                                 break;
6402                         default:
6403                                 /* Cannot get here. */
6404                                 smb_panic("smb_posix_open: logic error");
6405                                 return NT_STATUS_INVALID_PARAMETER;
6406                 }
6407         }
6408
6409         raw_unixmode = IVAL(pdata,8);
6410         /* Next 4 bytes are not yet defined. */
6411
6412         status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6413                                       (VALID_STAT(smb_fname->st) ?
6414                                           PERM_EXISTING_FILE : PERM_NEW_FILE),
6415                                       &unixmode);
6416
6417         if (!NT_STATUS_IS_OK(status)) {
6418                 return status;
6419         }
6420
6421         status = make_smb2_posix_create_ctx(talloc_tos(), &posx, unixmode);
6422         if (!NT_STATUS_IS_OK(status)) {
6423                 DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
6424                             nt_errstr(status));
6425                 return status;
6426         }
6427
6428         if (wire_open_mode & SMB_O_SYNC) {
6429                 create_options |= FILE_WRITE_THROUGH;
6430         }
6431         if (wire_open_mode & SMB_O_APPEND) {
6432                 access_mask |= FILE_APPEND_DATA;
6433         }
6434         if (wire_open_mode & SMB_O_DIRECT) {
6435                 attributes |= FILE_FLAG_NO_BUFFERING;
6436         }
6437
6438         if ((wire_open_mode & SMB_O_DIRECTORY) ||
6439                         VALID_STAT_OF_DIR(smb_fname->st)) {
6440                 if (access_mask != SMB_O_RDONLY_MAPPING) {
6441                         return NT_STATUS_FILE_IS_A_DIRECTORY;
6442                 }
6443                 create_options &= ~FILE_NON_DIRECTORY_FILE;
6444                 create_options |= FILE_DIRECTORY_FILE;
6445         }
6446
6447         DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
6448                 smb_fname_str_dbg(smb_fname),
6449                 (unsigned int)wire_open_mode,
6450                 (unsigned int)unixmode ));
6451
6452         status = SMB_VFS_CREATE_FILE(
6453                 conn,                                   /* conn */
6454                 req,                                    /* req */
6455                 NULL,                                   /* dirfsp */
6456                 smb_fname,                              /* fname */
6457                 access_mask,                            /* access_mask */
6458                 (FILE_SHARE_READ | FILE_SHARE_WRITE |   /* share_access */
6459                     FILE_SHARE_DELETE),
6460                 create_disp,                            /* create_disposition*/
6461                 create_options,                         /* create_options */
6462                 attributes,                             /* file_attributes */
6463                 oplock_request,                         /* oplock_request */
6464                 NULL,                                   /* lease */
6465                 0,                                      /* allocation_size */
6466                 0,                                      /* private_flags */
6467                 NULL,                                   /* sd */
6468                 NULL,                                   /* ea_list */
6469                 &fsp,                                   /* result */
6470                 &info,                                  /* pinfo */
6471                 posx,                                   /* in_context_blobs */
6472                 NULL);                                  /* out_context_blobs */
6473
6474         TALLOC_FREE(posx);
6475
6476         if (!NT_STATUS_IS_OK(status)) {
6477                 return status;
6478         }
6479
6480         if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
6481                 extended_oplock_granted = True;
6482         }
6483
6484         if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
6485                 extended_oplock_granted = True;
6486         }
6487
6488         info_level_return = SVAL(pdata,16);
6489  
6490         /* Allocate the correct return size. */
6491
6492         if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6493                 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6494         } else if (info_level_return ==  SMB_QUERY_FILE_UNIX_INFO2) {
6495                 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6496         } else {
6497                 *pdata_return_size = 12;
6498         }
6499
6500         /* Realloc the data size */
6501         *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6502         if (*ppdata == NULL) {
6503                 close_file_free(req, &fsp, ERROR_CLOSE);
6504                 *pdata_return_size = 0;
6505                 return NT_STATUS_NO_MEMORY;
6506         }
6507         pdata = *ppdata;
6508
6509         if (extended_oplock_granted) {
6510                 if (flags & REQUEST_BATCH_OPLOCK) {
6511                         SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
6512                 } else {
6513                         SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
6514                 }
6515         } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
6516                 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
6517         } else {
6518                 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6519         }
6520
6521         SSVAL(pdata,2,fsp->fnum);
6522         SIVAL(pdata,4,info); /* Was file created etc. */
6523
6524         switch (info_level_return) {
6525                 case SMB_QUERY_FILE_UNIX_BASIC:
6526                         SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6527                         SSVAL(pdata,10,0); /* padding. */
6528                         store_file_unix_basic(conn, pdata + 12, fsp,
6529                                               &smb_fname->st);
6530                         break;
6531                 case SMB_QUERY_FILE_UNIX_INFO2:
6532                         SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6533                         SSVAL(pdata,10,0); /* padding. */
6534                         store_file_unix_basic_info2(conn, pdata + 12, fsp,
6535                                                     &smb_fname->st);
6536                         break;
6537                 default:
6538                         SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6539                         SSVAL(pdata,10,0); /* padding. */
6540                         break;
6541         }
6542         return NT_STATUS_OK;
6543 }
6544
6545 /****************************************************************************
6546  Delete a file with POSIX semantics.
6547 ****************************************************************************/
6548
6549 static NTSTATUS smb_posix_unlink(connection_struct *conn,
6550                                  struct smb_request *req,
6551                                 const char *pdata,
6552                                 int total_data,
6553                                 struct smb_filename *smb_fname)
6554 {
6555         NTSTATUS status = NT_STATUS_OK;
6556         files_struct *fsp = NULL;
6557         uint16_t flags = 0;
6558         char del = 1;
6559         int info = 0;
6560         int create_options = 0;
6561         struct share_mode_lock *lck = NULL;
6562         bool other_nonposix_opens;
6563         struct smb2_create_blobs *posx = NULL;
6564
6565         if (total_data < 2) {
6566                 return NT_STATUS_INVALID_PARAMETER;
6567         }
6568
6569         flags = SVAL(pdata,0);
6570
6571         if (!VALID_STAT(smb_fname->st)) {
6572                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6573         }
6574
6575         if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
6576                         !VALID_STAT_OF_DIR(smb_fname->st)) {
6577                 return NT_STATUS_NOT_A_DIRECTORY;
6578         }
6579
6580         DEBUG(10,("smb_posix_unlink: %s %s\n",
6581                 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
6582                 smb_fname_str_dbg(smb_fname)));
6583
6584         if (VALID_STAT_OF_DIR(smb_fname->st)) {
6585                 create_options |= FILE_DIRECTORY_FILE;
6586         }
6587
6588         status = make_smb2_posix_create_ctx(talloc_tos(), &posx, 0777);
6589         if (!NT_STATUS_IS_OK(status)) {
6590                 DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
6591                             nt_errstr(status));
6592                 return status;
6593         }
6594
6595         status = SMB_VFS_CREATE_FILE(
6596                 conn,                                   /* conn */
6597                 req,                                    /* req */
6598                 NULL,                                   /* dirfsp */
6599                 smb_fname,                              /* fname */
6600                 DELETE_ACCESS,                          /* access_mask */
6601                 (FILE_SHARE_READ | FILE_SHARE_WRITE |   /* share_access */
6602                     FILE_SHARE_DELETE),
6603                 FILE_OPEN,                              /* create_disposition*/
6604                 create_options,                         /* create_options */
6605                 0,                                      /* file_attributes */
6606                 0,                                      /* oplock_request */
6607                 NULL,                                   /* lease */
6608                 0,                                      /* allocation_size */
6609                 0,                                      /* private_flags */
6610                 NULL,                                   /* sd */
6611                 NULL,                                   /* ea_list */
6612                 &fsp,                                   /* result */
6613                 &info,                                  /* pinfo */
6614                 posx,                                   /* in_context_blobs */
6615                 NULL);                                  /* out_context_blobs */
6616
6617         TALLOC_FREE(posx);
6618
6619         if (!NT_STATUS_IS_OK(status)) {
6620                 return status;
6621         }
6622
6623         /*
6624          * Don't lie to client. If we can't really delete due to
6625          * non-POSIX opens return SHARING_VIOLATION.
6626          */
6627
6628         lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
6629         if (lck == NULL) {
6630                 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
6631                           "lock for file %s\n", fsp_str_dbg(fsp)));
6632                 close_file_free(req, &fsp, NORMAL_CLOSE);
6633                 return NT_STATUS_INVALID_PARAMETER;
6634         }
6635
6636         other_nonposix_opens = has_other_nonposix_opens(lck, fsp);
6637         if (other_nonposix_opens) {
6638                 /* Fail with sharing violation. */
6639                 TALLOC_FREE(lck);
6640                 close_file_free(req, &fsp, NORMAL_CLOSE);
6641                 return NT_STATUS_SHARING_VIOLATION;
6642         }
6643
6644         /*
6645          * Set the delete on close.
6646          */
6647         status = smb_set_file_disposition_info(conn,
6648                                                 &del,
6649                                                 1,
6650                                                 fsp,
6651                                                 smb_fname);
6652
6653         TALLOC_FREE(lck);
6654
6655         if (!NT_STATUS_IS_OK(status)) {
6656                 close_file_free(req, &fsp, NORMAL_CLOSE);
6657                 return status;
6658         }
6659         return close_file_free(req, &fsp, NORMAL_CLOSE);
6660 }
6661
6662 static NTSTATUS smbd_do_posix_setfilepathinfo(struct connection_struct *conn,
6663                                               struct smb_request *req,
6664                                               TALLOC_CTX *mem_ctx,
6665                                               uint16_t info_level,
6666                                               struct smb_filename *smb_fname,
6667                                               files_struct *fsp,
6668                                               char **ppdata,
6669                                               int total_data,
6670                                               int *ret_data_size)
6671 {
6672         char *pdata = *ppdata;
6673         NTSTATUS status = NT_STATUS_OK;
6674         int data_return_size = 0;
6675
6676         *ret_data_size = 0;
6677
6678         if (!CAN_WRITE(conn)) {
6679                 /* Allow POSIX opens. The open path will deny
6680                  * any non-readonly opens. */
6681                 if (info_level != SMB_POSIX_PATH_OPEN) {
6682                         return NT_STATUS_DOS(ERRSRV, ERRaccess);
6683                 }
6684         }
6685
6686         DBG_DEBUG("file=%s (%s) info_level=%d totdata=%d\n",
6687                   smb_fname_str_dbg(smb_fname),
6688                   fsp_fnum_dbg(fsp),
6689                   info_level,
6690                   total_data);
6691
6692         switch (info_level) {
6693                 case SMB_SET_FILE_UNIX_BASIC:
6694                 {
6695                         status = smb_set_file_unix_basic(conn, req,
6696                                                         pdata,
6697                                                         total_data,
6698                                                         fsp,
6699                                                         smb_fname);
6700                         break;
6701                 }
6702
6703                 case SMB_SET_FILE_UNIX_INFO2:
6704                 {
6705                         status = smb_set_file_unix_info2(conn, req,
6706                                                         pdata,
6707                                                         total_data,
6708                                                         fsp,
6709                                                         smb_fname);
6710                         break;
6711                 }
6712
6713                 case SMB_SET_FILE_UNIX_LINK:
6714                 {
6715                         if (smb_fname == NULL) {
6716                                 /* We must have a pathname for this. */
6717                                 return NT_STATUS_INVALID_LEVEL;
6718                         }
6719                         status = smb_set_file_unix_link(conn, req, pdata,
6720                                                         total_data, smb_fname);
6721                         break;
6722                 }
6723
6724                 case SMB_SET_FILE_UNIX_HLINK:
6725                 {
6726                         if (smb_fname == NULL) {
6727                                 /* We must have a pathname for this. */
6728                                 return NT_STATUS_INVALID_LEVEL;
6729                         }
6730                         status = smb_set_file_unix_hlink(conn, req,
6731                                                          pdata, total_data,
6732                                                          smb_fname);
6733                         break;
6734                 }
6735
6736 #if defined(HAVE_POSIX_ACLS)
6737                 case SMB_SET_POSIX_ACL:
6738                 {
6739                         status = smb_set_posix_acl(conn,
6740                                                 req,
6741                                                 pdata,
6742                                                 total_data,
6743                                                 fsp,
6744                                                 smb_fname);
6745                         break;
6746                 }
6747 #endif
6748
6749 #if defined(WITH_SMB1SERVER)
6750                 case SMB_SET_POSIX_LOCK:
6751                 {
6752                         if (fsp == NULL) {
6753                                 return NT_STATUS_INVALID_LEVEL;
6754                         }
6755                         status = smb_set_posix_lock(conn, req,
6756                                                     pdata, total_data, fsp);
6757                         break;
6758                 }
6759 #endif
6760
6761                 case SMB_POSIX_PATH_OPEN:
6762                 {
6763                         if (smb_fname == NULL) {
6764                                 /* We must have a pathname for this. */
6765                                 return NT_STATUS_INVALID_LEVEL;
6766                         }
6767
6768                         status = smb_posix_open(conn, req,
6769                                                 ppdata,
6770                                                 total_data,
6771                                                 smb_fname,
6772                                                 &data_return_size);
6773                         break;
6774                 }
6775
6776                 case SMB_POSIX_PATH_UNLINK:
6777                 {
6778                         if (smb_fname == NULL) {
6779                                 /* We must have a pathname for this. */
6780                                 return NT_STATUS_INVALID_LEVEL;
6781                         }
6782
6783                         status = smb_posix_unlink(conn, req,
6784                                                 pdata,
6785                                                 total_data,
6786                                                 smb_fname);
6787                         break;
6788                 }
6789
6790                 default:
6791                         return NT_STATUS_INVALID_LEVEL;
6792         }
6793
6794         if (!NT_STATUS_IS_OK(status)) {
6795                 return status;
6796         }
6797
6798         *ret_data_size = data_return_size;
6799         return NT_STATUS_OK;
6800 }
6801
6802 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
6803                                 struct smb_request *req,
6804                                 TALLOC_CTX *mem_ctx,
6805                                 uint16_t info_level,
6806                                 files_struct *fsp,
6807                                 struct smb_filename *smb_fname,
6808                                 char **ppdata, int total_data,
6809                                 int *ret_data_size)
6810 {
6811         char *pdata = *ppdata;
6812         NTSTATUS status = NT_STATUS_OK;
6813         int data_return_size = 0;
6814
6815         if (INFO_LEVEL_IS_UNIX(info_level)) {
6816                 if (!lp_smb1_unix_extensions()) {
6817                         return NT_STATUS_INVALID_LEVEL;
6818                 }
6819                 if (!req->posix_pathnames) {
6820                         return NT_STATUS_INVALID_LEVEL;
6821                 }
6822                 status = smbd_do_posix_setfilepathinfo(conn,
6823                                                        req,
6824                                                        req,
6825                                                        info_level,
6826                                                        smb_fname,
6827                                                        fsp,
6828                                                        ppdata,
6829                                                        total_data,
6830                                                        &data_return_size);
6831                 if (!NT_STATUS_IS_OK(status)) {
6832                         return status;
6833                 }
6834                 *ret_data_size = data_return_size;
6835                 return NT_STATUS_OK;
6836         }
6837
6838         *ret_data_size = 0;
6839
6840         DEBUG(3,("smbd_do_setfilepathinfo: %s (%s) info_level=%d "
6841                  "totdata=%d\n", smb_fname_str_dbg(smb_fname),
6842                  fsp_fnum_dbg(fsp),
6843                  info_level, total_data));
6844
6845         switch (info_level) {
6846
6847                 case SMB_INFO_STANDARD:
6848                 {
6849                         status = smb_set_info_standard(conn,
6850                                         pdata,
6851                                         total_data,
6852                                         fsp,
6853                                         smb_fname);
6854                         break;
6855                 }
6856
6857                 case SMB_INFO_SET_EA:
6858                 {
6859                         status = smb_info_set_ea(conn,
6860                                                 pdata,
6861                                                 total_data,
6862                                                 fsp,
6863                                                 smb_fname);
6864                         break;
6865                 }
6866
6867                 case SMB_SET_FILE_BASIC_INFO:
6868                 case SMB_FILE_BASIC_INFORMATION:
6869                 {
6870                         status = smb_set_file_basic_info(conn,
6871                                                         pdata,
6872                                                         total_data,
6873                                                         fsp,
6874                                                         smb_fname);
6875                         break;
6876                 }
6877
6878                 case SMB_FILE_ALLOCATION_INFORMATION:
6879                 case SMB_SET_FILE_ALLOCATION_INFO:
6880                 {
6881                         status = smb_set_file_allocation_info(conn, req,
6882                                                                 pdata,
6883                                                                 total_data,
6884                                                                 fsp,
6885                                                                 smb_fname);
6886                         break;
6887                 }
6888
6889                 case SMB_FILE_END_OF_FILE_INFORMATION:
6890                 case SMB_SET_FILE_END_OF_FILE_INFO:
6891                 {
6892                         /*
6893                          * XP/Win7 both fail after the createfile with
6894                          * SMB_SET_FILE_END_OF_FILE_INFO but not
6895                          * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
6896                          * The level is known here, so pass it down
6897                          * appropriately.
6898                          */
6899                         bool should_fail =
6900                             (info_level == SMB_SET_FILE_END_OF_FILE_INFO);
6901
6902                         status = smb_set_file_end_of_file_info(conn, req,
6903                                                                 pdata,
6904                                                                 total_data,
6905                                                                 fsp,
6906                                                                 smb_fname,
6907                                                                 should_fail);
6908                         break;
6909                 }
6910
6911                 case SMB_FILE_DISPOSITION_INFORMATION:
6912                 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
6913                 {
6914 #if 0
6915                         /* JRA - We used to just ignore this on a path ? 
6916                          * Shouldn't this be invalid level on a pathname
6917                          * based call ?
6918                          */
6919                         if (tran_call != TRANSACT2_SETFILEINFO) {
6920                                 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6921                         }
6922 #endif
6923                         status = smb_set_file_disposition_info(conn,
6924                                                 pdata,
6925                                                 total_data,
6926                                                 fsp,
6927                                                 smb_fname);
6928                         break;
6929                 }
6930
6931                 case SMB_FILE_POSITION_INFORMATION:
6932                 {
6933                         status = smb_file_position_information(conn,
6934                                                 pdata,
6935                                                 total_data,
6936                                                 fsp);
6937                         break;
6938                 }
6939
6940                 case SMB_FILE_FULL_EA_INFORMATION:
6941                 {
6942                         status = smb_set_file_full_ea_info(conn,
6943                                                 pdata,
6944                                                 total_data,
6945                                                 fsp);
6946                         break;
6947                 }
6948
6949                 /* From tridge Samba4 : 
6950                  * MODE_INFORMATION in setfileinfo (I have no
6951                  * idea what "mode information" on a file is - it takes a value of 0,
6952                  * 2, 4 or 6. What could it be?).
6953                  */
6954
6955                 case SMB_FILE_MODE_INFORMATION:
6956                 {
6957                         status = smb_file_mode_information(conn,
6958                                                 pdata,
6959                                                 total_data);
6960                         break;
6961                 }
6962
6963                 /* [MS-SMB2] 3.3.5.21.1 states we MUST fail with STATUS_NOT_SUPPORTED. */
6964                 case SMB_FILE_VALID_DATA_LENGTH_INFORMATION:
6965                 case SMB_FILE_SHORT_NAME_INFORMATION:
6966                         return NT_STATUS_NOT_SUPPORTED;
6967
6968                 case SMB_FILE_RENAME_INFORMATION:
6969                 {
6970                         status = smb_file_rename_information(conn, req,
6971                                                              pdata, total_data,
6972                                                              fsp, smb_fname);
6973                         break;
6974                 }
6975
6976                 case SMB2_FILE_RENAME_INFORMATION_INTERNAL:
6977                 {
6978                         /* SMB2 rename information. */
6979                         status = smb2_file_rename_information(conn, req,
6980                                                              pdata, total_data,
6981                                                              fsp, smb_fname);
6982                         break;
6983                 }
6984
6985                 case SMB_FILE_LINK_INFORMATION:
6986                 {
6987                         status = smb_file_link_information(conn, req,
6988                                                         pdata, total_data,
6989                                                         fsp, smb_fname);
6990                         break;
6991                 }
6992
6993                 default:
6994                         return NT_STATUS_INVALID_LEVEL;
6995         }
6996
6997         if (!NT_STATUS_IS_OK(status)) {
6998                 return status;
6999         }
7000
7001         *ret_data_size = data_return_size;
7002         return NT_STATUS_OK;
7003 }
7004
7005 static uint32_t generate_volume_serial_number(
7006                         const struct loadparm_substitution *lp_sub,
7007                         int snum)
7008 {
7009         int serial = lp_volume_serial_number(snum);
7010         return serial != -1 ? serial:
7011                 str_checksum(lp_servicename(talloc_tos(), lp_sub, snum)) ^
7012                 (str_checksum(get_local_machine_name())<<16);
7013 }