s3: smbd: smb2-posix: Add SAMBA_XATTR_REPARSE_ATTRIB "user.SmbReparse" name.
[Samba.git] / source3 / smbd / smb2_trans2.c
blobb43f8f6330a470553dab683f1472131055ed5793
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
10 Extensively modified by Andrew Tridgell, 1995
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.
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.
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/>.
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 "../librpc/gen_ndr/ndr_smb3posix.h"
37 #include "libcli/security/security.h"
38 #include "trans2.h"
39 #include "auth.h"
40 #include "smbprofile.h"
41 #include "rpc_server/srv_pipe_hnd.h"
42 #include "printing.h"
43 #include "lib/util_ea.h"
44 #include "lib/readdir_attr.h"
45 #include "messages.h"
46 #include "libcli/smb/smb2_posix.h"
47 #include "lib/util/string_wrappers.h"
48 #include "source3/lib/substitute.h"
49 #include "source3/lib/adouble.h"
50 #include "source3/smbd/dir.h"
52 #define DIR_ENTRY_SAFETY_MARGIN 4096
54 static uint32_t generate_volume_serial_number(
55 const struct loadparm_substitution *lp_sub,
56 int snum);
58 /****************************************************************************
59 Check if an open file handle is a symlink.
60 ****************************************************************************/
62 NTSTATUS refuse_symlink_fsp(const files_struct *fsp)
65 if (!VALID_STAT(fsp->fsp_name->st)) {
66 return NT_STATUS_ACCESS_DENIED;
68 if (S_ISLNK(fsp->fsp_name->st.st_ex_mode)) {
69 return NT_STATUS_ACCESS_DENIED;
71 if (fsp_get_pathref_fd(fsp) == -1) {
72 return NT_STATUS_ACCESS_DENIED;
74 return NT_STATUS_OK;
77 /**
78 * Check that one or more of the rights in access mask are
79 * allowed. Iow, access_requested can contain more then one right and
80 * it is sufficient having only one of those granted to pass.
81 **/
82 NTSTATUS check_any_access_fsp(struct files_struct *fsp,
83 uint32_t access_requested)
85 const uint32_t ro_access = SEC_RIGHTS_FILE_READ | SEC_FILE_EXECUTE;
86 uint32_t ro_access_granted = 0;
87 uint32_t access_granted = 0;
88 NTSTATUS status;
90 if (fsp->fsp_flags.is_fsa) {
91 access_granted = fsp->access_mask;
92 } else {
93 uint32_t mask = 1;
95 while (mask != 0) {
96 if (!(mask & access_requested)) {
97 mask <<= 1;
98 continue;
101 status = smbd_check_access_rights_fsp(
102 fsp->conn->cwd_fsp,
103 fsp,
104 false,
105 mask);
106 if (NT_STATUS_IS_OK(status)) {
107 access_granted |= mask;
108 if (fsp->fsp_name->twrp == 0) {
110 * We can only optimize
111 * the non-snapshot case
113 break;
116 mask <<= 1;
119 if ((access_granted & access_requested) == 0) {
120 return NT_STATUS_ACCESS_DENIED;
123 if (fsp->fsp_name->twrp == 0) {
124 return NT_STATUS_OK;
127 ro_access_granted = access_granted & ro_access;
128 if ((ro_access_granted & access_requested) == 0) {
129 return NT_STATUS_MEDIA_WRITE_PROTECTED;
132 return NT_STATUS_OK;
135 /********************************************************************
136 Roundup a value to the nearest allocation roundup size boundary.
137 Only do this for Windows clients.
138 ********************************************************************/
140 uint64_t smb_roundup(connection_struct *conn, uint64_t val)
142 uint64_t rval = lp_allocation_roundup_size(SNUM(conn));
144 /* Only roundup for Windows clients. */
145 enum remote_arch_types ra_type = get_remote_arch();
146 if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
147 val = SMB_ROUNDUP(val,rval);
149 return val;
152 /****************************************************************************
153 Utility functions for dealing with extended attributes.
154 ****************************************************************************/
156 /****************************************************************************
157 Refuse to allow clients to overwrite our private xattrs.
158 ****************************************************************************/
160 bool samba_private_attr_name(const char *unix_ea_name)
162 bool prohibited = false;
164 prohibited |= strequal(unix_ea_name, SAMBA_POSIX_INHERITANCE_EA_NAME);
165 prohibited |= strequal(unix_ea_name, SAMBA_XATTR_DOS_ATTRIB);
166 prohibited |= strequal(unix_ea_name, SAMBA_XATTR_MARKER);
167 prohibited |= strequal(unix_ea_name, SAMBA_XATTR_REPARSE_ATTRIB);
168 prohibited |= strequal(unix_ea_name, XATTR_NTACL_NAME);
169 prohibited |= strequal(unix_ea_name, AFPINFO_EA_NETATALK);
171 if (prohibited) {
172 return true;
175 if (strncasecmp_m(unix_ea_name, SAMBA_XATTR_DOSSTREAM_PREFIX,
176 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX)) == 0) {
177 return true;
179 return false;
182 /****************************************************************************
183 Get one EA value. Fill in a struct ea_struct.
184 ****************************************************************************/
186 NTSTATUS get_ea_value_fsp(TALLOC_CTX *mem_ctx,
187 files_struct *fsp,
188 const char *ea_name,
189 struct ea_struct *pea)
191 /* Get the value of this xattr. Max size is 64k. */
192 size_t attr_size = 256;
193 char *val = NULL;
194 ssize_t sizeret;
195 size_t max_xattr_size = 0;
196 NTSTATUS status;
198 if (fsp == NULL) {
199 return NT_STATUS_INVALID_HANDLE;
201 status = refuse_symlink_fsp(fsp);
202 if (!NT_STATUS_IS_OK(status)) {
203 return status;
206 max_xattr_size = lp_smbd_max_xattr_size(SNUM(fsp->conn));
208 again:
210 val = talloc_realloc(mem_ctx, val, char, attr_size);
211 if (!val) {
212 return NT_STATUS_NO_MEMORY;
215 sizeret = SMB_VFS_FGETXATTR(fsp, ea_name, val, attr_size);
216 if (sizeret == -1 && errno == ERANGE && attr_size < max_xattr_size) {
217 attr_size = max_xattr_size;
218 goto again;
221 if (sizeret == -1) {
222 return map_nt_error_from_unix(errno);
225 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name, (unsigned int)sizeret));
226 dump_data(10, (uint8_t *)val, sizeret);
228 pea->flags = 0;
229 if (strnequal(ea_name, "user.", 5)) {
230 pea->name = talloc_strdup(mem_ctx, &ea_name[5]);
231 } else {
232 pea->name = talloc_strdup(mem_ctx, ea_name);
234 if (pea->name == NULL) {
235 TALLOC_FREE(val);
236 return NT_STATUS_NO_MEMORY;
238 pea->value.data = (unsigned char *)val;
239 pea->value.length = (size_t)sizeret;
240 return NT_STATUS_OK;
243 NTSTATUS get_ea_names_from_fsp(TALLOC_CTX *mem_ctx,
244 files_struct *fsp,
245 char ***pnames,
246 size_t *pnum_names)
248 char smallbuf[1024];
249 /* Get a list of all xattrs. Max namesize is 64k. */
250 size_t ea_namelist_size = 1024;
251 char *ea_namelist = smallbuf;
252 char *to_free = NULL;
254 char *p;
255 char **names;
256 size_t num_names;
257 ssize_t sizeret = -1;
258 NTSTATUS status;
260 if (pnames) {
261 *pnames = NULL;
263 *pnum_names = 0;
265 if ((fsp == NULL) || !NT_STATUS_IS_OK(refuse_symlink_fsp(fsp))) {
267 * Callers may pass fsp == NULL when passing smb_fname->fsp of a
268 * symlink. This is ok, handle it here, by just return no EA's
269 * on a symlink.
271 return NT_STATUS_OK;
274 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
275 ea_namelist_size);
277 if ((sizeret == -1) && (errno == ERANGE)) {
278 ea_namelist_size = 65536;
279 ea_namelist = talloc_array(mem_ctx, char, ea_namelist_size);
280 if (ea_namelist == NULL) {
281 return NT_STATUS_NO_MEMORY;
283 to_free = ea_namelist;
285 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
286 ea_namelist_size);
289 if (sizeret == -1) {
290 status = map_nt_error_from_unix(errno);
291 TALLOC_FREE(to_free);
292 return status;
295 DBG_DEBUG("ea_namelist size = %zd\n", sizeret);
297 if (sizeret == 0) {
298 TALLOC_FREE(to_free);
299 return NT_STATUS_OK;
303 * Ensure the result is 0-terminated
306 if (ea_namelist[sizeret-1] != '\0') {
307 TALLOC_FREE(to_free);
308 return NT_STATUS_INTERNAL_ERROR;
312 * count the names
314 num_names = 0;
316 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
317 num_names += 1;
320 *pnum_names = num_names;
322 if (pnames == NULL) {
323 TALLOC_FREE(to_free);
324 return NT_STATUS_OK;
327 names = talloc_array(mem_ctx, char *, num_names);
328 if (names == NULL) {
329 DEBUG(0, ("talloc failed\n"));
330 TALLOC_FREE(to_free);
331 return NT_STATUS_NO_MEMORY;
334 if (ea_namelist == smallbuf) {
335 ea_namelist = talloc_memdup(names, smallbuf, sizeret);
336 if (ea_namelist == NULL) {
337 TALLOC_FREE(names);
338 return NT_STATUS_NO_MEMORY;
340 } else {
341 talloc_steal(names, ea_namelist);
343 ea_namelist = talloc_realloc(names, ea_namelist, char,
344 sizeret);
345 if (ea_namelist == NULL) {
346 TALLOC_FREE(names);
347 return NT_STATUS_NO_MEMORY;
351 num_names = 0;
353 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
354 names[num_names++] = p;
357 *pnames = names;
359 return NT_STATUS_OK;
362 /****************************************************************************
363 Return a linked list of the total EA's. Plus the total size
364 ****************************************************************************/
366 static NTSTATUS get_ea_list_from_fsp(TALLOC_CTX *mem_ctx,
367 files_struct *fsp,
368 size_t *pea_total_len,
369 struct ea_list **ea_list)
371 /* Get a list of all xattrs. Max namesize is 64k. */
372 size_t i, num_names;
373 char **names;
374 struct ea_list *ea_list_head = NULL;
375 bool posix_pathnames = false;
376 NTSTATUS status;
378 *pea_total_len = 0;
379 *ea_list = NULL;
381 /* symlink */
382 if (fsp == NULL) {
383 return NT_STATUS_OK;
386 if (!lp_ea_support(SNUM(fsp->conn))) {
387 return NT_STATUS_OK;
390 if (fsp_is_alternate_stream(fsp)) {
391 return NT_STATUS_INVALID_PARAMETER;
394 posix_pathnames = (fsp->fsp_name->flags & SMB_FILENAME_POSIX_PATH);
396 status = get_ea_names_from_fsp(talloc_tos(),
397 fsp,
398 &names,
399 &num_names);
401 if (!NT_STATUS_IS_OK(status)) {
402 return status;
405 if (num_names == 0) {
406 return NT_STATUS_OK;
409 for (i=0; i<num_names; i++) {
410 struct ea_list *listp;
411 fstring dos_ea_name;
414 * POSIX EA names are divided into several namespaces by
415 * means of string prefixes. Usually, the system controls
416 * semantics for each namespace, but the 'user' namespace is
417 * available for arbitrary use, which comes closest to
418 * Windows EA semantics. Hence, we map POSIX EAs from the
419 * 'user' namespace to Windows EAs, and just ignore all the
420 * other namespaces. Also, a few specific names in the 'user'
421 * namespace are used by Samba internally. Filter them out as
422 * well, and only present the EAs that are available for
423 * arbitrary use.
425 if (!strnequal(names[i], "user.", 5)
426 || samba_private_attr_name(names[i]))
427 continue;
430 * Filter out any underlying POSIX EA names
431 * that a Windows client can't handle.
433 if (!posix_pathnames &&
434 is_invalid_windows_ea_name(names[i])) {
435 continue;
438 listp = talloc(mem_ctx, struct ea_list);
439 if (listp == NULL) {
440 return NT_STATUS_NO_MEMORY;
443 status = get_ea_value_fsp(listp,
444 fsp,
445 names[i],
446 &listp->ea);
448 if (!NT_STATUS_IS_OK(status)) {
449 TALLOC_FREE(listp);
450 return status;
453 if (listp->ea.value.length == 0) {
455 * We can never return a zero length EA.
456 * Windows reports the EA's as corrupted.
458 TALLOC_FREE(listp);
459 continue;
460 } else if (listp->ea.value.length > 65536) {
462 * SMB clients may report error with file
463 * if large EA is presented to them.
465 DBG_ERR("EA [%s] on file [%s] exceeds "
466 "maximum permitted EA size of 64KiB: %zu\n.",
467 listp->ea.name, fsp_str_dbg(fsp),
468 listp->ea.value.length);
469 TALLOC_FREE(listp);
470 continue;
473 push_ascii_fstring(dos_ea_name, listp->ea.name);
475 *pea_total_len +=
476 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
478 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
479 "= %u\n", (unsigned int)*pea_total_len, dos_ea_name,
480 (unsigned int)listp->ea.value.length));
482 DLIST_ADD_END(ea_list_head, listp);
486 /* Add on 4 for total length. */
487 if (*pea_total_len) {
488 *pea_total_len += 4;
491 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
492 (unsigned int)*pea_total_len));
494 *ea_list = ea_list_head;
495 return NT_STATUS_OK;
498 /****************************************************************************
499 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
500 that was filled.
501 ****************************************************************************/
503 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
504 connection_struct *conn, struct ea_list *ea_list)
506 unsigned int ret_data_size = 4;
507 char *p = pdata;
509 SMB_ASSERT(total_data_size >= 4);
511 if (!lp_ea_support(SNUM(conn))) {
512 SIVAL(pdata,4,0);
513 return 4;
516 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
517 size_t dos_namelen;
518 fstring dos_ea_name;
519 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
520 dos_namelen = strlen(dos_ea_name);
521 if (dos_namelen > 255 || dos_namelen == 0) {
522 break;
524 if (ea_list->ea.value.length > 65535) {
525 break;
527 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
528 break;
531 /* We know we have room. */
532 SCVAL(p,0,ea_list->ea.flags);
533 SCVAL(p,1,dos_namelen);
534 SSVAL(p,2,ea_list->ea.value.length);
535 strlcpy(p+4, dos_ea_name, dos_namelen+1);
536 if (ea_list->ea.value.length > 0) {
537 memcpy(p + 4 + dos_namelen + 1,
538 ea_list->ea.value.data,
539 ea_list->ea.value.length);
542 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
543 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
546 ret_data_size = PTR_DIFF(p, pdata);
547 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
548 SIVAL(pdata,0,ret_data_size);
549 return ret_data_size;
552 static NTSTATUS fill_ea_chained_buffer(TALLOC_CTX *mem_ctx,
553 char *pdata,
554 unsigned int total_data_size,
555 unsigned int *ret_data_size,
556 connection_struct *conn,
557 struct ea_list *ea_list)
559 uint8_t *p = (uint8_t *)pdata;
560 uint8_t *last_start = NULL;
561 bool do_store_data = (pdata != NULL);
563 *ret_data_size = 0;
565 if (!lp_ea_support(SNUM(conn))) {
566 return NT_STATUS_NO_EAS_ON_FILE;
569 for (; ea_list; ea_list = ea_list->next) {
570 size_t dos_namelen;
571 fstring dos_ea_name;
572 size_t this_size;
573 size_t pad = 0;
575 if (last_start != NULL && do_store_data) {
576 SIVAL(last_start, 0, PTR_DIFF(p, last_start));
578 last_start = p;
580 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
581 dos_namelen = strlen(dos_ea_name);
582 if (dos_namelen > 255 || dos_namelen == 0) {
583 return NT_STATUS_INTERNAL_ERROR;
585 if (ea_list->ea.value.length > 65535) {
586 return NT_STATUS_INTERNAL_ERROR;
589 this_size = 0x08 + dos_namelen + 1 + ea_list->ea.value.length;
591 if (ea_list->next) {
592 pad = (4 - (this_size % 4)) % 4;
593 this_size += pad;
596 if (do_store_data) {
597 if (this_size > total_data_size) {
598 return NT_STATUS_INFO_LENGTH_MISMATCH;
601 /* We know we have room. */
602 SIVAL(p, 0x00, 0); /* next offset */
603 SCVAL(p, 0x04, ea_list->ea.flags);
604 SCVAL(p, 0x05, dos_namelen);
605 SSVAL(p, 0x06, ea_list->ea.value.length);
606 strlcpy((char *)(p+0x08), dos_ea_name, dos_namelen+1);
607 memcpy(p + 0x08 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
608 if (pad) {
609 memset(p + 0x08 + dos_namelen + 1 + ea_list->ea.value.length,
610 '\0',
611 pad);
613 total_data_size -= this_size;
616 p += this_size;
619 *ret_data_size = PTR_DIFF(p, pdata);
620 DEBUG(10,("fill_ea_chained_buffer: data_size = %u\n", *ret_data_size));
621 return NT_STATUS_OK;
624 unsigned int estimate_ea_size(files_struct *fsp)
626 size_t total_ea_len = 0;
627 TALLOC_CTX *mem_ctx;
628 struct ea_list *ea_list = NULL;
629 NTSTATUS status;
631 /* symlink */
632 if (fsp == NULL) {
633 return 0;
636 if (!lp_ea_support(SNUM(fsp->conn))) {
637 return 0;
640 mem_ctx = talloc_stackframe();
642 /* If this is a stream fsp, then we need to instead find the
643 * estimated ea len from the main file, not the stream
644 * (streams cannot have EAs), but the estimate isn't just 0 in
645 * this case! */
646 fsp = metadata_fsp(fsp);
647 (void)get_ea_list_from_fsp(mem_ctx,
648 fsp,
649 &total_ea_len,
650 &ea_list);
652 if(conn_using_smb2(fsp->conn->sconn)) {
653 unsigned int ret_data_size;
655 * We're going to be using fill_ea_chained_buffer() to
656 * marshall EA's - this size is significantly larger
657 * than the SMB1 buffer. Re-calculate the size without
658 * marshalling.
660 status = fill_ea_chained_buffer(mem_ctx,
661 NULL,
663 &ret_data_size,
664 fsp->conn,
665 ea_list);
666 if (!NT_STATUS_IS_OK(status)) {
667 ret_data_size = 0;
669 total_ea_len = ret_data_size;
671 TALLOC_FREE(mem_ctx);
672 return total_ea_len;
675 /****************************************************************************
676 Ensure the EA name is case insensitive by matching any existing EA name.
677 ****************************************************************************/
679 static void canonicalize_ea_name(files_struct *fsp,
680 fstring unix_ea_name)
682 size_t total_ea_len;
683 TALLOC_CTX *mem_ctx = talloc_tos();
684 struct ea_list *ea_list;
685 NTSTATUS status = get_ea_list_from_fsp(mem_ctx,
686 fsp,
687 &total_ea_len,
688 &ea_list);
689 if (!NT_STATUS_IS_OK(status)) {
690 return;
693 for (; ea_list; ea_list = ea_list->next) {
694 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
695 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
696 &unix_ea_name[5], ea_list->ea.name));
697 strlcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-5);
698 break;
703 /****************************************************************************
704 Set or delete an extended attribute.
705 ****************************************************************************/
707 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp,
708 struct ea_list *ea_list)
710 NTSTATUS status;
711 bool posix_pathnames = false;
713 if (!lp_ea_support(SNUM(conn))) {
714 return NT_STATUS_EAS_NOT_SUPPORTED;
717 if (fsp == NULL) {
718 return NT_STATUS_INVALID_HANDLE;
721 posix_pathnames = (fsp->fsp_name->flags & SMB_FILENAME_POSIX_PATH);
723 status = refuse_symlink_fsp(fsp);
724 if (!NT_STATUS_IS_OK(status)) {
725 return status;
728 status = check_any_access_fsp(fsp, FILE_WRITE_EA);
729 if (!NT_STATUS_IS_OK(status)) {
730 return status;
733 /* Setting EAs on streams isn't supported. */
734 if (fsp_is_alternate_stream(fsp)) {
735 return NT_STATUS_INVALID_PARAMETER;
739 * Filter out invalid Windows EA names - before
740 * we set *any* of them.
743 if (!posix_pathnames && ea_list_has_invalid_name(ea_list)) {
744 return STATUS_INVALID_EA_NAME;
747 for (;ea_list; ea_list = ea_list->next) {
748 int ret;
749 fstring unix_ea_name;
752 * Complementing the forward mapping from POSIX EAs to
753 * Windows EAs in get_ea_list_from_fsp(), here we map in the
754 * opposite direction from Windows EAs to the 'user' namespace
755 * of POSIX EAs. Hence, all POSIX EA names the we set here must
756 * start with a 'user.' prefix.
758 fstrcpy(unix_ea_name, "user.");
759 fstrcat(unix_ea_name, ea_list->ea.name);
761 canonicalize_ea_name(fsp, unix_ea_name);
763 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
765 if (samba_private_attr_name(unix_ea_name)) {
766 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
767 return NT_STATUS_ACCESS_DENIED;
770 if (ea_list->ea.value.length == 0) {
771 /* Remove the attribute. */
772 DBG_DEBUG("deleting ea name %s on "
773 "file %s by file descriptor.\n",
774 unix_ea_name, fsp_str_dbg(fsp));
775 ret = SMB_VFS_FREMOVEXATTR(fsp, unix_ea_name);
776 #ifdef ENOATTR
777 /* Removing a non existent attribute always succeeds. */
778 if (ret == -1 && errno == ENOATTR) {
779 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
780 unix_ea_name));
781 ret = 0;
783 #endif
784 } else {
785 DEBUG(10,("set_ea: setting ea name %s on file "
786 "%s by file descriptor.\n",
787 unix_ea_name, fsp_str_dbg(fsp)));
788 ret = SMB_VFS_FSETXATTR(fsp, unix_ea_name,
789 ea_list->ea.value.data, ea_list->ea.value.length, 0);
792 if (ret == -1) {
793 #ifdef ENOTSUP
794 if (errno == ENOTSUP) {
795 return NT_STATUS_EAS_NOT_SUPPORTED;
797 #endif
798 return map_nt_error_from_unix(errno);
802 return NT_STATUS_OK;
805 /****************************************************************************
806 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
807 ****************************************************************************/
809 struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
811 struct ea_list *ea_list_head = NULL;
812 size_t offset = 0;
813 size_t bytes_used = 0;
815 while (offset < data_size) {
816 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
818 if (!eal) {
819 return NULL;
822 DLIST_ADD_END(ea_list_head, eal);
823 offset += bytes_used;
826 return ea_list_head;
829 /****************************************************************************
830 Count the total EA size needed.
831 ****************************************************************************/
833 static size_t ea_list_size(struct ea_list *ealist)
835 fstring dos_ea_name;
836 struct ea_list *listp;
837 size_t ret = 0;
839 for (listp = ealist; listp; listp = listp->next) {
840 push_ascii_fstring(dos_ea_name, listp->ea.name);
841 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
843 /* Add on 4 for total length. */
844 if (ret) {
845 ret += 4;
848 return ret;
851 /****************************************************************************
852 Return a union of EA's from a file list and a list of names.
853 The TALLOC context for the two lists *MUST* be identical as we steal
854 memory from one list to add to another. JRA.
855 ****************************************************************************/
857 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
859 struct ea_list *nlistp, *flistp;
861 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
862 for (flistp = file_list; flistp; flistp = flistp->next) {
863 if (strequal(nlistp->ea.name, flistp->ea.name)) {
864 break;
868 if (flistp) {
869 /* Copy the data from this entry. */
870 nlistp->ea.flags = flistp->ea.flags;
871 nlistp->ea.value = flistp->ea.value;
872 } else {
873 /* Null entry. */
874 nlistp->ea.flags = 0;
875 ZERO_STRUCT(nlistp->ea.value);
879 *total_ea_len = ea_list_size(name_list);
880 return name_list;
883 /****************************************************************************
884 Return the filetype for UNIX extensions.
885 ****************************************************************************/
887 static uint32_t unix_filetype(mode_t mode)
889 if(S_ISREG(mode))
890 return UNIX_TYPE_FILE;
891 else if(S_ISDIR(mode))
892 return UNIX_TYPE_DIR;
893 #ifdef S_ISLNK
894 else if(S_ISLNK(mode))
895 return UNIX_TYPE_SYMLINK;
896 #endif
897 #ifdef S_ISCHR
898 else if(S_ISCHR(mode))
899 return UNIX_TYPE_CHARDEV;
900 #endif
901 #ifdef S_ISBLK
902 else if(S_ISBLK(mode))
903 return UNIX_TYPE_BLKDEV;
904 #endif
905 #ifdef S_ISFIFO
906 else if(S_ISFIFO(mode))
907 return UNIX_TYPE_FIFO;
908 #endif
909 #ifdef S_ISSOCK
910 else if(S_ISSOCK(mode))
911 return UNIX_TYPE_SOCKET;
912 #endif
914 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
915 return UNIX_TYPE_UNKNOWN;
918 /****************************************************************************
919 Map wire perms onto standard UNIX permissions. Obey share restrictions.
920 ****************************************************************************/
922 NTSTATUS unix_perms_from_wire(connection_struct *conn,
923 const SMB_STRUCT_STAT *psbuf,
924 uint32_t perms,
925 enum perm_type ptype,
926 mode_t *ret_perms)
928 mode_t ret = 0;
930 if (perms == SMB_MODE_NO_CHANGE) {
931 if (!VALID_STAT(*psbuf)) {
932 return NT_STATUS_INVALID_PARAMETER;
933 } else {
934 *ret_perms = psbuf->st_ex_mode;
935 return NT_STATUS_OK;
939 ret = wire_perms_to_unix(perms);
941 if (ptype == PERM_NEW_FILE) {
943 * "create mask"/"force create mode" are
944 * only applied to new files, not existing ones.
946 ret &= lp_create_mask(SNUM(conn));
947 /* Add in force bits */
948 ret |= lp_force_create_mode(SNUM(conn));
949 } else if (ptype == PERM_NEW_DIR) {
951 * "directory mask"/"force directory mode" are
952 * only applied to new directories, not existing ones.
954 ret &= lp_directory_mask(SNUM(conn));
955 /* Add in force bits */
956 ret |= lp_force_directory_mode(SNUM(conn));
959 *ret_perms = ret;
960 return NT_STATUS_OK;
963 /****************************************************************************
964 Get a level dependent lanman2 dir entry.
965 ****************************************************************************/
967 struct smbd_dirptr_lanman2_state {
968 connection_struct *conn;
969 uint32_t info_level;
970 bool check_mangled_names;
971 bool case_sensitive;
974 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX *ctx,
975 void *private_data,
976 const char *dname,
977 const char *mask,
978 char **_fname)
980 struct smbd_dirptr_lanman2_state *state =
981 (struct smbd_dirptr_lanman2_state *)private_data;
982 bool ok;
983 char mangled_name[13]; /* mangled 8.3 name. */
984 bool got_match;
985 const char *fname;
987 /* Mangle fname if it's an illegal name. */
988 if (mangle_must_mangle(dname, state->conn->params)) {
990 * Slow path - ensure we can push the original name as UCS2. If
991 * not, then just don't return this name.
993 NTSTATUS status;
994 size_t ret_len = 0;
995 size_t len = (strlen(dname) + 2) * 4; /* Allow enough space. */
996 uint8_t *tmp = talloc_array(talloc_tos(),
997 uint8_t,
998 len);
1000 status = srvstr_push(NULL,
1001 FLAGS2_UNICODE_STRINGS,
1002 tmp,
1003 dname,
1004 len,
1005 STR_TERMINATE,
1006 &ret_len);
1008 TALLOC_FREE(tmp);
1010 if (!NT_STATUS_IS_OK(status)) {
1011 return false;
1014 ok = name_to_8_3(dname, mangled_name,
1015 true, state->conn->params);
1016 if (!ok) {
1017 return false;
1019 fname = mangled_name;
1020 } else {
1021 fname = dname;
1024 got_match = mask_match(fname, mask,
1025 state->case_sensitive);
1027 if(!got_match && state->check_mangled_names &&
1028 !mangle_is_8_3(fname, false, state->conn->params)) {
1030 * It turns out that NT matches wildcards against
1031 * both long *and* short names. This may explain some
1032 * of the wildcard weirdness from old DOS clients
1033 * that some people have been seeing.... JRA.
1035 /* Force the mangling into 8.3. */
1036 ok = name_to_8_3(fname, mangled_name,
1037 false, state->conn->params);
1038 if (!ok) {
1039 return false;
1042 got_match = mask_match(mangled_name, mask,
1043 state->case_sensitive);
1046 if (!got_match) {
1047 return false;
1050 *_fname = talloc_strdup(ctx, fname);
1051 if (*_fname == NULL) {
1052 return false;
1055 return true;
1058 static uint32_t get_dirent_ea_size(uint32_t mode, files_struct *fsp)
1060 if (!(mode & FILE_ATTRIBUTE_REPARSE_POINT)) {
1061 unsigned ea_size = estimate_ea_size(fsp);
1062 return ea_size;
1064 return IO_REPARSE_TAG_DFS;
1067 static NTSTATUS smbd_marshall_dir_entry(TALLOC_CTX *ctx,
1068 connection_struct *conn,
1069 uint16_t flags2,
1070 uint32_t info_level,
1071 struct ea_list *name_list,
1072 bool check_mangled_names,
1073 bool requires_resume_key,
1074 uint32_t mode,
1075 const char *fname,
1076 const struct smb_filename *smb_fname,
1077 int space_remaining,
1078 uint8_t align,
1079 bool do_pad,
1080 char *base_data,
1081 char **ppdata,
1082 char *end_data,
1083 uint64_t *last_entry_off)
1085 char *p, *q, *pdata = *ppdata;
1086 uint32_t reskey=0;
1087 uint64_t file_size = 0;
1088 uint64_t allocation_size = 0;
1089 uint64_t file_id = 0;
1090 size_t len = 0;
1091 struct timespec mdate_ts = {0};
1092 struct timespec adate_ts = {0};
1093 struct timespec cdate_ts = {0};
1094 struct timespec create_date_ts = {0};
1095 char *nameptr;
1096 char *last_entry_ptr;
1097 bool was_8_3;
1098 int off;
1099 int pad = 0;
1100 NTSTATUS status;
1101 struct readdir_attr_data *readdir_attr_data = NULL;
1102 uint32_t ea_size;
1104 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
1105 file_size = get_file_size_stat(&smb_fname->st);
1107 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
1110 * Skip SMB_VFS_FREADDIR_ATTR if the directory entry is a symlink or
1111 * a DFS symlink.
1113 if (smb_fname->fsp != NULL &&
1114 !(mode & FILE_ATTRIBUTE_REPARSE_POINT)) {
1115 status = SMB_VFS_FREADDIR_ATTR(smb_fname->fsp,
1116 ctx,
1117 &readdir_attr_data);
1118 if (!NT_STATUS_IS_OK(status)) {
1119 if (!NT_STATUS_EQUAL(NT_STATUS_NOT_SUPPORTED,
1120 status)) {
1121 return status;
1126 file_id = SMB_VFS_FS_FILE_ID(conn, &smb_fname->st);
1128 mdate_ts = smb_fname->st.st_ex_mtime;
1129 adate_ts = smb_fname->st.st_ex_atime;
1130 create_date_ts = get_create_timespec(conn, NULL, smb_fname);
1131 cdate_ts = get_change_timespec(conn, NULL, smb_fname);
1133 if (lp_dos_filetime_resolution(SNUM(conn))) {
1134 dos_filetime_timespec(&create_date_ts);
1135 dos_filetime_timespec(&mdate_ts);
1136 dos_filetime_timespec(&adate_ts);
1137 dos_filetime_timespec(&cdate_ts);
1140 /* align the record */
1141 SMB_ASSERT(align >= 1);
1143 off = (int)PTR_DIFF(pdata, base_data);
1144 pad = (off + (align-1)) & ~(align-1);
1145 pad -= off;
1147 if (pad && pad > space_remaining) {
1148 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1149 "for padding (wanted %u, had %d)\n",
1150 (unsigned int)pad,
1151 space_remaining ));
1152 return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
1155 off += pad;
1156 /* initialize padding to 0 */
1157 if (pad) {
1158 memset(pdata, 0, pad);
1160 space_remaining -= pad;
1162 DEBUG(10,("smbd_marshall_dir_entry: space_remaining = %d\n",
1163 space_remaining ));
1165 pdata += pad;
1166 p = pdata;
1167 last_entry_ptr = p;
1169 pad = 0;
1170 off = 0;
1172 switch (info_level) {
1173 case SMB_FIND_INFO_STANDARD:
1174 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1175 if(requires_resume_key) {
1176 SIVAL(p,0,reskey);
1177 p += 4;
1179 srv_put_dos_date2_ts(p, 0, create_date_ts);
1180 srv_put_dos_date2_ts(p, 4, adate_ts);
1181 srv_put_dos_date2_ts(p, 8, mdate_ts);
1182 SIVAL(p,12,(uint32_t)file_size);
1183 SIVAL(p,16,(uint32_t)allocation_size);
1184 SSVAL(p,20,mode);
1185 p += 23;
1186 nameptr = p;
1187 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1188 p += ucs2_align(base_data, p, 0);
1190 status = srvstr_push(base_data, flags2, p,
1191 fname, PTR_DIFF(end_data, p),
1192 STR_TERMINATE, &len);
1193 if (!NT_STATUS_IS_OK(status)) {
1194 return status;
1196 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1197 if (len > 2) {
1198 SCVAL(nameptr, -1, len - 2);
1199 } else {
1200 SCVAL(nameptr, -1, 0);
1202 } else {
1203 if (len > 1) {
1204 SCVAL(nameptr, -1, len - 1);
1205 } else {
1206 SCVAL(nameptr, -1, 0);
1209 p += len;
1210 break;
1212 case SMB_FIND_EA_SIZE:
1213 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
1214 if (requires_resume_key) {
1215 SIVAL(p,0,reskey);
1216 p += 4;
1218 srv_put_dos_date2_ts(p, 0, create_date_ts);
1219 srv_put_dos_date2_ts(p, 4, adate_ts);
1220 srv_put_dos_date2_ts(p, 8, mdate_ts);
1221 SIVAL(p,12,(uint32_t)file_size);
1222 SIVAL(p,16,(uint32_t)allocation_size);
1223 SSVAL(p,20,mode);
1225 ea_size = estimate_ea_size(smb_fname->fsp);
1226 SIVAL(p,22,ea_size); /* Extended attributes */
1228 p += 27;
1229 nameptr = p - 1;
1230 status = srvstr_push(base_data, flags2,
1231 p, fname, PTR_DIFF(end_data, p),
1232 STR_TERMINATE | STR_NOALIGN, &len);
1233 if (!NT_STATUS_IS_OK(status)) {
1234 return status;
1236 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1237 if (len > 2) {
1238 len -= 2;
1239 } else {
1240 len = 0;
1242 } else {
1243 if (len > 1) {
1244 len -= 1;
1245 } else {
1246 len = 0;
1249 SCVAL(nameptr,0,len);
1250 p += len;
1251 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1252 break;
1254 case SMB_FIND_EA_LIST:
1256 struct ea_list *file_list = NULL;
1257 size_t ea_len = 0;
1259 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
1260 if (!name_list) {
1261 return NT_STATUS_INVALID_PARAMETER;
1263 if (requires_resume_key) {
1264 SIVAL(p,0,reskey);
1265 p += 4;
1267 srv_put_dos_date2_ts(p, 0, create_date_ts);
1268 srv_put_dos_date2_ts(p, 4, adate_ts);
1269 srv_put_dos_date2_ts(p, 8, mdate_ts);
1270 SIVAL(p,12,(uint32_t)file_size);
1271 SIVAL(p,16,(uint32_t)allocation_size);
1272 SSVAL(p,20,mode);
1273 p += 22; /* p now points to the EA area. */
1275 status = get_ea_list_from_fsp(ctx,
1276 smb_fname->fsp,
1277 &ea_len, &file_list);
1278 if (!NT_STATUS_IS_OK(status)) {
1279 file_list = NULL;
1281 name_list = ea_list_union(name_list, file_list, &ea_len);
1283 /* We need to determine if this entry will fit in the space available. */
1284 /* Max string size is 255 bytes. */
1285 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1286 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1287 "(wanted %u, had %d)\n",
1288 (unsigned int)PTR_DIFF(p + 255 + ea_len,pdata),
1289 space_remaining ));
1290 return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
1293 /* Push the ea_data followed by the name. */
1294 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1295 nameptr = p;
1296 status = srvstr_push(base_data, flags2,
1297 p + 1, fname, PTR_DIFF(end_data, p+1),
1298 STR_TERMINATE | STR_NOALIGN, &len);
1299 if (!NT_STATUS_IS_OK(status)) {
1300 return status;
1302 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1303 if (len > 2) {
1304 len -= 2;
1305 } else {
1306 len = 0;
1308 } else {
1309 if (len > 1) {
1310 len -= 1;
1311 } else {
1312 len = 0;
1315 SCVAL(nameptr,0,len);
1316 p += len + 1;
1317 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1318 break;
1321 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1322 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1323 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1324 p += 4;
1325 SIVAL(p,0,reskey); p += 4;
1326 put_long_date_full_timespec(conn->ts_res,p,&create_date_ts); p += 8;
1327 put_long_date_full_timespec(conn->ts_res,p,&adate_ts); p += 8;
1328 put_long_date_full_timespec(conn->ts_res,p,&mdate_ts); p += 8;
1329 put_long_date_full_timespec(conn->ts_res,p,&cdate_ts); p += 8;
1330 SOFF_T(p,0,file_size); p += 8;
1331 SOFF_T(p,0,allocation_size); p += 8;
1332 SIVAL(p,0,mode); p += 4;
1333 q = p; p += 4; /* q is placeholder for name length. */
1334 ea_size = get_dirent_ea_size(mode, smb_fname->fsp);
1335 SIVAL(p, 0, ea_size);
1336 p += 4;
1337 /* Clear the short name buffer. This is
1338 * IMPORTANT as not doing so will trigger
1339 * a Win2k client bug. JRA.
1341 if (!was_8_3 && check_mangled_names) {
1342 char mangled_name[13]; /* mangled 8.3 name. */
1343 if (!name_to_8_3(fname,mangled_name,True,
1344 conn->params)) {
1345 /* Error - mangle failed ! */
1346 memset(mangled_name,'\0',12);
1348 mangled_name[12] = 0;
1349 status = srvstr_push(base_data, flags2,
1350 p+2, mangled_name, 24,
1351 STR_UPPER|STR_UNICODE, &len);
1352 if (!NT_STATUS_IS_OK(status)) {
1353 return status;
1355 if (len < 24) {
1356 memset(p + 2 + len,'\0',24 - len);
1358 SSVAL(p, 0, len);
1359 } else {
1360 memset(p,'\0',26);
1362 p += 2 + 24;
1363 status = srvstr_push(base_data, flags2, p,
1364 fname, PTR_DIFF(end_data, p),
1365 STR_TERMINATE_ASCII, &len);
1366 if (!NT_STATUS_IS_OK(status)) {
1367 return status;
1369 SIVAL(q,0,len);
1370 p += len;
1372 len = PTR_DIFF(p, pdata);
1373 pad = (len + (align-1)) & ~(align-1);
1375 * offset to the next entry, the caller
1376 * will overwrite it for the last entry
1377 * that's why we always include the padding
1379 SIVAL(pdata,0,pad);
1381 * set padding to zero
1383 if (do_pad) {
1384 memset(p, 0, pad - len);
1385 p = pdata + pad;
1386 } else {
1387 p = pdata + len;
1389 break;
1391 case SMB_FIND_FILE_DIRECTORY_INFO:
1392 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1393 p += 4;
1394 SIVAL(p,0,reskey); p += 4;
1395 put_long_date_full_timespec(conn->ts_res,p,&create_date_ts); p += 8;
1396 put_long_date_full_timespec(conn->ts_res,p,&adate_ts); p += 8;
1397 put_long_date_full_timespec(conn->ts_res,p,&mdate_ts); p += 8;
1398 put_long_date_full_timespec(conn->ts_res,p,&cdate_ts); p += 8;
1399 SOFF_T(p,0,file_size); p += 8;
1400 SOFF_T(p,0,allocation_size); p += 8;
1401 SIVAL(p,0,mode); p += 4;
1402 status = srvstr_push(base_data, flags2,
1403 p + 4, fname, PTR_DIFF(end_data, p+4),
1404 STR_TERMINATE_ASCII, &len);
1405 if (!NT_STATUS_IS_OK(status)) {
1406 return status;
1408 SIVAL(p,0,len);
1409 p += 4 + len;
1411 len = PTR_DIFF(p, pdata);
1412 pad = (len + (align-1)) & ~(align-1);
1414 * offset to the next entry, the caller
1415 * will overwrite it for the last entry
1416 * that's why we always include the padding
1418 SIVAL(pdata,0,pad);
1420 * set padding to zero
1422 if (do_pad) {
1423 memset(p, 0, pad - len);
1424 p = pdata + pad;
1425 } else {
1426 p = pdata + len;
1428 break;
1430 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1431 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1432 p += 4;
1433 SIVAL(p,0,reskey); p += 4;
1434 put_long_date_full_timespec(conn->ts_res,p,&create_date_ts); p += 8;
1435 put_long_date_full_timespec(conn->ts_res,p,&adate_ts); p += 8;
1436 put_long_date_full_timespec(conn->ts_res,p,&mdate_ts); p += 8;
1437 put_long_date_full_timespec(conn->ts_res,p,&cdate_ts); p += 8;
1438 SOFF_T(p,0,file_size); p += 8;
1439 SOFF_T(p,0,allocation_size); p += 8;
1440 SIVAL(p,0,mode); p += 4;
1441 q = p; p += 4; /* q is placeholder for name length. */
1442 ea_size = get_dirent_ea_size(mode, smb_fname->fsp);
1443 SIVAL(p, 0, ea_size);
1444 p +=4;
1445 status = srvstr_push(base_data, flags2, p,
1446 fname, PTR_DIFF(end_data, p),
1447 STR_TERMINATE_ASCII, &len);
1448 if (!NT_STATUS_IS_OK(status)) {
1449 return status;
1451 SIVAL(q, 0, len);
1452 p += len;
1454 len = PTR_DIFF(p, pdata);
1455 pad = (len + (align-1)) & ~(align-1);
1457 * offset to the next entry, the caller
1458 * will overwrite it for the last entry
1459 * that's why we always include the padding
1461 SIVAL(pdata,0,pad);
1463 * set padding to zero
1465 if (do_pad) {
1466 memset(p, 0, pad - len);
1467 p = pdata + pad;
1468 } else {
1469 p = pdata + len;
1471 break;
1473 case SMB_FIND_FILE_NAMES_INFO:
1474 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1475 p += 4;
1476 SIVAL(p,0,reskey); p += 4;
1477 p += 4;
1478 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1479 acl on a dir (tridge) */
1480 status = srvstr_push(base_data, flags2, p,
1481 fname, PTR_DIFF(end_data, p),
1482 STR_TERMINATE_ASCII, &len);
1483 if (!NT_STATUS_IS_OK(status)) {
1484 return status;
1486 SIVAL(p, -4, len);
1487 p += len;
1489 len = PTR_DIFF(p, pdata);
1490 pad = (len + (align-1)) & ~(align-1);
1492 * offset to the next entry, the caller
1493 * will overwrite it for the last entry
1494 * that's why we always include the padding
1496 SIVAL(pdata,0,pad);
1498 * set padding to zero
1500 if (do_pad) {
1501 memset(p, 0, pad - len);
1502 p = pdata + pad;
1503 } else {
1504 p = pdata + len;
1506 break;
1508 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1509 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1510 p += 4;
1511 SIVAL(p,0,reskey); p += 4;
1512 put_long_date_full_timespec(conn->ts_res,p,&create_date_ts); p += 8;
1513 put_long_date_full_timespec(conn->ts_res,p,&adate_ts); p += 8;
1514 put_long_date_full_timespec(conn->ts_res,p,&mdate_ts); p += 8;
1515 put_long_date_full_timespec(conn->ts_res,p,&cdate_ts); p += 8;
1516 SOFF_T(p,0,file_size); p += 8;
1517 SOFF_T(p,0,allocation_size); p += 8;
1518 SIVAL(p,0,mode); p += 4;
1519 q = p; p += 4; /* q is placeholder for name length. */
1520 ea_size = get_dirent_ea_size(mode, smb_fname->fsp);
1521 SIVAL(p, 0, ea_size);
1522 p += 4;
1523 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1524 SBVAL(p,0,file_id); p += 8;
1525 status = srvstr_push(base_data, flags2, p,
1526 fname, PTR_DIFF(end_data, p),
1527 STR_TERMINATE_ASCII, &len);
1528 if (!NT_STATUS_IS_OK(status)) {
1529 return status;
1531 SIVAL(q, 0, len);
1532 p += len;
1534 len = PTR_DIFF(p, pdata);
1535 pad = (len + (align-1)) & ~(align-1);
1537 * offset to the next entry, the caller
1538 * will overwrite it for the last entry
1539 * that's why we always include the padding
1541 SIVAL(pdata,0,pad);
1543 * set padding to zero
1545 if (do_pad) {
1546 memset(p, 0, pad - len);
1547 p = pdata + pad;
1548 } else {
1549 p = pdata + len;
1551 break;
1553 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1554 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1555 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1556 p += 4;
1557 SIVAL(p,0,reskey); p += 4;
1558 put_long_date_full_timespec(conn->ts_res,p,&create_date_ts); p += 8;
1559 put_long_date_full_timespec(conn->ts_res,p,&adate_ts); p += 8;
1560 put_long_date_full_timespec(conn->ts_res,p,&mdate_ts); p += 8;
1561 put_long_date_full_timespec(conn->ts_res,p,&cdate_ts); p += 8;
1562 SOFF_T(p,0,file_size); p += 8;
1563 SOFF_T(p,0,allocation_size); p += 8;
1564 SIVAL(p,0,mode); p += 4;
1565 q = p; p += 4; /* q is placeholder for name length */
1566 if (readdir_attr_data &&
1567 readdir_attr_data->type == RDATTR_AAPL) {
1569 * OS X specific SMB2 extension negotiated via
1570 * AAPL create context: return max_access in
1571 * ea_size field.
1573 ea_size = readdir_attr_data->attr_data.aapl.max_access;
1574 } else {
1575 ea_size = get_dirent_ea_size(mode, smb_fname->fsp);
1577 SIVAL(p,0,ea_size); /* Extended attributes */
1578 p += 4;
1580 if (readdir_attr_data &&
1581 readdir_attr_data->type == RDATTR_AAPL) {
1583 * OS X specific SMB2 extension negotiated via
1584 * AAPL create context: return resource fork
1585 * length and compressed FinderInfo in
1586 * shortname field.
1588 * According to documentation short_name_len
1589 * should be 0, but on the wire behaviour
1590 * shows its set to 24 by clients.
1592 SSVAL(p, 0, 24);
1594 /* Resourefork length */
1595 SBVAL(p, 2, readdir_attr_data->attr_data.aapl.rfork_size);
1597 /* Compressed FinderInfo */
1598 memcpy(p + 10, &readdir_attr_data->attr_data.aapl.finder_info, 16);
1599 } else if (!was_8_3 && check_mangled_names) {
1600 char mangled_name[13]; /* mangled 8.3 name. */
1601 if (!name_to_8_3(fname,mangled_name,True,
1602 conn->params)) {
1603 /* Error - mangle failed ! */
1604 memset(mangled_name,'\0',12);
1606 mangled_name[12] = 0;
1607 status = srvstr_push(base_data, flags2,
1608 p+2, mangled_name, 24,
1609 STR_UPPER|STR_UNICODE, &len);
1610 if (!NT_STATUS_IS_OK(status)) {
1611 return status;
1613 SSVAL(p, 0, len);
1614 if (len < 24) {
1615 memset(p + 2 + len,'\0',24 - len);
1617 SSVAL(p, 0, len);
1618 } else {
1619 /* Clear the short name buffer. This is
1620 * IMPORTANT as not doing so will trigger
1621 * a Win2k client bug. JRA.
1623 memset(p,'\0',26);
1625 p += 26;
1627 /* Reserved ? */
1628 if (readdir_attr_data &&
1629 readdir_attr_data->type == RDATTR_AAPL) {
1631 * OS X specific SMB2 extension negotiated via
1632 * AAPL create context: return UNIX mode in
1633 * reserved field.
1635 uint16_t aapl_mode = (uint16_t)readdir_attr_data->attr_data.aapl.unix_mode;
1636 SSVAL(p, 0, aapl_mode);
1637 } else {
1638 SSVAL(p, 0, 0);
1640 p += 2;
1642 SBVAL(p,0,file_id); p += 8;
1643 status = srvstr_push(base_data, flags2, p,
1644 fname, PTR_DIFF(end_data, p),
1645 STR_TERMINATE_ASCII, &len);
1646 if (!NT_STATUS_IS_OK(status)) {
1647 return status;
1649 SIVAL(q,0,len);
1650 p += len;
1652 len = PTR_DIFF(p, pdata);
1653 pad = (len + (align-1)) & ~(align-1);
1655 * offset to the next entry, the caller
1656 * will overwrite it for the last entry
1657 * that's why we always include the padding
1659 SIVAL(pdata,0,pad);
1661 * set padding to zero
1663 if (do_pad) {
1664 memset(p, 0, pad - len);
1665 p = pdata + pad;
1666 } else {
1667 p = pdata + len;
1669 break;
1671 /* CIFS UNIX Extension. */
1673 case SMB_FIND_FILE_UNIX:
1674 case SMB_FIND_FILE_UNIX_INFO2:
1675 p+= 4;
1676 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1678 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1680 if (info_level == SMB_FIND_FILE_UNIX) {
1681 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
1682 p = store_file_unix_basic(conn, p,
1683 NULL, &smb_fname->st);
1684 status = srvstr_push(base_data, flags2, p,
1685 fname, PTR_DIFF(end_data, p),
1686 STR_TERMINATE, &len);
1687 if (!NT_STATUS_IS_OK(status)) {
1688 return status;
1690 } else {
1691 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
1692 p = store_file_unix_basic_info2(conn, p,
1693 NULL, &smb_fname->st);
1694 nameptr = p;
1695 p += 4;
1696 status = srvstr_push(base_data, flags2, p, fname,
1697 PTR_DIFF(end_data, p), 0, &len);
1698 if (!NT_STATUS_IS_OK(status)) {
1699 return status;
1701 SIVAL(nameptr, 0, len);
1704 p += len;
1706 len = PTR_DIFF(p, pdata);
1707 pad = (len + (align-1)) & ~(align-1);
1709 * offset to the next entry, the caller
1710 * will overwrite it for the last entry
1711 * that's why we always include the padding
1713 SIVAL(pdata,0,pad);
1715 * set padding to zero
1717 if (do_pad) {
1718 memset(p, 0, pad - len);
1719 p = pdata + pad;
1720 } else {
1721 p = pdata + len;
1723 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1725 break;
1727 /* SMB2 UNIX Extension. */
1729 case SMB2_FILE_POSIX_INFORMATION:
1731 struct smb3_file_posix_information info = {};
1732 uint8_t buf[sizeof(info)];
1733 struct ndr_push ndr = {
1734 .data = buf,
1735 .alloc_size = sizeof(buf),
1736 .fixed_buf_size = true,
1738 enum ndr_err_code ndr_err;
1740 p+= 4;
1741 SIVAL(p,0,reskey); p+= 4;
1743 DBG_DEBUG("SMB2_FILE_POSIX_INFORMATION\n");
1745 if (!conn_using_smb2(conn->sconn)) {
1746 return NT_STATUS_INVALID_LEVEL;
1749 smb3_file_posix_information_init(
1750 conn, &smb_fname->st, 0, mode, &info);
1752 ndr_err = ndr_push_smb3_file_posix_information(
1753 &ndr, NDR_SCALARS|NDR_BUFFERS, &info);
1754 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1755 return NT_STATUS_INSUFFICIENT_RESOURCES;
1758 memcpy(p, buf, ndr.offset);
1759 p += ndr.offset;
1761 nameptr = p;
1762 p += 4;
1763 status = srvstr_push(base_data, flags2, p, fname,
1764 PTR_DIFF(end_data, p), 0, &len);
1765 if (!NT_STATUS_IS_OK(status)) {
1766 return status;
1768 SIVAL(nameptr, 0, len);
1770 p += len;
1772 len = PTR_DIFF(p, pdata);
1773 pad = (len + (align-1)) & ~(align-1);
1775 * offset to the next entry, the caller
1776 * will overwrite it for the last entry
1777 * that's why we always include the padding
1779 SIVAL(pdata,0,pad);
1780 break;
1783 default:
1784 return NT_STATUS_INVALID_LEVEL;
1787 if (PTR_DIFF(p,pdata) > space_remaining) {
1788 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1789 "(wanted %u, had %d)\n",
1790 (unsigned int)PTR_DIFF(p,pdata),
1791 space_remaining ));
1792 return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
1795 /* Setup the last entry pointer, as an offset from base_data */
1796 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
1797 /* Advance the data pointer to the next slot */
1798 *ppdata = p;
1800 return NT_STATUS_OK;
1803 NTSTATUS smbd_dirptr_lanman2_entry(TALLOC_CTX *ctx,
1804 connection_struct *conn,
1805 struct dptr_struct *dirptr,
1806 uint16_t flags2,
1807 const char *path_mask,
1808 uint32_t dirtype,
1809 int info_level,
1810 int requires_resume_key,
1811 bool dont_descend,
1812 bool ask_sharemode,
1813 bool get_dosmode,
1814 uint8_t align,
1815 bool do_pad,
1816 char **ppdata,
1817 char *base_data,
1818 char *end_data,
1819 int space_remaining,
1820 struct smb_filename **_smb_fname,
1821 int *_last_entry_off,
1822 struct ea_list *name_list,
1823 struct file_id *file_id)
1825 const char *p;
1826 const char *mask = NULL;
1827 uint32_t mode = 0;
1828 char *fname = NULL;
1829 struct smb_filename *smb_fname = NULL;
1830 struct smbd_dirptr_lanman2_state state;
1831 bool ok;
1832 uint64_t last_entry_off = 0;
1833 NTSTATUS status;
1834 enum mangled_names_options mangled_names;
1835 bool marshall_with_83_names;
1837 mangled_names = lp_mangled_names(conn->params);
1839 ZERO_STRUCT(state);
1840 state.conn = conn;
1841 state.info_level = info_level;
1842 if (mangled_names != MANGLED_NAMES_NO) {
1843 state.check_mangled_names = true;
1845 state.case_sensitive = dptr_case_sensitive(dirptr);
1847 p = strrchr_m(path_mask,'/');
1848 if(p != NULL) {
1849 if(p[1] == '\0') {
1850 mask = "*.*";
1851 } else {
1852 mask = p+1;
1854 } else {
1855 mask = path_mask;
1858 ok = smbd_dirptr_get_entry(ctx,
1859 dirptr,
1860 mask,
1861 dirtype,
1862 dont_descend,
1863 ask_sharemode,
1864 get_dosmode,
1865 smbd_dirptr_lanman2_match_fn,
1866 &state,
1867 &fname,
1868 &smb_fname,
1869 &mode);
1870 if (!ok) {
1871 return NT_STATUS_END_OF_FILE;
1874 marshall_with_83_names = (mangled_names == MANGLED_NAMES_YES);
1876 status = smbd_marshall_dir_entry(ctx,
1877 conn,
1878 flags2,
1879 info_level,
1880 name_list,
1881 marshall_with_83_names,
1882 requires_resume_key,
1883 mode,
1884 fname,
1885 smb_fname,
1886 space_remaining,
1887 align,
1888 do_pad,
1889 base_data,
1890 ppdata,
1891 end_data,
1892 &last_entry_off);
1893 if (NT_STATUS_EQUAL(status, NT_STATUS_ILLEGAL_CHARACTER)) {
1894 DEBUG(1,("Conversion error: illegal character: %s\n",
1895 smb_fname_str_dbg(smb_fname)));
1898 if (file_id != NULL) {
1899 *file_id = vfs_file_id_from_sbuf(conn, &smb_fname->st);
1902 if (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
1903 smbd_dirptr_push_overflow(dirptr, &fname, &smb_fname, mode);
1906 if (!NT_STATUS_IS_OK(status)) {
1907 TALLOC_FREE(smb_fname);
1908 TALLOC_FREE(fname);
1909 return status;
1912 smbd_dirptr_set_last_name_sent(dirptr, &smb_fname->base_name);
1914 if (_smb_fname != NULL) {
1916 * smb_fname is already talloc'ed off ctx.
1917 * We just need to make sure we don't return
1918 * any stream_name, and replace base_name
1919 * with fname in case base_name got mangled.
1920 * This allows us to preserve any smb_fname->fsp
1921 * for asynchronous handle lookups.
1923 TALLOC_FREE(smb_fname->stream_name);
1926 * smbd_dirptr_set_last_name_sent() above consumed
1927 * base_name
1929 smb_fname->base_name = talloc_strdup(smb_fname, fname);
1931 if (smb_fname->base_name == NULL) {
1932 TALLOC_FREE(smb_fname);
1933 TALLOC_FREE(fname);
1934 return NT_STATUS_NO_MEMORY;
1936 *_smb_fname = smb_fname;
1937 } else {
1938 TALLOC_FREE(smb_fname);
1940 TALLOC_FREE(fname);
1942 *_last_entry_off = last_entry_off;
1943 return NT_STATUS_OK;
1946 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
1948 const struct loadparm_substitution *lp_sub =
1949 loadparm_s3_global_substitution();
1951 E_md4hash(lp_servicename(talloc_tos(), lp_sub, SNUM(conn)),objid);
1952 return objid;
1955 static void samba_extended_info_version(struct smb_extended_info *extended_info)
1957 SMB_ASSERT(extended_info != NULL);
1959 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
1960 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
1961 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
1962 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
1963 #ifdef SAMBA_VERSION_REVISION
1964 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
1965 #endif
1966 extended_info->samba_subversion = 0;
1967 #ifdef SAMBA_VERSION_RC_RELEASE
1968 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
1969 #else
1970 #ifdef SAMBA_VERSION_PRE_RELEASE
1971 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
1972 #endif
1973 #endif
1974 #ifdef SAMBA_VERSION_VENDOR_PATCH
1975 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
1976 #endif
1977 extended_info->samba_gitcommitdate = 0;
1978 #ifdef SAMBA_VERSION_COMMIT_TIME
1979 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_COMMIT_TIME);
1980 #endif
1982 memset(extended_info->samba_version_string, 0,
1983 sizeof(extended_info->samba_version_string));
1985 snprintf (extended_info->samba_version_string,
1986 sizeof(extended_info->samba_version_string),
1987 "%s", samba_version_string());
1990 static bool fsinfo_unix_valid_level(connection_struct *conn,
1991 struct files_struct *fsp,
1992 uint16_t info_level)
1994 if (conn_using_smb2(conn->sconn) &&
1995 fsp->posix_flags == FSP_POSIX_FLAGS_OPEN &&
1996 info_level == SMB2_FS_POSIX_INFORMATION_INTERNAL)
1998 return true;
2000 #if defined(SMB1SERVER)
2001 if (lp_smb1_unix_extensions() &&
2002 info_level == SMB_QUERY_POSIX_FS_INFO) {
2003 return true;
2005 #endif
2006 return false;
2010 * fsp is only valid for SMB2.
2012 NTSTATUS smbd_do_qfsinfo(struct smbXsrv_connection *xconn,
2013 connection_struct *conn,
2014 TALLOC_CTX *mem_ctx,
2015 uint16_t info_level,
2016 uint16_t flags2,
2017 unsigned int max_data_bytes,
2018 size_t *fixed_portion,
2019 struct files_struct *fsp,
2020 struct smb_filename *fname,
2021 char **ppdata,
2022 int *ret_data_len)
2024 const struct loadparm_substitution *lp_sub =
2025 loadparm_s3_global_substitution();
2026 char *pdata, *end_data;
2027 int data_len = 0;
2028 size_t len = 0;
2029 const char *vname = volume_label(talloc_tos(), SNUM(conn));
2030 int snum = SNUM(conn);
2031 const char *fstype = lp_fstype(SNUM(conn));
2032 const char *filename = NULL;
2033 const uint64_t bytes_per_sector = 512;
2034 uint32_t additional_flags = 0;
2035 struct smb_filename smb_fname;
2036 SMB_STRUCT_STAT st;
2037 NTSTATUS status = NT_STATUS_OK;
2038 uint64_t df_ret;
2039 uint32_t serial;
2041 if (fname == NULL || fname->base_name == NULL) {
2042 filename = ".";
2043 } else {
2044 filename = fname->base_name;
2047 if (IS_IPC(conn)) {
2048 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2049 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
2050 "info level (0x%x) on IPC$.\n",
2051 (unsigned int)info_level));
2052 return NT_STATUS_ACCESS_DENIED;
2056 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
2058 smb_fname = (struct smb_filename) {
2059 .base_name = discard_const_p(char, filename),
2060 .flags = fname ? fname->flags : 0,
2061 .twrp = fname ? fname->twrp : 0,
2064 if(info_level != SMB_FS_QUOTA_INFORMATION
2065 && SMB_VFS_STAT(conn, &smb_fname) != 0) {
2066 DEBUG(2,("stat of . failed (%s)\n", strerror(errno)));
2067 return map_nt_error_from_unix(errno);
2070 st = smb_fname.st;
2072 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
2073 return NT_STATUS_INVALID_PARAMETER;
2076 *ppdata = (char *)SMB_REALLOC(
2077 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2078 if (*ppdata == NULL) {
2079 return NT_STATUS_NO_MEMORY;
2082 pdata = *ppdata;
2083 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2084 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2086 *fixed_portion = 0;
2088 switch (info_level) {
2089 case SMB_INFO_ALLOCATION:
2091 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
2092 data_len = 18;
2093 df_ret = get_dfree_info(conn, &smb_fname, &bsize,
2094 &dfree, &dsize);
2095 if (df_ret == (uint64_t)-1) {
2096 return map_nt_error_from_unix(errno);
2099 block_size = lp_block_size(snum);
2100 if (bsize < block_size) {
2101 uint64_t factor = block_size/bsize;
2102 bsize = block_size;
2103 dsize /= factor;
2104 dfree /= factor;
2106 if (bsize > block_size) {
2107 uint64_t factor = bsize/block_size;
2108 bsize = block_size;
2109 dsize *= factor;
2110 dfree *= factor;
2112 sectors_per_unit = bsize/bytes_per_sector;
2114 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2115 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2116 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2119 * For large drives, return max values and not modulo.
2121 dsize = MIN(dsize, UINT32_MAX);
2122 dfree = MIN(dfree, UINT32_MAX);
2124 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
2125 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2126 SIVAL(pdata,l1_cUnit,dsize);
2127 SIVAL(pdata,l1_cUnitAvail,dfree);
2128 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2129 break;
2132 case SMB_INFO_VOLUME:
2133 /* Return volume name */
2135 * Add volume serial number - hash of a combination of
2136 * the called hostname and the service name.
2138 serial = generate_volume_serial_number(lp_sub, snum);
2139 SIVAL(pdata,0,serial);
2141 * Win2k3 and previous mess this up by sending a name length
2142 * one byte short. I believe only older clients (OS/2 Win9x) use
2143 * this call so try fixing this by adding a terminating null to
2144 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2146 status = srvstr_push(
2147 pdata, flags2,
2148 pdata+l2_vol_szVolLabel, vname,
2149 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
2150 STR_NOALIGN|STR_TERMINATE, &len);
2151 if (!NT_STATUS_IS_OK(status)) {
2152 return status;
2154 SCVAL(pdata,l2_vol_cch,len);
2155 data_len = l2_vol_szVolLabel + len;
2156 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %u, "
2157 "name = %s serial = 0x%04"PRIx32"\n",
2158 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
2159 (unsigned)len, vname, serial));
2160 break;
2162 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2163 case SMB_FS_ATTRIBUTE_INFORMATION:
2165 additional_flags = 0;
2166 #if defined(HAVE_SYS_QUOTAS)
2167 additional_flags |= FILE_VOLUME_QUOTAS;
2168 #endif
2170 if(lp_nt_acl_support(SNUM(conn))) {
2171 additional_flags |= FILE_PERSISTENT_ACLS;
2174 /* Capabilities are filled in at connection time through STATVFS call */
2175 additional_flags |= conn->fs_capabilities;
2176 additional_flags |= lp_parm_int(conn->params->service,
2177 "share", "fake_fscaps",
2180 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2181 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
2182 additional_flags); /* FS ATTRIBUTES */
2184 SIVAL(pdata,4,255); /* Max filename component length */
2185 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2186 and will think we can't do long filenames */
2187 status = srvstr_push(pdata, flags2, pdata+12, fstype,
2188 PTR_DIFF(end_data, pdata+12),
2189 STR_UNICODE, &len);
2190 if (!NT_STATUS_IS_OK(status)) {
2191 return status;
2193 SIVAL(pdata,8,len);
2194 data_len = 12 + len;
2195 if (max_data_bytes >= 16 && data_len > max_data_bytes) {
2196 /* the client only requested a portion of the
2197 file system name */
2198 data_len = max_data_bytes;
2199 status = STATUS_BUFFER_OVERFLOW;
2201 *fixed_portion = 16;
2202 break;
2204 case SMB_QUERY_FS_LABEL_INFO:
2205 case SMB_FS_LABEL_INFORMATION:
2206 status = srvstr_push(pdata, flags2, pdata+4, vname,
2207 PTR_DIFF(end_data, pdata+4), 0, &len);
2208 if (!NT_STATUS_IS_OK(status)) {
2209 return status;
2211 data_len = 4 + len;
2212 SIVAL(pdata,0,len);
2213 break;
2215 case SMB_QUERY_FS_VOLUME_INFO:
2216 case SMB_FS_VOLUME_INFORMATION:
2217 put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER,
2218 pdata, &st.st_ex_btime);
2220 * Add volume serial number - hash of a combination of
2221 * the called hostname and the service name.
2223 serial = generate_volume_serial_number(lp_sub, snum);
2224 SIVAL(pdata,8,serial);
2226 /* Max label len is 32 characters. */
2227 status = srvstr_push(pdata, flags2, pdata+18, vname,
2228 PTR_DIFF(end_data, pdata+18),
2229 STR_UNICODE, &len);
2230 if (!NT_STATUS_IS_OK(status)) {
2231 return status;
2233 SIVAL(pdata,12,len);
2234 data_len = 18+len;
2236 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO "
2237 "namelen = %d, vol=%s serv=%s "
2238 "serial=0x%04"PRIx32"\n",
2239 (int)strlen(vname),vname,
2240 lp_servicename(talloc_tos(), lp_sub, snum),
2241 serial));
2242 if (max_data_bytes >= 24 && data_len > max_data_bytes) {
2243 /* the client only requested a portion of the
2244 volume label */
2245 data_len = max_data_bytes;
2246 status = STATUS_BUFFER_OVERFLOW;
2248 *fixed_portion = 24;
2249 break;
2251 case SMB_QUERY_FS_SIZE_INFO:
2252 case SMB_FS_SIZE_INFORMATION:
2254 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
2255 data_len = 24;
2256 df_ret = get_dfree_info(conn, &smb_fname, &bsize,
2257 &dfree, &dsize);
2258 if (df_ret == (uint64_t)-1) {
2259 return map_nt_error_from_unix(errno);
2261 block_size = lp_block_size(snum);
2262 if (bsize < block_size) {
2263 uint64_t factor = block_size/bsize;
2264 bsize = block_size;
2265 dsize /= factor;
2266 dfree /= factor;
2268 if (bsize > block_size) {
2269 uint64_t factor = bsize/block_size;
2270 bsize = block_size;
2271 dsize *= factor;
2272 dfree *= factor;
2274 sectors_per_unit = bsize/bytes_per_sector;
2275 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2276 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2277 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2278 SBIG_UINT(pdata,0,dsize);
2279 SBIG_UINT(pdata,8,dfree);
2280 SIVAL(pdata,16,sectors_per_unit);
2281 SIVAL(pdata,20,bytes_per_sector);
2282 *fixed_portion = 24;
2283 break;
2286 case SMB_FS_FULL_SIZE_INFORMATION:
2288 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
2289 data_len = 32;
2290 df_ret = get_dfree_info(conn, &smb_fname, &bsize,
2291 &dfree, &dsize);
2292 if (df_ret == (uint64_t)-1) {
2293 return map_nt_error_from_unix(errno);
2295 block_size = lp_block_size(snum);
2296 if (bsize < block_size) {
2297 uint64_t factor = block_size/bsize;
2298 bsize = block_size;
2299 dsize /= factor;
2300 dfree /= factor;
2302 if (bsize > block_size) {
2303 uint64_t factor = bsize/block_size;
2304 bsize = block_size;
2305 dsize *= factor;
2306 dfree *= factor;
2308 sectors_per_unit = bsize/bytes_per_sector;
2309 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2310 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2311 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2312 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2313 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2314 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2315 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2316 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2317 *fixed_portion = 32;
2318 break;
2321 case SMB_QUERY_FS_DEVICE_INFO:
2322 case SMB_FS_DEVICE_INFORMATION:
2324 uint32_t characteristics = FILE_DEVICE_IS_MOUNTED;
2326 if (!CAN_WRITE(conn)) {
2327 characteristics |= FILE_READ_ONLY_DEVICE;
2329 data_len = 8;
2330 SIVAL(pdata,0,FILE_DEVICE_DISK); /* dev type */
2331 SIVAL(pdata,4,characteristics);
2332 *fixed_portion = 8;
2333 break;
2336 #ifdef HAVE_SYS_QUOTAS
2337 case SMB_FS_QUOTA_INFORMATION:
2339 * what we have to send --metze:
2341 * Unknown1: 24 NULL bytes
2342 * Soft Quota Threshold: 8 bytes seems like uint64_t or so
2343 * Hard Quota Limit: 8 bytes seems like uint64_t or so
2344 * Quota Flags: 2 byte :
2345 * Unknown3: 6 NULL bytes
2347 * 48 bytes total
2349 * details for Quota Flags:
2351 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2352 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2353 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2354 * 0x0001 Enable Quotas: enable quota for this fs
2358 /* we need to fake up a fsp here,
2359 * because its not send in this call
2361 files_struct tmpfsp;
2362 SMB_NTQUOTA_STRUCT quotas;
2364 ZERO_STRUCT(tmpfsp);
2365 ZERO_STRUCT(quotas);
2367 tmpfsp.conn = conn;
2368 tmpfsp.fnum = FNUM_FIELD_INVALID;
2370 /* access check */
2371 if (get_current_uid(conn) != 0) {
2372 DEBUG(0,("get_user_quota: access_denied "
2373 "service [%s] user [%s]\n",
2374 lp_servicename(talloc_tos(), lp_sub, SNUM(conn)),
2375 conn->session_info->unix_info->unix_name));
2376 return NT_STATUS_ACCESS_DENIED;
2379 status = vfs_get_ntquota(&tmpfsp, SMB_USER_FS_QUOTA_TYPE,
2380 NULL, &quotas);
2381 if (!NT_STATUS_IS_OK(status)) {
2382 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), lp_sub, SNUM(conn))));
2383 return status;
2386 data_len = 48;
2388 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
2389 lp_servicename(talloc_tos(), lp_sub, SNUM(conn))));
2391 /* Unknown1 24 NULL bytes*/
2392 SBIG_UINT(pdata,0,(uint64_t)0);
2393 SBIG_UINT(pdata,8,(uint64_t)0);
2394 SBIG_UINT(pdata,16,(uint64_t)0);
2396 /* Default Soft Quota 8 bytes */
2397 SBIG_UINT(pdata,24,quotas.softlim);
2399 /* Default Hard Quota 8 bytes */
2400 SBIG_UINT(pdata,32,quotas.hardlim);
2402 /* Quota flag 2 bytes */
2403 SSVAL(pdata,40,quotas.qflags);
2405 /* Unknown3 6 NULL bytes */
2406 SSVAL(pdata,42,0);
2407 SIVAL(pdata,44,0);
2409 break;
2411 #endif /* HAVE_SYS_QUOTAS */
2412 case SMB_FS_OBJECTID_INFORMATION:
2414 unsigned char objid[16];
2415 struct smb_extended_info extended_info;
2416 memcpy(pdata,create_volume_objectid(conn, objid),16);
2417 samba_extended_info_version (&extended_info);
2418 SIVAL(pdata,16,extended_info.samba_magic);
2419 SIVAL(pdata,20,extended_info.samba_version);
2420 SIVAL(pdata,24,extended_info.samba_subversion);
2421 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
2422 memcpy(pdata+36,extended_info.samba_version_string,28);
2423 data_len = 64;
2424 break;
2427 case SMB_FS_SECTOR_SIZE_INFORMATION:
2429 data_len = 28;
2431 * These values match a physical Windows Server 2012
2432 * share backed by NTFS atop spinning rust.
2434 DEBUG(5, ("SMB_FS_SECTOR_SIZE_INFORMATION:"));
2435 /* logical_bytes_per_sector */
2436 SIVAL(pdata, 0, bytes_per_sector);
2437 /* phys_bytes_per_sector_atomic */
2438 SIVAL(pdata, 4, bytes_per_sector);
2439 /* phys_bytes_per_sector_perf */
2440 SIVAL(pdata, 8, bytes_per_sector);
2441 /* fs_effective_phys_bytes_per_sector_atomic */
2442 SIVAL(pdata, 12, bytes_per_sector);
2443 /* flags */
2444 SIVAL(pdata, 16, SSINFO_FLAGS_ALIGNED_DEVICE
2445 | SSINFO_FLAGS_PARTITION_ALIGNED_ON_DEVICE);
2446 /* byte_off_sector_align */
2447 SIVAL(pdata, 20, 0);
2448 /* byte_off_partition_align */
2449 SIVAL(pdata, 24, 0);
2450 *fixed_portion = 28;
2451 break;
2455 #if defined(WITH_SMB1SERVER)
2457 * Query the version and capabilities of the CIFS UNIX extensions
2458 * in use.
2461 case SMB_QUERY_CIFS_UNIX_INFO:
2463 bool large_write = lp_min_receive_file_size() &&
2464 !smb1_srv_is_signing_active(xconn);
2465 bool large_read = !smb1_srv_is_signing_active(xconn);
2466 int encrypt_caps = 0;
2468 if (!lp_smb1_unix_extensions()) {
2469 return NT_STATUS_INVALID_LEVEL;
2472 switch (conn->encrypt_level) {
2473 case SMB_SIGNING_OFF:
2474 encrypt_caps = 0;
2475 break;
2476 case SMB_SIGNING_DESIRED:
2477 case SMB_SIGNING_IF_REQUIRED:
2478 case SMB_SIGNING_DEFAULT:
2479 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
2480 break;
2481 case SMB_SIGNING_REQUIRED:
2482 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
2483 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
2484 large_write = false;
2485 large_read = false;
2486 break;
2489 data_len = 12;
2490 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2491 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2493 /* We have POSIX ACLs, pathname, encryption,
2494 * large read/write, and locking capability. */
2496 SBIG_UINT(pdata,4,((uint64_t)(
2497 CIFS_UNIX_POSIX_ACLS_CAP|
2498 CIFS_UNIX_POSIX_PATHNAMES_CAP|
2499 CIFS_UNIX_FCNTL_LOCKS_CAP|
2500 CIFS_UNIX_EXTATTR_CAP|
2501 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
2502 encrypt_caps|
2503 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
2504 (large_write ?
2505 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
2506 break;
2508 #endif
2510 case SMB_QUERY_POSIX_FS_INFO:
2511 case SMB2_FS_POSIX_INFORMATION_INTERNAL:
2513 int rc;
2514 struct vfs_statvfs_struct svfs;
2516 if (!fsinfo_unix_valid_level(conn, fsp, info_level)) {
2517 return NT_STATUS_INVALID_LEVEL;
2520 rc = SMB_VFS_STATVFS(conn, &smb_fname, &svfs);
2522 if (!rc) {
2523 data_len = 56;
2524 SIVAL(pdata,0,svfs.OptimalTransferSize);
2525 SIVAL(pdata,4,svfs.BlockSize);
2526 SBIG_UINT(pdata,8,svfs.TotalBlocks);
2527 SBIG_UINT(pdata,16,svfs.BlocksAvail);
2528 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
2529 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
2530 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
2531 SBIG_UINT(pdata,48,svfs.FsIdentifier);
2532 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO successful\n"));
2533 #ifdef EOPNOTSUPP
2534 } else if (rc == EOPNOTSUPP) {
2535 return NT_STATUS_INVALID_LEVEL;
2536 #endif /* EOPNOTSUPP */
2537 } else {
2538 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(talloc_tos(), lp_sub, SNUM(conn))));
2539 return NT_STATUS_DOS(ERRSRV, ERRerror);
2541 break;
2544 case SMB_QUERY_POSIX_WHOAMI:
2546 uint32_t flags = 0;
2547 uint32_t sid_bytes;
2548 uint32_t i;
2550 if (!lp_smb1_unix_extensions()) {
2551 return NT_STATUS_INVALID_LEVEL;
2554 if (max_data_bytes < 40) {
2555 return NT_STATUS_BUFFER_TOO_SMALL;
2558 if (security_session_user_level(conn->session_info, NULL) < SECURITY_USER) {
2559 flags |= SMB_WHOAMI_GUEST;
2562 /* NOTE: 8 bytes for UID/GID, irrespective of native
2563 * platform size. This matches
2564 * SMB_QUERY_FILE_UNIX_BASIC and friends.
2566 data_len = 4 /* flags */
2567 + 4 /* flag mask */
2568 + 8 /* uid */
2569 + 8 /* gid */
2570 + 4 /* ngroups */
2571 + 4 /* num_sids */
2572 + 4 /* SID bytes */
2573 + 4 /* pad/reserved */
2574 + (conn->session_info->unix_token->ngroups * 8)
2575 /* groups list */
2576 + (conn->session_info->security_token->num_sids *
2577 SID_MAX_SIZE)
2578 /* SID list */;
2580 SIVAL(pdata, 0, flags);
2581 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
2582 SBIG_UINT(pdata, 8,
2583 (uint64_t)conn->session_info->unix_token->uid);
2584 SBIG_UINT(pdata, 16,
2585 (uint64_t)conn->session_info->unix_token->gid);
2588 if (data_len >= max_data_bytes) {
2589 /* Potential overflow, skip the GIDs and SIDs. */
2591 SIVAL(pdata, 24, 0); /* num_groups */
2592 SIVAL(pdata, 28, 0); /* num_sids */
2593 SIVAL(pdata, 32, 0); /* num_sid_bytes */
2594 SIVAL(pdata, 36, 0); /* reserved */
2596 data_len = 40;
2597 break;
2600 SIVAL(pdata, 24, conn->session_info->unix_token->ngroups);
2601 SIVAL(pdata, 28, conn->session_info->security_token->num_sids);
2603 /* We walk the SID list twice, but this call is fairly
2604 * infrequent, and I don't expect that it's performance
2605 * sensitive -- jpeach
2607 for (i = 0, sid_bytes = 0;
2608 i < conn->session_info->security_token->num_sids; ++i) {
2609 sid_bytes += ndr_size_dom_sid(
2610 &conn->session_info->security_token->sids[i],
2614 /* SID list byte count */
2615 SIVAL(pdata, 32, sid_bytes);
2617 /* 4 bytes pad/reserved - must be zero */
2618 SIVAL(pdata, 36, 0);
2619 data_len = 40;
2621 /* GID list */
2622 for (i = 0; i < conn->session_info->unix_token->ngroups; ++i) {
2623 SBIG_UINT(pdata, data_len,
2624 (uint64_t)conn->session_info->unix_token->groups[i]);
2625 data_len += 8;
2628 /* SID list */
2629 for (i = 0;
2630 i < conn->session_info->security_token->num_sids; ++i) {
2631 int sid_len = ndr_size_dom_sid(
2632 &conn->session_info->security_token->sids[i],
2635 sid_linearize((uint8_t *)(pdata + data_len),
2636 sid_len,
2637 &conn->session_info->security_token->sids[i]);
2638 data_len += sid_len;
2641 break;
2644 case SMB_MAC_QUERY_FS_INFO:
2646 * Thursby MAC extension... ONLY on NTFS filesystems
2647 * once we do streams then we don't need this
2649 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
2650 data_len = 88;
2651 SIVAL(pdata,84,0x100); /* Don't support mac... */
2652 break;
2655 FALL_THROUGH;
2656 default:
2657 return NT_STATUS_INVALID_LEVEL;
2660 *ret_data_len = data_len;
2661 return status;
2664 NTSTATUS smb_set_fsquota(connection_struct *conn,
2665 struct smb_request *req,
2666 files_struct *fsp,
2667 const DATA_BLOB *qdata)
2669 const struct loadparm_substitution *lp_sub =
2670 loadparm_s3_global_substitution();
2671 NTSTATUS status;
2672 SMB_NTQUOTA_STRUCT quotas;
2674 ZERO_STRUCT(quotas);
2676 /* access check */
2677 if ((get_current_uid(conn) != 0) || !CAN_WRITE(conn)) {
2678 DBG_NOTICE("access_denied service [%s] user [%s]\n",
2679 lp_servicename(talloc_tos(), lp_sub, SNUM(conn)),
2680 conn->session_info->unix_info->unix_name);
2681 return NT_STATUS_ACCESS_DENIED;
2684 if (!check_fsp_ntquota_handle(conn, req,
2685 fsp)) {
2686 DBG_WARNING("no valid QUOTA HANDLE\n");
2687 return NT_STATUS_INVALID_HANDLE;
2690 /* note: normally there're 48 bytes,
2691 * but we didn't use the last 6 bytes for now
2692 * --metze
2694 if (qdata->length < 42) {
2695 DBG_ERR("requires total_data(%zu) >= 42 bytes!\n",
2696 qdata->length);
2697 return NT_STATUS_INVALID_PARAMETER;
2700 /* unknown_1 24 NULL bytes in pdata*/
2702 /* the soft quotas 8 bytes (uint64_t)*/
2703 quotas.softlim = BVAL(qdata->data,24);
2705 /* the hard quotas 8 bytes (uint64_t)*/
2706 quotas.hardlim = BVAL(qdata->data,32);
2708 /* quota_flags 2 bytes **/
2709 quotas.qflags = SVAL(qdata->data,40);
2711 /* unknown_2 6 NULL bytes follow*/
2713 /* now set the quotas */
2714 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
2715 DBG_WARNING("vfs_set_ntquota() failed for service [%s]\n",
2716 lp_servicename(talloc_tos(), lp_sub, SNUM(conn)));
2717 status = map_nt_error_from_unix(errno);
2718 } else {
2719 status = NT_STATUS_OK;
2721 return status;
2724 NTSTATUS smbd_do_setfsinfo(connection_struct *conn,
2725 struct smb_request *req,
2726 TALLOC_CTX *mem_ctx,
2727 uint16_t info_level,
2728 files_struct *fsp,
2729 const DATA_BLOB *pdata)
2731 switch (info_level) {
2732 case SMB_FS_QUOTA_INFORMATION:
2734 return smb_set_fsquota(conn,
2735 req,
2736 fsp,
2737 pdata);
2740 default:
2741 break;
2743 return NT_STATUS_INVALID_LEVEL;
2746 /****************************************************************************
2747 Store the FILE_UNIX_BASIC info.
2748 ****************************************************************************/
2750 char *store_file_unix_basic(connection_struct *conn,
2751 char *pdata,
2752 files_struct *fsp,
2753 const SMB_STRUCT_STAT *psbuf)
2755 dev_t devno;
2757 DBG_DEBUG("SMB_QUERY_FILE_UNIX_BASIC\n");
2758 DBG_NOTICE("st_mode=%o\n", (int)psbuf->st_ex_mode);
2760 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
2761 pdata += 8;
2763 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
2764 pdata += 8;
2766 put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata, &psbuf->st_ex_ctime); /* Change Time 64 Bit */
2767 put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER ,pdata+8, &psbuf->st_ex_atime); /* Last access time 64 Bit */
2768 put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+16, &psbuf->st_ex_mtime); /* Last modification time 64 Bit */
2769 pdata += 24;
2771 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
2772 SIVAL(pdata,4,0);
2773 pdata += 8;
2775 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
2776 SIVAL(pdata,4,0);
2777 pdata += 8;
2779 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
2780 pdata += 4;
2782 if (S_ISBLK(psbuf->st_ex_mode) || S_ISCHR(psbuf->st_ex_mode)) {
2783 devno = psbuf->st_ex_rdev;
2784 } else {
2785 devno = psbuf->st_ex_dev;
2788 SIVAL(pdata,0,unix_dev_major(devno)); /* Major device number if type is device */
2789 SIVAL(pdata,4,0);
2790 pdata += 8;
2792 SIVAL(pdata,0,unix_dev_minor(devno)); /* Minor device number if type is device */
2793 SIVAL(pdata,4,0);
2794 pdata += 8;
2796 SINO_T_VAL(pdata, 0, psbuf->st_ex_ino); /* inode number */
2797 pdata += 8;
2799 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
2800 SIVAL(pdata,4,0);
2801 pdata += 8;
2803 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
2804 SIVAL(pdata,4,0);
2805 pdata += 8;
2807 return pdata;
2810 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
2811 * the chflags(2) (or equivalent) flags.
2813 * XXX: this really should be behind the VFS interface. To do this, we would
2814 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
2815 * Each VFS module could then implement its own mapping as appropriate for the
2816 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
2818 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
2819 info2_flags_map[] =
2821 #ifdef UF_NODUMP
2822 { UF_NODUMP, EXT_DO_NOT_BACKUP },
2823 #endif
2825 #ifdef UF_IMMUTABLE
2826 { UF_IMMUTABLE, EXT_IMMUTABLE },
2827 #endif
2829 #ifdef UF_APPEND
2830 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
2831 #endif
2833 #ifdef UF_HIDDEN
2834 { UF_HIDDEN, EXT_HIDDEN },
2835 #endif
2837 /* Do not remove. We need to guarantee that this array has at least one
2838 * entry to build on HP-UX.
2840 { 0, 0 }
2844 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
2845 uint32_t *smb_fflags, uint32_t *smb_fmask)
2847 size_t i;
2849 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
2850 *smb_fmask |= info2_flags_map[i].smb_fflag;
2851 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
2852 *smb_fflags |= info2_flags_map[i].smb_fflag;
2857 bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
2858 const uint32_t smb_fflags,
2859 const uint32_t smb_fmask,
2860 int *stat_fflags)
2862 uint32_t max_fmask = 0;
2863 size_t i;
2865 *stat_fflags = psbuf->st_ex_flags;
2867 /* For each flags requested in smb_fmask, check the state of the
2868 * corresponding flag in smb_fflags and set or clear the matching
2869 * stat flag.
2872 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
2873 max_fmask |= info2_flags_map[i].smb_fflag;
2874 if (smb_fmask & info2_flags_map[i].smb_fflag) {
2875 if (smb_fflags & info2_flags_map[i].smb_fflag) {
2876 *stat_fflags |= info2_flags_map[i].stat_fflag;
2877 } else {
2878 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
2883 /* If smb_fmask is asking to set any bits that are not supported by
2884 * our flag mappings, we should fail.
2886 if ((smb_fmask & max_fmask) != smb_fmask) {
2887 return False;
2890 return True;
2894 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
2895 * of file flags and birth (create) time.
2897 char *store_file_unix_basic_info2(connection_struct *conn,
2898 char *pdata,
2899 files_struct *fsp,
2900 const SMB_STRUCT_STAT *psbuf)
2902 uint32_t file_flags = 0;
2903 uint32_t flags_mask = 0;
2905 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
2907 /* Create (birth) time 64 bit */
2908 put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER,pdata, &psbuf->st_ex_btime);
2909 pdata += 8;
2911 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
2912 SIVAL(pdata, 0, file_flags); /* flags */
2913 SIVAL(pdata, 4, flags_mask); /* mask */
2914 pdata += 8;
2916 return pdata;
2919 static NTSTATUS marshall_stream_info(unsigned int num_streams,
2920 const struct stream_struct *streams,
2921 char *data,
2922 unsigned int max_data_bytes,
2923 unsigned int *data_size)
2925 unsigned int i;
2926 unsigned int ofs = 0;
2928 if (max_data_bytes < 32) {
2929 return NT_STATUS_INFO_LENGTH_MISMATCH;
2932 for (i = 0; i < num_streams; i++) {
2933 unsigned int next_offset;
2934 size_t namelen;
2935 smb_ucs2_t *namebuf;
2937 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
2938 streams[i].name, &namelen) ||
2939 namelen <= 2)
2941 return NT_STATUS_INVALID_PARAMETER;
2945 * name_buf is now null-terminated, we need to marshall as not
2946 * terminated
2949 namelen -= 2;
2952 * We cannot overflow ...
2954 if ((ofs + 24 + namelen) > max_data_bytes) {
2955 DEBUG(10, ("refusing to overflow reply at stream %u\n",
2956 i));
2957 TALLOC_FREE(namebuf);
2958 return STATUS_BUFFER_OVERFLOW;
2961 SIVAL(data, ofs+4, namelen);
2962 SOFF_T(data, ofs+8, streams[i].size);
2963 SOFF_T(data, ofs+16, streams[i].alloc_size);
2964 memcpy(data+ofs+24, namebuf, namelen);
2965 TALLOC_FREE(namebuf);
2967 next_offset = ofs + 24 + namelen;
2969 if (i == num_streams-1) {
2970 SIVAL(data, ofs, 0);
2972 else {
2973 unsigned int align = ndr_align_size(next_offset, 8);
2975 if ((next_offset + align) > max_data_bytes) {
2976 DEBUG(10, ("refusing to overflow align "
2977 "reply at stream %u\n",
2978 i));
2979 TALLOC_FREE(namebuf);
2980 return STATUS_BUFFER_OVERFLOW;
2983 memset(data+next_offset, 0, align);
2984 next_offset += align;
2986 SIVAL(data, ofs, next_offset - ofs);
2987 ofs = next_offset;
2990 ofs = next_offset;
2993 DEBUG(10, ("max_data: %u, data_size: %u\n", max_data_bytes, ofs));
2995 *data_size = ofs;
2997 return NT_STATUS_OK;
3000 NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
3001 TALLOC_CTX *mem_ctx,
3002 struct smb_request *req,
3003 uint16_t info_level,
3004 files_struct *fsp,
3005 struct smb_filename *smb_fname,
3006 bool delete_pending,
3007 struct timespec write_time_ts,
3008 struct ea_list *ea_list,
3009 uint16_t flags2,
3010 unsigned int max_data_bytes,
3011 size_t *fixed_portion,
3012 char **ppdata,
3013 unsigned int *pdata_size)
3015 char *pdata = *ppdata;
3016 char *dstart, *dend;
3017 unsigned int data_size;
3018 struct timespec create_time_ts, mtime_ts, atime_ts, ctime_ts;
3019 SMB_STRUCT_STAT *psbuf = NULL;
3020 SMB_STRUCT_STAT *base_sp = NULL;
3021 char *p;
3022 char *base_name;
3023 char *dos_fname;
3024 int mode;
3025 int nlink;
3026 NTSTATUS status;
3027 uint64_t file_size = 0;
3028 uint64_t pos = 0;
3029 uint64_t allocation_size = 0;
3030 uint64_t file_id = 0;
3031 uint32_t access_mask = 0;
3032 size_t len = 0;
3034 if (INFO_LEVEL_IS_UNIX(info_level)) {
3035 bool ok = false;
3037 if (lp_smb1_unix_extensions() && req->posix_pathnames) {
3038 DBG_DEBUG("SMB1 unix extensions activated\n");
3039 ok = true;
3042 if (conn_using_smb2(conn->sconn) &&
3043 (fsp->posix_flags & FSP_POSIX_FLAGS_OPEN))
3045 DBG_DEBUG("SMB2 posix open\n");
3046 ok = true;
3049 if (!ok) {
3050 return NT_STATUS_INVALID_LEVEL;
3054 DBG_INFO("%s (%s) level=%d max_data=%u\n",
3055 smb_fname_str_dbg(smb_fname),
3056 fsp_fnum_dbg(fsp),
3057 info_level, max_data_bytes);
3060 * In case of querying a symlink in POSIX context,
3061 * fsp will be NULL. fdos_mode() deals with it.
3063 if (fsp != NULL) {
3064 smb_fname = fsp->fsp_name;
3066 mode = fdos_mode(fsp);
3067 psbuf = &smb_fname->st;
3069 if (fsp != NULL) {
3070 base_sp = fsp->base_fsp ?
3071 &fsp->base_fsp->fsp_name->st :
3072 &fsp->fsp_name->st;
3073 } else {
3074 base_sp = &smb_fname->st;
3077 nlink = psbuf->st_ex_nlink;
3079 if (nlink && (mode&FILE_ATTRIBUTE_DIRECTORY)) {
3080 nlink = 1;
3083 if ((nlink > 0) && delete_pending) {
3084 nlink -= 1;
3087 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
3088 return NT_STATUS_INVALID_PARAMETER;
3091 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3092 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
3093 if (*ppdata == NULL) {
3094 return NT_STATUS_NO_MEMORY;
3096 pdata = *ppdata;
3097 dstart = pdata;
3098 dend = dstart + data_size - 1;
3100 if (!is_omit_timespec(&write_time_ts) &&
3101 !INFO_LEVEL_IS_UNIX(info_level))
3103 update_stat_ex_mtime(psbuf, write_time_ts);
3106 create_time_ts = get_create_timespec(conn, fsp, smb_fname);
3107 mtime_ts = psbuf->st_ex_mtime;
3108 atime_ts = psbuf->st_ex_atime;
3109 ctime_ts = get_change_timespec(conn, fsp, smb_fname);
3111 if (lp_dos_filetime_resolution(SNUM(conn))) {
3112 dos_filetime_timespec(&create_time_ts);
3113 dos_filetime_timespec(&mtime_ts);
3114 dos_filetime_timespec(&atime_ts);
3115 dos_filetime_timespec(&ctime_ts);
3118 p = strrchr_m(smb_fname->base_name,'/');
3119 if (p == NULL) {
3120 base_name = smb_fname->base_name;
3121 } else {
3122 base_name = p+1;
3125 /* NT expects the name to be in an exact form of the *full*
3126 filename. See the trans2 torture test */
3127 if (ISDOT(base_name)) {
3128 dos_fname = talloc_strdup(mem_ctx, "\\");
3129 if (!dos_fname) {
3130 return NT_STATUS_NO_MEMORY;
3132 } else {
3133 dos_fname = talloc_asprintf(mem_ctx,
3134 "\\%s",
3135 smb_fname->base_name);
3136 if (!dos_fname) {
3137 return NT_STATUS_NO_MEMORY;
3139 if (is_named_stream(smb_fname)) {
3140 dos_fname = talloc_asprintf(dos_fname, "%s",
3141 smb_fname->stream_name);
3142 if (!dos_fname) {
3143 return NT_STATUS_NO_MEMORY;
3147 string_replace(dos_fname, '/', '\\');
3150 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, psbuf);
3152 if (fsp == NULL || !fsp->fsp_flags.is_fsa) {
3153 /* Do we have this path open ? */
3154 struct file_id fileid = vfs_file_id_from_sbuf(conn, psbuf);
3155 files_struct *fsp1 = file_find_di_first(
3156 conn->sconn, fileid, true);
3157 if (fsp1 && fsp1->initial_allocation_size) {
3158 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, psbuf);
3162 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
3163 file_size = get_file_size_stat(psbuf);
3166 if (fsp) {
3167 pos = fh_get_position_information(fsp->fh);
3170 if (fsp) {
3171 access_mask = fsp->access_mask;
3172 } else {
3173 /* GENERIC_EXECUTE mapping from Windows */
3174 access_mask = 0x12019F;
3177 /* This should be an index number - looks like
3178 dev/ino to me :-)
3180 I think this causes us to fail the IFSKIT
3181 BasicFileInformationTest. -tpot */
3182 file_id = SMB_VFS_FS_FILE_ID(conn, base_sp);
3184 *fixed_portion = 0;
3186 switch (info_level) {
3187 case SMB_INFO_STANDARD:
3188 DBG_DEBUG("SMB_INFO_STANDARD\n");
3189 data_size = 22;
3190 srv_put_dos_date2_ts(pdata,
3191 l1_fdateCreation,
3192 create_time_ts);
3193 srv_put_dos_date2_ts(pdata,
3194 l1_fdateLastAccess,
3195 atime_ts);
3196 srv_put_dos_date2_ts(pdata,
3197 l1_fdateLastWrite,
3198 mtime_ts); /* write time */
3199 SIVAL(pdata,l1_cbFile,(uint32_t)file_size);
3200 SIVAL(pdata,l1_cbFileAlloc,(uint32_t)allocation_size);
3201 SSVAL(pdata,l1_attrFile,mode);
3202 break;
3204 case SMB_INFO_QUERY_EA_SIZE:
3206 unsigned int ea_size =
3207 estimate_ea_size(smb_fname->fsp);
3208 DBG_DEBUG("SMB_INFO_QUERY_EA_SIZE\n");
3209 data_size = 26;
3210 srv_put_dos_date2_ts(pdata, 0, create_time_ts);
3211 srv_put_dos_date2_ts(pdata, 4, atime_ts);
3212 srv_put_dos_date2_ts(pdata,
3214 mtime_ts); /* write time */
3215 SIVAL(pdata,12,(uint32_t)file_size);
3216 SIVAL(pdata,16,(uint32_t)allocation_size);
3217 SSVAL(pdata,20,mode);
3218 SIVAL(pdata,22,ea_size);
3219 break;
3222 case SMB_INFO_IS_NAME_VALID:
3223 DBG_DEBUG("SMB_INFO_IS_NAME_VALID\n");
3224 if (fsp) {
3225 /* os/2 needs this ? really ?*/
3226 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
3228 /* This is only reached for qpathinfo */
3229 data_size = 0;
3230 break;
3232 case SMB_INFO_QUERY_EAS_FROM_LIST:
3234 size_t total_ea_len = 0;
3235 struct ea_list *ea_file_list = NULL;
3236 DBG_DEBUG("SMB_INFO_QUERY_EAS_FROM_LIST\n");
3238 status =
3239 get_ea_list_from_fsp(mem_ctx,
3240 smb_fname->fsp,
3241 &total_ea_len, &ea_file_list);
3242 if (!NT_STATUS_IS_OK(status)) {
3243 return status;
3246 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
3248 if (!ea_list || (total_ea_len > data_size)) {
3249 data_size = 4;
3250 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
3251 break;
3254 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
3255 break;
3258 case SMB_INFO_QUERY_ALL_EAS:
3260 /* We have data_size bytes to put EA's into. */
3261 size_t total_ea_len = 0;
3262 DBG_DEBUG(" SMB_INFO_QUERY_ALL_EAS\n");
3264 status = get_ea_list_from_fsp(mem_ctx,
3265 smb_fname->fsp,
3266 &total_ea_len, &ea_list);
3267 if (!NT_STATUS_IS_OK(status)) {
3268 return status;
3271 if (!ea_list || (total_ea_len > data_size)) {
3272 data_size = 4;
3273 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
3274 break;
3277 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
3278 break;
3281 case SMB2_FILE_FULL_EA_INFORMATION:
3283 /* We have data_size bytes to put EA's into. */
3284 size_t total_ea_len = 0;
3285 struct ea_list *ea_file_list = NULL;
3287 DBG_DEBUG("SMB2_INFO_QUERY_ALL_EAS\n");
3289 /*TODO: add filtering and index handling */
3291 status =
3292 get_ea_list_from_fsp(mem_ctx,
3293 smb_fname->fsp,
3294 &total_ea_len, &ea_file_list);
3295 if (!NT_STATUS_IS_OK(status)) {
3296 return status;
3298 if (!ea_file_list) {
3299 return NT_STATUS_NO_EAS_ON_FILE;
3302 status = fill_ea_chained_buffer(mem_ctx,
3303 pdata,
3304 data_size,
3305 &data_size,
3306 conn, ea_file_list);
3307 if (!NT_STATUS_IS_OK(status)) {
3308 return status;
3310 break;
3313 case SMB_FILE_BASIC_INFORMATION:
3314 case SMB_QUERY_FILE_BASIC_INFO:
3316 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
3317 DBG_DEBUG("SMB_QUERY_FILE_BASIC_INFO\n");
3318 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
3319 } else {
3320 DBG_DEBUG("SMB_FILE_BASIC_INFORMATION\n");
3321 data_size = 40;
3322 SIVAL(pdata,36,0);
3324 put_long_date_full_timespec(conn->ts_res,pdata,&create_time_ts);
3325 put_long_date_full_timespec(conn->ts_res,pdata+8,&atime_ts);
3326 put_long_date_full_timespec(conn->ts_res,pdata+16,&mtime_ts); /* write time */
3327 put_long_date_full_timespec(conn->ts_res,pdata+24,&ctime_ts); /* change time */
3328 SIVAL(pdata,32,mode);
3330 DBG_INFO("SMB_QFBI - create: %s access: %s "
3331 "write: %s change: %s mode: %x\n",
3332 ctime(&create_time_ts.tv_sec),
3333 ctime(&atime_ts.tv_sec),
3334 ctime(&mtime_ts.tv_sec),
3335 ctime(&ctime_ts.tv_sec),
3336 mode);
3337 *fixed_portion = data_size;
3338 break;
3340 case SMB_FILE_STANDARD_INFORMATION:
3341 case SMB_QUERY_FILE_STANDARD_INFO:
3343 DBG_DEBUG("SMB_FILE_STANDARD_INFORMATION\n");
3344 data_size = 24;
3345 SOFF_T(pdata,0,allocation_size);
3346 SOFF_T(pdata,8,file_size);
3347 SIVAL(pdata,16,nlink);
3348 SCVAL(pdata,20,delete_pending?1:0);
3349 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
3350 SSVAL(pdata,22,0); /* Padding. */
3351 *fixed_portion = 24;
3352 break;
3354 case SMB_FILE_EA_INFORMATION:
3355 case SMB_QUERY_FILE_EA_INFO:
3357 unsigned int ea_size =
3358 estimate_ea_size(smb_fname->fsp);
3359 DBG_DEBUG("SMB_FILE_EA_INFORMATION\n");
3360 data_size = 4;
3361 *fixed_portion = 4;
3362 SIVAL(pdata,0,ea_size);
3363 break;
3366 /* Get the 8.3 name - used if NT SMB was negotiated. */
3367 case SMB_QUERY_FILE_ALT_NAME_INFO:
3368 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
3370 char mangled_name[13];
3371 DBG_DEBUG("SMB_FILE_ALTERNATE_NAME_INFORMATION\n");
3372 if (!name_to_8_3(base_name,mangled_name,
3373 True,conn->params)) {
3374 return NT_STATUS_NO_MEMORY;
3376 status = srvstr_push(dstart, flags2,
3377 pdata+4, mangled_name,
3378 PTR_DIFF(dend, pdata+4),
3379 STR_UNICODE, &len);
3380 if (!NT_STATUS_IS_OK(status)) {
3381 return status;
3383 data_size = 4 + len;
3384 SIVAL(pdata,0,len);
3385 *fixed_portion = 8;
3386 break;
3389 case SMB_QUERY_FILE_NAME_INFO:
3392 this must be *exactly* right for ACLs on mapped drives to work
3394 status = srvstr_push(dstart, flags2,
3395 pdata+4, dos_fname,
3396 PTR_DIFF(dend, pdata+4),
3397 STR_UNICODE, &len);
3398 if (!NT_STATUS_IS_OK(status)) {
3399 return status;
3401 DBG_DEBUG("SMB_QUERY_FILE_NAME_INFO\n");
3402 data_size = 4 + len;
3403 SIVAL(pdata,0,len);
3404 break;
3407 case SMB_FILE_NORMALIZED_NAME_INFORMATION:
3409 char *nfname = NULL;
3411 if (fsp == NULL ||
3412 !conn_using_smb2(fsp->conn->sconn)) {
3413 return NT_STATUS_INVALID_LEVEL;
3416 nfname = talloc_strdup(mem_ctx, smb_fname->base_name);
3417 if (nfname == NULL) {
3418 return NT_STATUS_NO_MEMORY;
3421 if (ISDOT(nfname)) {
3422 nfname[0] = '\0';
3424 string_replace(nfname, '/', '\\');
3426 if (fsp_is_alternate_stream(fsp)) {
3427 const char *s = smb_fname->stream_name;
3428 const char *e = NULL;
3429 size_t n;
3431 SMB_ASSERT(s[0] != '\0');
3434 * smb_fname->stream_name is in form
3435 * of ':StrEam:$DATA', but we should only
3436 * append ':StrEam' here.
3439 e = strchr(&s[1], ':');
3440 if (e == NULL) {
3441 n = strlen(s);
3442 } else {
3443 n = PTR_DIFF(e, s);
3445 nfname = talloc_strndup_append(nfname, s, n);
3446 if (nfname == NULL) {
3447 return NT_STATUS_NO_MEMORY;
3451 status = srvstr_push(dstart, flags2,
3452 pdata+4, nfname,
3453 PTR_DIFF(dend, pdata+4),
3454 STR_UNICODE, &len);
3455 if (!NT_STATUS_IS_OK(status)) {
3456 return status;
3458 DBG_DEBUG("SMB_FILE_NORMALIZED_NAME_INFORMATION\n");
3459 data_size = 4 + len;
3460 SIVAL(pdata,0,len);
3461 *fixed_portion = 8;
3462 break;
3465 case SMB_FILE_ALLOCATION_INFORMATION:
3466 case SMB_QUERY_FILE_ALLOCATION_INFO:
3467 DBG_DEBUG("SMB_FILE_ALLOCATION_INFORMATION\n");
3468 data_size = 8;
3469 SOFF_T(pdata,0,allocation_size);
3470 break;
3472 case SMB_FILE_END_OF_FILE_INFORMATION:
3473 case SMB_QUERY_FILE_END_OF_FILEINFO:
3474 DBG_DEBUG("SMB_FILE_END_OF_FILE_INFORMATION\n");
3475 data_size = 8;
3476 SOFF_T(pdata,0,file_size);
3477 break;
3479 case SMB_QUERY_FILE_ALL_INFO:
3480 case SMB_FILE_ALL_INFORMATION:
3482 unsigned int ea_size =
3483 estimate_ea_size(smb_fname->fsp);
3484 DBG_DEBUG("SMB_FILE_ALL_INFORMATION\n");
3485 put_long_date_full_timespec(conn->ts_res,pdata,&create_time_ts);
3486 put_long_date_full_timespec(conn->ts_res,pdata+8,&atime_ts);
3487 put_long_date_full_timespec(conn->ts_res,pdata+16,&mtime_ts); /* write time */
3488 put_long_date_full_timespec(conn->ts_res,pdata+24,&ctime_ts); /* change time */
3489 SIVAL(pdata,32,mode);
3490 SIVAL(pdata,36,0); /* padding. */
3491 pdata += 40;
3492 SOFF_T(pdata,0,allocation_size);
3493 SOFF_T(pdata,8,file_size);
3494 SIVAL(pdata,16,nlink);
3495 SCVAL(pdata,20,delete_pending);
3496 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
3497 SSVAL(pdata,22,0);
3498 pdata += 24;
3499 SIVAL(pdata,0,ea_size);
3500 pdata += 4; /* EA info */
3501 status = srvstr_push(dstart, flags2,
3502 pdata+4, dos_fname,
3503 PTR_DIFF(dend, pdata+4),
3504 STR_UNICODE, &len);
3505 if (!NT_STATUS_IS_OK(status)) {
3506 return status;
3508 SIVAL(pdata,0,len);
3509 pdata += 4 + len;
3510 data_size = PTR_DIFF(pdata,(*ppdata));
3511 *fixed_portion = 10;
3512 break;
3515 case SMB2_FILE_ALL_INFORMATION:
3517 unsigned int ea_size =
3518 estimate_ea_size(smb_fname->fsp);
3519 DBG_DEBUG("SMB2_FILE_ALL_INFORMATION\n");
3520 put_long_date_full_timespec(conn->ts_res,pdata+0x00,&create_time_ts);
3521 put_long_date_full_timespec(conn->ts_res,pdata+0x08,&atime_ts);
3522 put_long_date_full_timespec(conn->ts_res,pdata+0x10,&mtime_ts); /* write time */
3523 put_long_date_full_timespec(conn->ts_res,pdata+0x18,&ctime_ts); /* change time */
3524 SIVAL(pdata, 0x20, mode);
3525 SIVAL(pdata, 0x24, 0); /* padding. */
3526 SBVAL(pdata, 0x28, allocation_size);
3527 SBVAL(pdata, 0x30, file_size);
3528 SIVAL(pdata, 0x38, nlink);
3529 SCVAL(pdata, 0x3C, delete_pending);
3530 SCVAL(pdata, 0x3D, (mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
3531 SSVAL(pdata, 0x3E, 0); /* padding */
3532 SBVAL(pdata, 0x40, file_id);
3533 SIVAL(pdata, 0x48, ea_size);
3534 SIVAL(pdata, 0x4C, access_mask);
3535 SBVAL(pdata, 0x50, pos);
3536 SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
3537 SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
3539 pdata += 0x60;
3541 status = srvstr_push(dstart, flags2,
3542 pdata+4, dos_fname,
3543 PTR_DIFF(dend, pdata+4),
3544 STR_UNICODE, &len);
3545 if (!NT_STATUS_IS_OK(status)) {
3546 return status;
3548 SIVAL(pdata,0,len);
3549 pdata += 4 + len;
3550 data_size = PTR_DIFF(pdata,(*ppdata));
3551 *fixed_portion = 104;
3552 break;
3554 case SMB_FILE_INTERNAL_INFORMATION:
3556 DBG_DEBUG("SMB_FILE_INTERNAL_INFORMATION\n");
3557 SBVAL(pdata, 0, file_id);
3558 data_size = 8;
3559 *fixed_portion = 8;
3560 break;
3562 case SMB_FILE_ACCESS_INFORMATION:
3563 DBG_DEBUG("SMB_FILE_ACCESS_INFORMATION\n");
3564 SIVAL(pdata, 0, access_mask);
3565 data_size = 4;
3566 *fixed_portion = 4;
3567 break;
3569 case SMB_FILE_NAME_INFORMATION:
3570 /* Pathname with leading '\'. */
3572 size_t byte_len;
3573 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
3574 DBG_DEBUG("SMB_FILE_NAME_INFORMATION\n");
3575 SIVAL(pdata,0,byte_len);
3576 data_size = 4 + byte_len;
3577 break;
3580 case SMB_FILE_DISPOSITION_INFORMATION:
3581 DBG_DEBUG("SMB_FILE_DISPOSITION_INFORMATION\n");
3582 data_size = 1;
3583 SCVAL(pdata,0,delete_pending);
3584 *fixed_portion = 1;
3585 break;
3587 case SMB_FILE_POSITION_INFORMATION:
3588 DBG_DEBUG("SMB_FILE_POSITION_INFORMATION\n");
3589 data_size = 8;
3590 SOFF_T(pdata,0,pos);
3591 *fixed_portion = 8;
3592 break;
3594 case SMB_FILE_MODE_INFORMATION:
3595 DBG_DEBUG("SMB_FILE_MODE_INFORMATION\n");
3596 SIVAL(pdata,0,mode);
3597 data_size = 4;
3598 *fixed_portion = 4;
3599 break;
3601 case SMB_FILE_ALIGNMENT_INFORMATION:
3602 DBG_DEBUG("SMB_FILE_ALIGNMENT_INFORMATION\n");
3603 SIVAL(pdata,0,0); /* No alignment needed. */
3604 data_size = 4;
3605 *fixed_portion = 4;
3606 break;
3609 * NT4 server just returns "invalid query" to this - if we try
3610 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
3611 * want this. JRA.
3613 /* The first statement above is false - verified using Thursby
3614 * client against NT4 -- gcolley.
3616 case SMB_QUERY_FILE_STREAM_INFO:
3617 case SMB_FILE_STREAM_INFORMATION: {
3618 unsigned int num_streams = 0;
3619 struct stream_struct *streams = NULL;
3621 DBG_DEBUG("SMB_FILE_STREAM_INFORMATION\n");
3623 if (is_ntfs_stream_smb_fname(smb_fname)) {
3624 return NT_STATUS_INVALID_PARAMETER;
3627 status = vfs_fstreaminfo(fsp,
3628 mem_ctx,
3629 &num_streams,
3630 &streams);
3632 if (!NT_STATUS_IS_OK(status)) {
3633 DBG_DEBUG("could not get stream info: %s\n",
3634 nt_errstr(status));
3635 return status;
3638 status = marshall_stream_info(num_streams, streams,
3639 pdata, max_data_bytes,
3640 &data_size);
3642 if (!NT_STATUS_IS_OK(status)) {
3643 DBG_DEBUG("marshall_stream_info failed: %s\n",
3644 nt_errstr(status));
3645 TALLOC_FREE(streams);
3646 return status;
3649 TALLOC_FREE(streams);
3651 *fixed_portion = 32;
3653 break;
3655 case SMB_QUERY_COMPRESSION_INFO:
3656 case SMB_FILE_COMPRESSION_INFORMATION:
3657 DBG_DEBUG("SMB_FILE_COMPRESSION_INFORMATION\n");
3658 SOFF_T(pdata,0,file_size);
3659 SIVAL(pdata,8,0); /* ??? */
3660 SIVAL(pdata,12,0); /* ??? */
3661 data_size = 16;
3662 *fixed_portion = 16;
3663 break;
3665 case SMB_FILE_NETWORK_OPEN_INFORMATION:
3666 DBG_DEBUG("SMB_FILE_NETWORK_OPEN_INFORMATION\n");
3667 put_long_date_full_timespec(conn->ts_res,pdata,&create_time_ts);
3668 put_long_date_full_timespec(conn->ts_res,pdata+8,&atime_ts);
3669 put_long_date_full_timespec(conn->ts_res,pdata+16,&mtime_ts); /* write time */
3670 put_long_date_full_timespec(conn->ts_res,pdata+24,&ctime_ts); /* change time */
3671 SOFF_T(pdata,32,allocation_size);
3672 SOFF_T(pdata,40,file_size);
3673 SIVAL(pdata,48,mode);
3674 SIVAL(pdata,52,0); /* ??? */
3675 data_size = 56;
3676 *fixed_portion = 56;
3677 break;
3679 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
3680 DBG_DEBUG(" SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n");
3681 SIVAL(pdata,0,mode);
3682 SIVAL(pdata,4,0);
3683 data_size = 8;
3684 *fixed_portion = 8;
3685 break;
3688 * SMB2 UNIX Extensions.
3690 case SMB2_FILE_POSIX_INFORMATION_INTERNAL:
3692 struct smb3_file_posix_information info = {};
3693 uint8_t buf[sizeof(info)];
3694 struct ndr_push ndr = {
3695 .data = buf,
3696 .alloc_size = sizeof(buf),
3697 .fixed_buf_size = true,
3699 enum ndr_err_code ndr_err;
3701 if (!conn_using_smb2(conn->sconn)) {
3702 return NT_STATUS_INVALID_LEVEL;
3704 if (fsp == NULL) {
3705 return NT_STATUS_INVALID_HANDLE;
3707 if (!(fsp->posix_flags & FSP_POSIX_FLAGS_OPEN)) {
3708 return NT_STATUS_INVALID_LEVEL;
3711 smb3_file_posix_information_init(
3712 conn, &smb_fname->st, 0, mode, &info);
3714 ndr_err = ndr_push_smb3_file_posix_information(
3715 &ndr, NDR_SCALARS|NDR_BUFFERS, &info);
3716 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
3717 return NT_STATUS_INSUFFICIENT_RESOURCES;
3720 memcpy(pdata, buf, ndr.offset);
3721 data_size = ndr.offset;
3722 break;
3725 default:
3726 return NT_STATUS_INVALID_LEVEL;
3729 *pdata_size = data_size;
3730 return NT_STATUS_OK;
3733 /****************************************************************************
3734 Set a hard link (called by UNIX extensions and by NT rename with HARD link
3735 code.
3736 ****************************************************************************/
3738 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
3739 connection_struct *conn,
3740 struct smb_request *req,
3741 bool overwrite_if_exists,
3742 const struct smb_filename *smb_fname_old,
3743 struct smb_filename *smb_fname_new)
3745 NTSTATUS status = NT_STATUS_OK;
3746 int ret;
3747 bool ok;
3748 struct smb_filename *parent_fname_old = NULL;
3749 struct smb_filename *base_name_old = NULL;
3750 struct smb_filename *parent_fname_new = NULL;
3751 struct smb_filename *base_name_new = NULL;
3753 /* source must already exist. */
3754 if (!VALID_STAT(smb_fname_old->st)) {
3755 status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
3756 goto out;
3759 /* No links from a directory. */
3760 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
3761 status = NT_STATUS_FILE_IS_A_DIRECTORY;
3762 goto out;
3765 /* Setting a hardlink to/from a stream isn't currently supported. */
3766 ok = is_ntfs_stream_smb_fname(smb_fname_old);
3767 if (ok) {
3768 DBG_DEBUG("Old name has streams\n");
3769 status = NT_STATUS_INVALID_PARAMETER;
3770 goto out;
3772 ok = is_ntfs_stream_smb_fname(smb_fname_new);
3773 if (ok) {
3774 DBG_DEBUG("New name has streams\n");
3775 status = NT_STATUS_INVALID_PARAMETER;
3776 goto out;
3779 if (smb_fname_old->twrp != 0) {
3780 status = NT_STATUS_NOT_SAME_DEVICE;
3781 goto out;
3784 status = parent_pathref(talloc_tos(),
3785 conn->cwd_fsp,
3786 smb_fname_old,
3787 &parent_fname_old,
3788 &base_name_old);
3789 if (!NT_STATUS_IS_OK(status)) {
3790 goto out;
3793 status = parent_pathref(talloc_tos(),
3794 conn->cwd_fsp,
3795 smb_fname_new,
3796 &parent_fname_new,
3797 &base_name_new);
3798 if (!NT_STATUS_IS_OK(status)) {
3799 goto out;
3802 if (VALID_STAT(smb_fname_new->st)) {
3803 if (overwrite_if_exists) {
3804 if (S_ISDIR(smb_fname_new->st.st_ex_mode)) {
3805 status = NT_STATUS_FILE_IS_A_DIRECTORY;
3806 goto out;
3808 status = unlink_internals(conn,
3809 req,
3810 FILE_ATTRIBUTE_NORMAL,
3811 NULL, /* new_dirfsp */
3812 smb_fname_new);
3813 if (!NT_STATUS_IS_OK(status)) {
3814 goto out;
3816 } else {
3817 /* Disallow if newname already exists. */
3818 status = NT_STATUS_OBJECT_NAME_COLLISION;
3819 goto out;
3823 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
3824 smb_fname_old->base_name, smb_fname_new->base_name));
3826 ret = SMB_VFS_LINKAT(conn,
3827 parent_fname_old->fsp,
3828 base_name_old,
3829 parent_fname_new->fsp,
3830 base_name_new,
3833 if (ret != 0) {
3834 status = map_nt_error_from_unix(errno);
3835 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
3836 nt_errstr(status), smb_fname_old->base_name,
3837 smb_fname_new->base_name));
3840 out:
3842 TALLOC_FREE(parent_fname_old);
3843 TALLOC_FREE(parent_fname_new);
3844 return status;
3847 /****************************************************************************
3848 Deal with setting the time from any of the setfilepathinfo functions.
3849 NOTE !!!! The check for FILE_WRITE_ATTRIBUTES access must be done *before*
3850 calling this function.
3851 ****************************************************************************/
3853 NTSTATUS smb_set_file_time(connection_struct *conn,
3854 files_struct *fsp,
3855 struct smb_filename *smb_fname,
3856 struct smb_file_time *ft,
3857 bool setting_write_time)
3859 struct files_struct *set_fsp = NULL;
3860 struct timeval_buf tbuf[4];
3861 uint32_t action =
3862 FILE_NOTIFY_CHANGE_LAST_ACCESS
3863 |FILE_NOTIFY_CHANGE_LAST_WRITE
3864 |FILE_NOTIFY_CHANGE_CREATION;
3865 int ret;
3867 if (!VALID_STAT(smb_fname->st)) {
3868 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3871 if (fsp == NULL) {
3872 /* A symlink */
3873 return NT_STATUS_OK;
3876 set_fsp = metadata_fsp(fsp);
3878 /* get some defaults (no modifications) if any info is zero or -1. */
3879 if (is_omit_timespec(&ft->create_time)) {
3880 action &= ~FILE_NOTIFY_CHANGE_CREATION;
3883 if (is_omit_timespec(&ft->atime)) {
3884 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
3887 if (is_omit_timespec(&ft->mtime)) {
3888 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
3891 if (!setting_write_time) {
3892 /* ft->mtime comes from change time, not write time. */
3893 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
3896 /* Ensure the resolution is the correct for
3897 * what we can store on this filesystem. */
3899 round_timespec(conn->ts_res, &ft->create_time);
3900 round_timespec(conn->ts_res, &ft->ctime);
3901 round_timespec(conn->ts_res, &ft->atime);
3902 round_timespec(conn->ts_res, &ft->mtime);
3904 DBG_DEBUG("smb_set_filetime: actime: %s\n ",
3905 timespec_string_buf(&ft->atime, true, &tbuf[0]));
3906 DBG_DEBUG("smb_set_filetime: modtime: %s\n ",
3907 timespec_string_buf(&ft->mtime, true, &tbuf[1]));
3908 DBG_DEBUG("smb_set_filetime: ctime: %s\n ",
3909 timespec_string_buf(&ft->ctime, true, &tbuf[2]));
3910 DBG_DEBUG("smb_set_file_time: createtime: %s\n ",
3911 timespec_string_buf(&ft->create_time, true, &tbuf[3]));
3913 if (setting_write_time) {
3915 * This was a Windows setfileinfo on an open file.
3916 * NT does this a lot. We also need to
3917 * set the time here, as it can be read by
3918 * FindFirst/FindNext and with the patch for bug #2045
3919 * in smbd/fileio.c it ensures that this timestamp is
3920 * kept sticky even after a write. We save the request
3921 * away and will set it on file close and after a write. JRA.
3924 DBG_DEBUG("setting pending modtime to %s\n",
3925 timespec_string_buf(&ft->mtime, true, &tbuf[0]));
3927 if (set_fsp != NULL) {
3928 set_sticky_write_time_fsp(set_fsp, ft->mtime);
3929 } else {
3930 set_sticky_write_time_path(
3931 vfs_file_id_from_sbuf(conn, &smb_fname->st),
3932 ft->mtime);
3936 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
3938 ret = file_ntimes(conn, set_fsp, ft);
3939 if (ret != 0) {
3940 return map_nt_error_from_unix(errno);
3943 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
3944 smb_fname->base_name);
3945 return NT_STATUS_OK;
3948 /****************************************************************************
3949 Deal with setting the dosmode from any of the setfilepathinfo functions.
3950 NB. The check for FILE_WRITE_ATTRIBUTES access on this path must have been
3951 done before calling this function.
3952 ****************************************************************************/
3954 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
3955 struct files_struct *fsp,
3956 uint32_t dosmode)
3958 struct files_struct *dos_fsp = NULL;
3959 uint32_t current_dosmode;
3960 int ret;
3962 if (!VALID_STAT(fsp->fsp_name->st)) {
3963 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3966 dos_fsp = metadata_fsp(fsp);
3968 if (dosmode != 0) {
3969 if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
3970 dosmode |= FILE_ATTRIBUTE_DIRECTORY;
3971 } else {
3972 dosmode &= ~FILE_ATTRIBUTE_DIRECTORY;
3976 DBG_DEBUG("dosmode: 0x%" PRIx32 "\n", dosmode);
3978 /* check the mode isn't different, before changing it */
3979 if (dosmode == 0) {
3980 return NT_STATUS_OK;
3982 current_dosmode = fdos_mode(dos_fsp);
3983 if (dosmode == current_dosmode) {
3984 return NT_STATUS_OK;
3987 DBG_DEBUG("file %s : setting dos mode 0x%" PRIx32 "\n",
3988 fsp_str_dbg(dos_fsp), dosmode);
3990 ret = file_set_dosmode(conn, dos_fsp->fsp_name, dosmode, NULL, false);
3991 if (ret != 0) {
3992 DBG_WARNING("file_set_dosmode of %s failed: %s\n",
3993 fsp_str_dbg(dos_fsp), strerror(errno));
3994 return map_nt_error_from_unix(errno);
3997 return NT_STATUS_OK;
4000 /****************************************************************************
4001 Deal with setting the size from any of the setfilepathinfo functions.
4002 ****************************************************************************/
4004 NTSTATUS smb_set_file_size(connection_struct *conn,
4005 struct smb_request *req,
4006 files_struct *fsp,
4007 struct smb_filename *smb_fname,
4008 const SMB_STRUCT_STAT *psbuf,
4009 off_t size,
4010 bool fail_after_createfile)
4012 NTSTATUS status = NT_STATUS_OK;
4013 files_struct *new_fsp = NULL;
4015 if (!VALID_STAT(*psbuf)) {
4016 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4019 DBG_INFO("size: %"PRIu64", file_size_stat=%"PRIu64"\n",
4020 (uint64_t)size,
4021 get_file_size_stat(psbuf));
4023 if (size == get_file_size_stat(psbuf)) {
4024 if (fsp == NULL) {
4025 return NT_STATUS_OK;
4027 if (!fsp->fsp_flags.modified) {
4028 return NT_STATUS_OK;
4030 trigger_write_time_update_immediate(fsp);
4031 return NT_STATUS_OK;
4034 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
4035 smb_fname_str_dbg(smb_fname), (double)size));
4037 if (fsp &&
4038 !fsp->fsp_flags.is_pathref &&
4039 fsp_get_io_fd(fsp) != -1)
4041 /* Handle based call. */
4042 status = check_any_access_fsp(fsp, FILE_WRITE_DATA);
4043 if (!NT_STATUS_IS_OK(status)) {
4044 return status;
4047 if (vfs_set_filelen(fsp, size) == -1) {
4048 return map_nt_error_from_unix(errno);
4050 trigger_write_time_update_immediate(fsp);
4051 return NT_STATUS_OK;
4054 status = SMB_VFS_CREATE_FILE(
4055 conn, /* conn */
4056 req, /* req */
4057 NULL, /* dirfsp */
4058 smb_fname, /* fname */
4059 FILE_WRITE_DATA, /* access_mask */
4060 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
4061 FILE_SHARE_DELETE),
4062 FILE_OPEN, /* create_disposition*/
4063 0, /* create_options */
4064 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
4065 0, /* oplock_request */
4066 NULL, /* lease */
4067 0, /* allocation_size */
4068 0, /* private_flags */
4069 NULL, /* sd */
4070 NULL, /* ea_list */
4071 &new_fsp, /* result */
4072 NULL, /* pinfo */
4073 NULL, NULL); /* create context */
4075 if (!NT_STATUS_IS_OK(status)) {
4076 /* NB. We check for open_was_deferred in the caller. */
4077 return status;
4080 /* See RAW-SFILEINFO-END-OF-FILE */
4081 if (fail_after_createfile) {
4082 close_file_free(req, &new_fsp, NORMAL_CLOSE);
4083 return NT_STATUS_INVALID_LEVEL;
4086 if (vfs_set_filelen(new_fsp, size) == -1) {
4087 status = map_nt_error_from_unix(errno);
4088 close_file_free(req, &new_fsp, NORMAL_CLOSE);
4089 return status;
4092 trigger_write_time_update_immediate(new_fsp);
4093 close_file_free(req, &new_fsp, NORMAL_CLOSE);
4094 return NT_STATUS_OK;
4097 /****************************************************************************
4098 Deal with SMB_INFO_SET_EA.
4099 ****************************************************************************/
4101 static NTSTATUS smb_info_set_ea(connection_struct *conn,
4102 const char *pdata,
4103 int total_data,
4104 files_struct *fsp,
4105 struct smb_filename *smb_fname)
4107 struct ea_list *ea_list = NULL;
4108 TALLOC_CTX *ctx = NULL;
4109 NTSTATUS status = NT_STATUS_OK;
4111 if (total_data < 10) {
4113 /* OS/2 workplace shell seems to send SET_EA requests of "null"
4114 length. They seem to have no effect. Bug #3212. JRA */
4116 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
4117 /* We're done. We only get EA info in this call. */
4118 return NT_STATUS_OK;
4121 return NT_STATUS_INVALID_PARAMETER;
4124 if (IVAL(pdata,0) > total_data) {
4125 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
4126 IVAL(pdata,0), (unsigned int)total_data));
4127 return NT_STATUS_INVALID_PARAMETER;
4130 ctx = talloc_tos();
4131 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
4132 if (!ea_list) {
4133 return NT_STATUS_INVALID_PARAMETER;
4136 if (fsp == NULL) {
4138 * The only way fsp can be NULL here is if
4139 * smb_fname points at a symlink and
4140 * and we're in POSIX context.
4141 * Ensure this is the case.
4143 * In this case we cannot set the EA.
4145 SMB_ASSERT(smb_fname->flags & SMB_FILENAME_POSIX_PATH);
4146 return NT_STATUS_ACCESS_DENIED;
4149 status = set_ea(conn, fsp, ea_list);
4151 return status;
4154 /****************************************************************************
4155 Deal with SMB_FILE_FULL_EA_INFORMATION set.
4156 ****************************************************************************/
4158 static NTSTATUS smb_set_file_full_ea_info(connection_struct *conn,
4159 const char *pdata,
4160 int total_data,
4161 files_struct *fsp)
4163 struct ea_list *ea_list = NULL;
4164 NTSTATUS status;
4166 if (fsp == NULL) {
4167 return NT_STATUS_INVALID_HANDLE;
4170 if (!lp_ea_support(SNUM(conn))) {
4171 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
4172 "EA's not supported.\n",
4173 (unsigned int)total_data));
4174 return NT_STATUS_EAS_NOT_SUPPORTED;
4177 if (total_data < 10) {
4178 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
4179 "too small.\n",
4180 (unsigned int)total_data));
4181 return NT_STATUS_INVALID_PARAMETER;
4184 ea_list = read_nttrans_ea_list(talloc_tos(),
4185 pdata,
4186 total_data);
4188 if (!ea_list) {
4189 return NT_STATUS_INVALID_PARAMETER;
4192 status = set_ea(conn, fsp, ea_list);
4194 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
4195 smb_fname_str_dbg(fsp->fsp_name),
4196 nt_errstr(status) ));
4198 return status;
4202 /****************************************************************************
4203 Deal with SMB_SET_FILE_DISPOSITION_INFO.
4204 ****************************************************************************/
4206 NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
4207 const char *pdata,
4208 int total_data,
4209 files_struct *fsp,
4210 struct smb_filename *smb_fname)
4212 NTSTATUS status = NT_STATUS_OK;
4213 bool delete_on_close;
4214 uint32_t dosmode = 0;
4216 if (total_data < 1) {
4217 return NT_STATUS_INVALID_PARAMETER;
4220 if (fsp == NULL) {
4221 return NT_STATUS_INVALID_HANDLE;
4224 delete_on_close = (CVAL(pdata,0) ? True : False);
4225 dosmode = fdos_mode(fsp);
4227 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
4228 "delete_on_close = %u\n",
4229 smb_fname_str_dbg(smb_fname),
4230 (unsigned int)dosmode,
4231 (unsigned int)delete_on_close ));
4233 if (delete_on_close) {
4234 status = can_set_delete_on_close(fsp, dosmode);
4235 if (!NT_STATUS_IS_OK(status)) {
4236 return status;
4240 /* The set is across all open files on this dev/inode pair. */
4241 if (!set_delete_on_close(fsp, delete_on_close,
4242 conn->session_info->security_token,
4243 conn->session_info->unix_token)) {
4244 return NT_STATUS_ACCESS_DENIED;
4246 return NT_STATUS_OK;
4249 /****************************************************************************
4250 Deal with SMB_FILE_POSITION_INFORMATION.
4251 ****************************************************************************/
4253 static NTSTATUS smb_file_position_information(connection_struct *conn,
4254 const char *pdata,
4255 int total_data,
4256 files_struct *fsp)
4258 uint64_t position_information;
4260 if (total_data < 8) {
4261 return NT_STATUS_INVALID_PARAMETER;
4264 if (fsp == NULL) {
4265 /* Ignore on pathname based set. */
4266 return NT_STATUS_OK;
4269 position_information = (uint64_t)IVAL(pdata,0);
4270 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
4272 DEBUG(10,("smb_file_position_information: Set file position "
4273 "information for file %s to %.0f\n", fsp_str_dbg(fsp),
4274 (double)position_information));
4275 fh_set_position_information(fsp->fh, position_information);
4276 return NT_STATUS_OK;
4279 /****************************************************************************
4280 Deal with SMB_FILE_MODE_INFORMATION.
4281 ****************************************************************************/
4283 static NTSTATUS smb_file_mode_information(connection_struct *conn,
4284 const char *pdata,
4285 int total_data)
4287 uint32_t mode;
4289 if (total_data < 4) {
4290 return NT_STATUS_INVALID_PARAMETER;
4292 mode = IVAL(pdata,0);
4293 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
4294 return NT_STATUS_INVALID_PARAMETER;
4296 return NT_STATUS_OK;
4299 /****************************************************************************
4300 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
4301 ****************************************************************************/
4303 static NTSTATUS smb2_file_rename_information(connection_struct *conn,
4304 struct smb_request *req,
4305 const char *pdata,
4306 int total_data,
4307 files_struct *fsp,
4308 struct smb_filename *smb_fname_src)
4310 bool overwrite;
4311 uint32_t len;
4312 char *newname = NULL;
4313 struct files_struct *dst_dirfsp = NULL;
4314 struct smb_filename *smb_fname_dst = NULL;
4315 const char *dst_original_lcomp = NULL;
4316 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
4317 NTSTATUS status = NT_STATUS_OK;
4318 TALLOC_CTX *ctx = talloc_tos();
4320 if (!fsp) {
4321 return NT_STATUS_INVALID_HANDLE;
4324 if (total_data < 20) {
4325 return NT_STATUS_INVALID_PARAMETER;
4328 overwrite = (CVAL(pdata,0) ? True : False);
4329 len = IVAL(pdata,16);
4331 if (len > (total_data - 20) || (len == 0)) {
4332 return NT_STATUS_INVALID_PARAMETER;
4335 (void)srvstr_pull_talloc(ctx,
4336 pdata,
4337 req->flags2,
4338 &newname,
4339 &pdata[20],
4340 len,
4341 STR_TERMINATE);
4343 if (newname == NULL) {
4344 return NT_STATUS_INVALID_PARAMETER;
4347 /* SMB2 rename paths are never DFS. */
4348 req->flags2 &= ~FLAGS2_DFS_PATHNAMES;
4349 ucf_flags &= ~UCF_DFS_PATHNAME;
4351 status = check_path_syntax(newname,
4352 fsp->fsp_name->flags & SMB_FILENAME_POSIX_PATH);
4353 if (!NT_STATUS_IS_OK(status)) {
4354 return status;
4357 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
4358 newname));
4360 if (newname[0] == ':') {
4361 /* Create an smb_fname to call rename_internals_fsp() with. */
4362 smb_fname_dst = synthetic_smb_fname(talloc_tos(),
4363 fsp->base_fsp->fsp_name->base_name,
4364 newname,
4365 NULL,
4366 fsp->base_fsp->fsp_name->twrp,
4367 fsp->base_fsp->fsp_name->flags);
4368 if (smb_fname_dst == NULL) {
4369 status = NT_STATUS_NO_MEMORY;
4370 goto out;
4372 } else {
4373 status = filename_convert_dirfsp(ctx,
4374 conn,
4375 newname,
4376 ucf_flags,
4377 0, /* Never a TWRP. */
4378 &dst_dirfsp,
4379 &smb_fname_dst);
4380 if (!NT_STATUS_IS_OK(status)) {
4381 goto out;
4386 * Set the original last component, since
4387 * rename_internals_fsp() requires it.
4389 dst_original_lcomp = get_original_lcomp(smb_fname_dst,
4390 conn,
4391 newname,
4392 ucf_flags);
4393 if (dst_original_lcomp == NULL) {
4394 status = NT_STATUS_NO_MEMORY;
4395 goto out;
4398 DEBUG(10,("smb2_file_rename_information: "
4399 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
4400 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
4401 smb_fname_str_dbg(smb_fname_dst)));
4402 status = rename_internals_fsp(conn,
4403 fsp,
4404 smb_fname_dst,
4405 dst_original_lcomp,
4406 (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM),
4407 overwrite);
4409 out:
4410 TALLOC_FREE(smb_fname_dst);
4411 return status;
4414 static NTSTATUS smb2_file_link_information(connection_struct *conn,
4415 struct smb_request *req,
4416 const char *pdata,
4417 int total_data,
4418 files_struct *fsp,
4419 struct smb_filename *smb_fname_src)
4421 bool overwrite;
4422 uint32_t len;
4423 char *newname = NULL;
4424 struct files_struct *dst_dirfsp = NULL;
4425 struct smb_filename *smb_fname_dst = NULL;
4426 NTSTATUS status = NT_STATUS_OK;
4427 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
4428 size_t ret;
4429 TALLOC_CTX *ctx = talloc_tos();
4431 if (!fsp) {
4432 return NT_STATUS_INVALID_HANDLE;
4435 if (total_data < 20) {
4436 return NT_STATUS_INVALID_PARAMETER;
4439 overwrite = (CVAL(pdata,0) ? true : false);
4440 len = IVAL(pdata,16);
4442 if (len > (total_data - 20) || (len == 0)) {
4443 return NT_STATUS_INVALID_PARAMETER;
4446 ret = srvstr_pull_talloc(ctx,
4447 pdata,
4448 req->flags2,
4449 &newname,
4450 &pdata[20],
4451 len,
4452 STR_TERMINATE);
4454 if (ret == (size_t)-1 || newname == NULL) {
4455 return NT_STATUS_INVALID_PARAMETER;
4458 /* SMB2 hardlink paths are never DFS. */
4459 req->flags2 &= ~FLAGS2_DFS_PATHNAMES;
4460 ucf_flags &= ~UCF_DFS_PATHNAME;
4462 status = check_path_syntax(newname,
4463 fsp->fsp_name->flags & SMB_FILENAME_POSIX_PATH);
4464 if (!NT_STATUS_IS_OK(status)) {
4465 return status;
4468 DBG_DEBUG("got name |%s|\n", newname);
4470 status = filename_convert_dirfsp(ctx,
4471 conn,
4472 newname,
4473 ucf_flags,
4474 0, /* No TWRP. */
4475 &dst_dirfsp,
4476 &smb_fname_dst);
4477 if (!NT_STATUS_IS_OK(status)) {
4478 return status;
4481 if (fsp->base_fsp) {
4482 /* No stream names. */
4483 return NT_STATUS_NOT_SUPPORTED;
4486 DBG_DEBUG("SMB_FILE_LINK_INFORMATION (%s) %s -> %s\n",
4487 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
4488 smb_fname_str_dbg(smb_fname_dst));
4489 status = hardlink_internals(ctx,
4490 conn,
4491 req,
4492 overwrite,
4493 fsp->fsp_name,
4494 smb_fname_dst);
4496 TALLOC_FREE(smb_fname_dst);
4497 return status;
4500 static NTSTATUS smb_file_link_information(connection_struct *conn,
4501 struct smb_request *req,
4502 const char *pdata,
4503 int total_data,
4504 files_struct *fsp,
4505 struct smb_filename *smb_fname_src)
4507 bool overwrite;
4508 uint32_t len;
4509 char *newname = NULL;
4510 struct files_struct *dst_dirfsp = NULL;
4511 struct smb_filename *smb_fname_dst = NULL;
4512 NTSTATUS status = NT_STATUS_OK;
4513 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
4514 NTTIME dst_twrp = 0;
4515 TALLOC_CTX *ctx = talloc_tos();
4517 if (!fsp) {
4518 return NT_STATUS_INVALID_HANDLE;
4521 if (total_data < 20) {
4522 return NT_STATUS_INVALID_PARAMETER;
4525 overwrite = (CVAL(pdata,0) ? true : false);
4526 len = IVAL(pdata,16);
4528 if (len > (total_data - 20) || (len == 0)) {
4529 return NT_STATUS_INVALID_PARAMETER;
4532 if (smb_fname_src->flags & SMB_FILENAME_POSIX_PATH) {
4533 srvstr_get_path_posix(ctx,
4534 pdata,
4535 req->flags2,
4536 &newname,
4537 &pdata[20],
4538 len,
4539 STR_TERMINATE,
4540 &status);
4541 ucf_flags |= UCF_POSIX_PATHNAMES;
4542 } else {
4543 srvstr_get_path(ctx,
4544 pdata,
4545 req->flags2,
4546 &newname,
4547 &pdata[20],
4548 len,
4549 STR_TERMINATE,
4550 &status);
4552 if (!NT_STATUS_IS_OK(status)) {
4553 return status;
4556 DEBUG(10,("smb_file_link_information: got name |%s|\n",
4557 newname));
4559 if (ucf_flags & UCF_GMT_PATHNAME) {
4560 extract_snapshot_token(newname, &dst_twrp);
4562 /* hardlink paths are never DFS. */
4563 ucf_flags &= ~UCF_DFS_PATHNAME;
4565 status = filename_convert_dirfsp(ctx,
4566 conn,
4567 newname,
4568 ucf_flags,
4569 dst_twrp,
4570 &dst_dirfsp,
4571 &smb_fname_dst);
4572 if (!NT_STATUS_IS_OK(status)) {
4573 return status;
4576 if (fsp->base_fsp) {
4577 /* No stream names. */
4578 return NT_STATUS_NOT_SUPPORTED;
4581 DEBUG(10,("smb_file_link_information: "
4582 "SMB_FILE_LINK_INFORMATION (%s) %s -> %s\n",
4583 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
4584 smb_fname_str_dbg(smb_fname_dst)));
4585 status = hardlink_internals(ctx,
4586 conn,
4587 req,
4588 overwrite,
4589 fsp->fsp_name,
4590 smb_fname_dst);
4592 TALLOC_FREE(smb_fname_dst);
4593 return status;
4597 /****************************************************************************
4598 Deal with SMB_FILE_RENAME_INFORMATION.
4599 ****************************************************************************/
4601 static NTSTATUS smb_file_rename_information(connection_struct *conn,
4602 struct smb_request *req,
4603 const char *pdata,
4604 int total_data,
4605 files_struct *fsp,
4606 struct smb_filename *smb_fname_src)
4608 bool overwrite;
4609 uint32_t root_fid;
4610 uint32_t len;
4611 char *newname = NULL;
4612 struct files_struct *dst_dirfsp = NULL;
4613 struct smb_filename *smb_fname_dst = NULL;
4614 const char *dst_original_lcomp = NULL;
4615 NTSTATUS status = NT_STATUS_OK;
4616 char *p;
4617 TALLOC_CTX *ctx = talloc_tos();
4619 if (total_data < 13) {
4620 return NT_STATUS_INVALID_PARAMETER;
4623 overwrite = (CVAL(pdata,0) != 0);
4624 root_fid = IVAL(pdata,4);
4625 len = IVAL(pdata,8);
4627 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
4628 return NT_STATUS_INVALID_PARAMETER;
4631 if (req->posix_pathnames) {
4632 srvstr_get_path_posix(ctx,
4633 pdata,
4634 req->flags2,
4635 &newname,
4636 &pdata[12],
4637 len,
4639 &status);
4640 } else {
4641 srvstr_get_path(ctx,
4642 pdata,
4643 req->flags2,
4644 &newname,
4645 &pdata[12],
4646 len,
4648 &status);
4650 if (!NT_STATUS_IS_OK(status)) {
4651 return status;
4654 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
4655 newname));
4657 /* Check the new name has no '/' characters. */
4658 if (strchr_m(newname, '/')) {
4659 return NT_STATUS_NOT_SUPPORTED;
4662 if (fsp && fsp->base_fsp) {
4663 /* newname must be a stream name. */
4664 if (newname[0] != ':') {
4665 return NT_STATUS_NOT_SUPPORTED;
4668 /* Create an smb_fname to call rename_internals_fsp() with. */
4669 smb_fname_dst = synthetic_smb_fname(talloc_tos(),
4670 fsp->base_fsp->fsp_name->base_name,
4671 newname,
4672 NULL,
4673 fsp->base_fsp->fsp_name->twrp,
4674 fsp->base_fsp->fsp_name->flags);
4675 if (smb_fname_dst == NULL) {
4676 status = NT_STATUS_NO_MEMORY;
4677 goto out;
4681 * Get the original last component, since
4682 * rename_internals_fsp() requires it.
4684 dst_original_lcomp = get_original_lcomp(smb_fname_dst,
4685 conn,
4686 newname,
4688 if (dst_original_lcomp == NULL) {
4689 status = NT_STATUS_NO_MEMORY;
4690 goto out;
4693 } else {
4695 * Build up an smb_fname_dst based on the filename passed in.
4696 * We basically just strip off the last component, and put on
4697 * the newname instead.
4699 char *base_name = NULL;
4700 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
4701 NTTIME dst_twrp = 0;
4703 /* newname must *not* be a stream name. */
4704 if (newname[0] == ':') {
4705 return NT_STATUS_NOT_SUPPORTED;
4709 * Strip off the last component (filename) of the path passed
4710 * in.
4712 base_name = talloc_strdup(ctx, smb_fname_src->base_name);
4713 if (!base_name) {
4714 return NT_STATUS_NO_MEMORY;
4716 p = strrchr_m(base_name, '/');
4717 if (p) {
4718 p[1] = '\0';
4719 } else {
4720 base_name = talloc_strdup(ctx, "");
4721 if (!base_name) {
4722 return NT_STATUS_NO_MEMORY;
4725 /* Append the new name. */
4726 base_name = talloc_asprintf_append(base_name,
4727 "%s",
4728 newname);
4729 if (!base_name) {
4730 return NT_STATUS_NO_MEMORY;
4733 if (ucf_flags & UCF_GMT_PATHNAME) {
4734 extract_snapshot_token(base_name, &dst_twrp);
4737 /* The newname is *not* a DFS path. */
4738 ucf_flags &= ~UCF_DFS_PATHNAME;
4740 status = filename_convert_dirfsp(ctx,
4741 conn,
4742 base_name,
4743 ucf_flags,
4744 dst_twrp,
4745 &dst_dirfsp,
4746 &smb_fname_dst);
4748 if (!NT_STATUS_IS_OK(status)) {
4749 goto out;
4751 dst_original_lcomp = get_original_lcomp(smb_fname_dst,
4752 conn,
4753 newname,
4754 ucf_flags);
4755 if (dst_original_lcomp == NULL) {
4756 status = NT_STATUS_NO_MEMORY;
4757 goto out;
4761 if (fsp != NULL && fsp->fsp_flags.is_fsa) {
4762 DEBUG(10,("smb_file_rename_information: "
4763 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
4764 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
4765 smb_fname_str_dbg(smb_fname_dst)));
4766 status = rename_internals_fsp(conn,
4767 fsp,
4768 smb_fname_dst,
4769 dst_original_lcomp,
4771 overwrite);
4772 } else {
4773 DEBUG(10,("smb_file_rename_information: "
4774 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
4775 smb_fname_str_dbg(smb_fname_src),
4776 smb_fname_str_dbg(smb_fname_dst)));
4777 status = rename_internals(ctx,
4778 conn,
4779 req,
4780 NULL, /* src_dirfsp */
4781 smb_fname_src,
4782 smb_fname_dst,
4783 dst_original_lcomp,
4785 overwrite,
4786 FILE_WRITE_ATTRIBUTES);
4788 out:
4789 TALLOC_FREE(smb_fname_dst);
4790 return status;
4793 /****************************************************************************
4794 Deal with SMB_SET_FILE_BASIC_INFO.
4795 ****************************************************************************/
4797 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
4798 const char *pdata,
4799 int total_data,
4800 files_struct *fsp,
4801 struct smb_filename *smb_fname)
4803 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
4804 struct smb_file_time ft;
4805 uint32_t dosmode = 0;
4806 NTSTATUS status = NT_STATUS_OK;
4808 init_smb_file_time(&ft);
4810 if (total_data < 36) {
4811 return NT_STATUS_INVALID_PARAMETER;
4814 if (fsp == NULL) {
4815 return NT_STATUS_INVALID_HANDLE;
4818 status = check_any_access_fsp(fsp, FILE_WRITE_ATTRIBUTES);
4819 if (!NT_STATUS_IS_OK(status)) {
4820 return status;
4823 /* Set the attributes */
4824 dosmode = IVAL(pdata,32);
4825 status = smb_set_file_dosmode(conn, fsp, dosmode);
4826 if (!NT_STATUS_IS_OK(status)) {
4827 return status;
4830 /* create time */
4831 ft.create_time = pull_long_date_full_timespec(pdata);
4833 /* access time */
4834 ft.atime = pull_long_date_full_timespec(pdata+8);
4836 /* write time. */
4837 ft.mtime = pull_long_date_full_timespec(pdata+16);
4839 /* change time. */
4840 ft.ctime = pull_long_date_full_timespec(pdata+24);
4842 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
4843 smb_fname_str_dbg(smb_fname)));
4845 status = smb_set_file_time(conn, fsp, smb_fname, &ft, true);
4846 if (!NT_STATUS_IS_OK(status)) {
4847 return status;
4850 if (fsp->fsp_flags.modified) {
4851 trigger_write_time_update_immediate(fsp);
4853 return NT_STATUS_OK;
4856 /****************************************************************************
4857 Deal with SMB_INFO_STANDARD.
4858 ****************************************************************************/
4860 static NTSTATUS smb_set_info_standard(connection_struct *conn,
4861 const char *pdata,
4862 int total_data,
4863 files_struct *fsp,
4864 struct smb_filename *smb_fname)
4866 NTSTATUS status;
4867 struct smb_file_time ft;
4869 init_smb_file_time(&ft);
4871 if (total_data < 12) {
4872 return NT_STATUS_INVALID_PARAMETER;
4875 if (fsp == NULL) {
4876 return NT_STATUS_INVALID_HANDLE;
4879 /* create time */
4880 ft.create_time = time_t_to_full_timespec(srv_make_unix_date2(pdata));
4881 /* access time */
4882 ft.atime = time_t_to_full_timespec(srv_make_unix_date2(pdata+4));
4883 /* write time */
4884 ft.mtime = time_t_to_full_timespec(srv_make_unix_date2(pdata+8));
4886 DEBUG(10,("smb_set_info_standard: file %s\n",
4887 smb_fname_str_dbg(smb_fname)));
4889 status = check_any_access_fsp(fsp, FILE_WRITE_ATTRIBUTES);
4890 if (!NT_STATUS_IS_OK(status)) {
4891 return status;
4894 status = smb_set_file_time(conn, fsp, smb_fname, &ft, true);
4895 if (!NT_STATUS_IS_OK(status)) {
4896 return status;
4899 if (fsp->fsp_flags.modified) {
4900 trigger_write_time_update_immediate(fsp);
4902 return NT_STATUS_OK;
4905 /****************************************************************************
4906 Deal with SMB_SET_FILE_ALLOCATION_INFO.
4907 ****************************************************************************/
4909 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
4910 struct smb_request *req,
4911 const char *pdata,
4912 int total_data,
4913 files_struct *fsp,
4914 struct smb_filename *smb_fname)
4916 uint64_t allocation_size = 0;
4917 NTSTATUS status = NT_STATUS_OK;
4918 files_struct *new_fsp = NULL;
4920 if (!VALID_STAT(smb_fname->st)) {
4921 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4924 if (total_data < 8) {
4925 return NT_STATUS_INVALID_PARAMETER;
4928 allocation_size = (uint64_t)IVAL(pdata,0);
4929 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
4930 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
4931 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
4932 (double)allocation_size));
4934 if (allocation_size) {
4935 allocation_size = smb_roundup(conn, allocation_size);
4938 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
4939 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
4940 (double)allocation_size));
4942 if (fsp &&
4943 !fsp->fsp_flags.is_pathref &&
4944 fsp_get_io_fd(fsp) != -1)
4946 /* Open file handle. */
4947 status = check_any_access_fsp(fsp, FILE_WRITE_DATA);
4948 if (!NT_STATUS_IS_OK(status)) {
4949 return status;
4952 /* Only change if needed. */
4953 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
4954 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
4955 return map_nt_error_from_unix(errno);
4958 /* But always update the time. */
4960 * This is equivalent to a write. Ensure it's seen immediately
4961 * if there are no pending writes.
4963 trigger_write_time_update_immediate(fsp);
4964 return NT_STATUS_OK;
4967 /* Pathname or stat or directory file. */
4968 status = SMB_VFS_CREATE_FILE(
4969 conn, /* conn */
4970 req, /* req */
4971 NULL, /* dirfsp */
4972 smb_fname, /* fname */
4973 FILE_WRITE_DATA, /* access_mask */
4974 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
4975 FILE_SHARE_DELETE),
4976 FILE_OPEN, /* create_disposition*/
4977 0, /* create_options */
4978 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
4979 0, /* oplock_request */
4980 NULL, /* lease */
4981 0, /* allocation_size */
4982 0, /* private_flags */
4983 NULL, /* sd */
4984 NULL, /* ea_list */
4985 &new_fsp, /* result */
4986 NULL, /* pinfo */
4987 NULL, NULL); /* create context */
4989 if (!NT_STATUS_IS_OK(status)) {
4990 /* NB. We check for open_was_deferred in the caller. */
4991 return status;
4994 /* Only change if needed. */
4995 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
4996 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
4997 status = map_nt_error_from_unix(errno);
4998 close_file_free(req, &new_fsp, NORMAL_CLOSE);
4999 return status;
5003 /* Changing the allocation size should set the last mod time. */
5005 * This is equivalent to a write. Ensure it's seen immediately
5006 * if there are no pending writes.
5008 trigger_write_time_update_immediate(new_fsp);
5009 close_file_free(req, &new_fsp, NORMAL_CLOSE);
5010 return NT_STATUS_OK;
5013 /****************************************************************************
5014 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
5015 ****************************************************************************/
5017 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
5018 struct smb_request *req,
5019 const char *pdata,
5020 int total_data,
5021 files_struct *fsp,
5022 struct smb_filename *smb_fname,
5023 bool fail_after_createfile)
5025 off_t size;
5027 if (total_data < 8) {
5028 return NT_STATUS_INVALID_PARAMETER;
5031 size = IVAL(pdata,0);
5032 size |= (((off_t)IVAL(pdata,4)) << 32);
5033 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
5034 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
5035 (double)size));
5037 return smb_set_file_size(conn, req,
5038 fsp,
5039 smb_fname,
5040 &smb_fname->st,
5041 size,
5042 fail_after_createfile);
5045 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
5046 struct smb_request *req,
5047 TALLOC_CTX *mem_ctx,
5048 uint16_t info_level,
5049 files_struct *fsp,
5050 struct smb_filename *smb_fname,
5051 char **ppdata, int total_data,
5052 int *ret_data_size)
5054 char *pdata = *ppdata;
5055 NTSTATUS status = NT_STATUS_OK;
5056 int data_return_size = 0;
5058 *ret_data_size = 0;
5060 DEBUG(3,("smbd_do_setfilepathinfo: %s (%s) info_level=%d "
5061 "totdata=%d\n", smb_fname_str_dbg(smb_fname),
5062 fsp_fnum_dbg(fsp),
5063 info_level, total_data));
5065 switch (info_level) {
5067 case SMB_INFO_STANDARD:
5069 status = smb_set_info_standard(conn,
5070 pdata,
5071 total_data,
5072 fsp,
5073 smb_fname);
5074 break;
5077 case SMB_INFO_SET_EA:
5079 status = smb_info_set_ea(conn,
5080 pdata,
5081 total_data,
5082 fsp,
5083 smb_fname);
5084 break;
5087 case SMB_SET_FILE_BASIC_INFO:
5088 case SMB_FILE_BASIC_INFORMATION:
5090 status = smb_set_file_basic_info(conn,
5091 pdata,
5092 total_data,
5093 fsp,
5094 smb_fname);
5095 break;
5098 case SMB_FILE_ALLOCATION_INFORMATION:
5099 case SMB_SET_FILE_ALLOCATION_INFO:
5101 status = smb_set_file_allocation_info(conn, req,
5102 pdata,
5103 total_data,
5104 fsp,
5105 smb_fname);
5106 break;
5109 case SMB_FILE_END_OF_FILE_INFORMATION:
5110 case SMB_SET_FILE_END_OF_FILE_INFO:
5113 * XP/Win7 both fail after the createfile with
5114 * SMB_SET_FILE_END_OF_FILE_INFO but not
5115 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
5116 * The level is known here, so pass it down
5117 * appropriately.
5119 bool should_fail =
5120 (info_level == SMB_SET_FILE_END_OF_FILE_INFO);
5122 status = smb_set_file_end_of_file_info(conn, req,
5123 pdata,
5124 total_data,
5125 fsp,
5126 smb_fname,
5127 should_fail);
5128 break;
5131 case SMB_FILE_DISPOSITION_INFORMATION:
5132 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
5134 #if 0
5135 /* JRA - We used to just ignore this on a path ?
5136 * Shouldn't this be invalid level on a pathname
5137 * based call ?
5139 if (tran_call != TRANSACT2_SETFILEINFO) {
5140 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5142 #endif
5143 status = smb_set_file_disposition_info(conn,
5144 pdata,
5145 total_data,
5146 fsp,
5147 smb_fname);
5148 break;
5151 case SMB_FILE_POSITION_INFORMATION:
5153 status = smb_file_position_information(conn,
5154 pdata,
5155 total_data,
5156 fsp);
5157 break;
5160 case SMB_FILE_FULL_EA_INFORMATION:
5162 status = smb_set_file_full_ea_info(conn,
5163 pdata,
5164 total_data,
5165 fsp);
5166 break;
5169 /* From tridge Samba4 :
5170 * MODE_INFORMATION in setfileinfo (I have no
5171 * idea what "mode information" on a file is - it takes a value of 0,
5172 * 2, 4 or 6. What could it be?).
5175 case SMB_FILE_MODE_INFORMATION:
5177 status = smb_file_mode_information(conn,
5178 pdata,
5179 total_data);
5180 break;
5183 /* [MS-SMB2] 3.3.5.21.1 states we MUST fail with STATUS_NOT_SUPPORTED. */
5184 case SMB_FILE_VALID_DATA_LENGTH_INFORMATION:
5185 case SMB_FILE_SHORT_NAME_INFORMATION:
5186 return NT_STATUS_NOT_SUPPORTED;
5188 case SMB_FILE_RENAME_INFORMATION:
5190 status = smb_file_rename_information(conn, req,
5191 pdata, total_data,
5192 fsp, smb_fname);
5193 break;
5196 case SMB2_FILE_RENAME_INFORMATION_INTERNAL:
5198 /* SMB2 rename information. */
5199 status = smb2_file_rename_information(conn, req,
5200 pdata, total_data,
5201 fsp, smb_fname);
5202 break;
5205 case SMB_FILE_LINK_INFORMATION:
5207 if (conn_using_smb2(conn->sconn)) {
5208 status = smb2_file_link_information(conn,
5209 req,
5210 pdata,
5211 total_data,
5212 fsp,
5213 smb_fname);
5214 } else {
5215 status = smb_file_link_information(conn,
5216 req,
5217 pdata,
5218 total_data,
5219 fsp,
5220 smb_fname);
5222 break;
5225 default:
5226 return NT_STATUS_INVALID_LEVEL;
5229 if (!NT_STATUS_IS_OK(status)) {
5230 return status;
5233 *ret_data_size = data_return_size;
5234 return NT_STATUS_OK;
5237 static uint32_t generate_volume_serial_number(
5238 const struct loadparm_substitution *lp_sub,
5239 int snum)
5241 int serial = lp_volume_serial_number(snum);
5242 return serial != -1 ? serial:
5243 str_checksum(lp_servicename(talloc_tos(), lp_sub, snum)) ^
5244 (str_checksum(get_local_machine_name())<<16);