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/>.
28 #include "system/filesys.h"
29 #include "lib/util/time_basic.h"
31 #include "smbd/smbd.h"
32 #include "smbd/globals.h"
33 #include "../libcli/auth/libcli_auth.h"
34 #include "../librpc/gen_ndr/xattr.h"
35 #include "../librpc/gen_ndr/ndr_security.h"
36 #include "libcli/security/security.h"
39 #include "smbprofile.h"
40 #include "rpc_server/srv_pipe_hnd.h"
42 #include "lib/util_ea.h"
43 #include "lib/readdir_attr.h"
45 #include "libcli/smb/smb2_posix.h"
46 #include "lib/util/string_wrappers.h"
47 #include "source3/lib/substitute.h"
48 #include "source3/lib/adouble.h"
50 #define DIR_ENTRY_SAFETY_MARGIN 4096
52 static char *store_file_unix_basic(connection_struct *conn,
55 const SMB_STRUCT_STAT *psbuf);
57 static char *store_file_unix_basic_info2(connection_struct *conn,
60 const SMB_STRUCT_STAT *psbuf);
62 static uint32_t generate_volume_serial_number(
63 const struct loadparm_substitution *lp_sub,
66 /****************************************************************************
67 Check if an open file handle is a symlink.
68 ****************************************************************************/
70 NTSTATUS refuse_symlink_fsp(const files_struct *fsp)
73 if (!VALID_STAT(fsp->fsp_name->st)) {
74 return NT_STATUS_ACCESS_DENIED;
76 if (S_ISLNK(fsp->fsp_name->st.st_ex_mode)) {
77 return NT_STATUS_ACCESS_DENIED;
79 if (fsp_get_pathref_fd(fsp) == -1) {
80 return NT_STATUS_ACCESS_DENIED;
85 NTSTATUS check_access_fsp(struct files_struct *fsp,
88 if (!fsp->fsp_flags.is_fsa) {
89 return smbd_check_access_rights_fsp(fsp->conn->cwd_fsp,
94 if (!(fsp->access_mask & access_mask)) {
95 return NT_STATUS_ACCESS_DENIED;
100 #if defined(HAVE_POSIX_ACLS)
101 /****************************************************************************
102 Utility function to open a fsp for a POSIX handle operation.
103 ****************************************************************************/
105 static NTSTATUS get_posix_fsp(connection_struct *conn,
106 struct smb_request *req,
107 struct smb_filename *smb_fname,
108 uint32_t access_mask,
109 files_struct **ret_fsp)
112 uint32_t create_disposition = FILE_OPEN;
113 uint32_t share_access = FILE_SHARE_READ|
116 struct smb2_create_blobs *posx = NULL;
119 * Only FILE_FLAG_POSIX_SEMANTICS matters on existing files,
120 * but set reasonable defaults.
122 uint32_t file_attributes = 0664;
123 uint32_t oplock = NO_OPLOCK;
124 uint32_t create_options = FILE_NON_DIRECTORY_FILE;
126 /* File or directory must exist. */
127 if (!VALID_STAT(smb_fname->st)) {
128 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
130 /* Cannot be a symlink. */
131 if (S_ISLNK(smb_fname->st.st_ex_mode)) {
132 return NT_STATUS_ACCESS_DENIED;
134 /* Set options correctly for directory open. */
135 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
137 * Only FILE_FLAG_POSIX_SEMANTICS matters on existing
138 * directories, but set reasonable defaults.
140 file_attributes = 0775;
141 create_options = FILE_DIRECTORY_FILE;
144 status = make_smb2_posix_create_ctx(
145 talloc_tos(), &posx, file_attributes);
146 if (!NT_STATUS_IS_OK(status)) {
147 DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
152 status = SMB_VFS_CREATE_FILE(
156 smb_fname, /* fname */
157 access_mask, /* access_mask */
158 share_access, /* share_access */
159 create_disposition,/* create_disposition*/
160 create_options, /* create_options */
161 file_attributes,/* file_attributes */
162 oplock, /* oplock_request */
164 0, /* allocation_size */
165 0, /* private_flags */
168 ret_fsp, /* result */
170 posx, /* in_context */
171 NULL); /* out_context */
179 /********************************************************************
180 Roundup a value to the nearest allocation roundup size boundary.
181 Only do this for Windows clients.
182 ********************************************************************/
184 uint64_t smb_roundup(connection_struct *conn, uint64_t val)
186 uint64_t rval = lp_allocation_roundup_size(SNUM(conn));
188 /* Only roundup for Windows clients. */
189 enum remote_arch_types ra_type = get_remote_arch();
190 if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
191 val = SMB_ROUNDUP(val,rval);
196 /****************************************************************************
197 Utility functions for dealing with extended attributes.
198 ****************************************************************************/
200 /****************************************************************************
201 Refuse to allow clients to overwrite our private xattrs.
202 ****************************************************************************/
204 bool samba_private_attr_name(const char *unix_ea_name)
206 static const char * const prohibited_ea_names[] = {
207 SAMBA_POSIX_INHERITANCE_EA_NAME,
208 SAMBA_XATTR_DOS_ATTRIB,
217 for (i = 0; prohibited_ea_names[i]; i++) {
218 if (strequal( prohibited_ea_names[i], unix_ea_name))
221 if (strncasecmp_m(unix_ea_name, SAMBA_XATTR_DOSSTREAM_PREFIX,
222 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX)) == 0) {
228 /****************************************************************************
229 Get one EA value. Fill in a struct ea_struct.
230 ****************************************************************************/
232 NTSTATUS get_ea_value_fsp(TALLOC_CTX *mem_ctx,
235 struct ea_struct *pea)
237 /* Get the value of this xattr. Max size is 64k. */
238 size_t attr_size = 256;
241 size_t max_xattr_size = 0;
244 return NT_STATUS_INVALID_HANDLE;
247 max_xattr_size = lp_smbd_max_xattr_size(SNUM(fsp->conn));
251 val = talloc_realloc(mem_ctx, val, char, attr_size);
253 return NT_STATUS_NO_MEMORY;
256 sizeret = SMB_VFS_FGETXATTR(fsp, ea_name, val, attr_size);
257 if (sizeret == -1 && errno == ERANGE && attr_size < max_xattr_size) {
258 attr_size = max_xattr_size;
263 return map_nt_error_from_unix(errno);
266 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name, (unsigned int)sizeret));
267 dump_data(10, (uint8_t *)val, sizeret);
270 if (strnequal(ea_name, "user.", 5)) {
271 pea->name = talloc_strdup(mem_ctx, &ea_name[5]);
273 pea->name = talloc_strdup(mem_ctx, ea_name);
275 if (pea->name == NULL) {
277 return NT_STATUS_NO_MEMORY;
279 pea->value.data = (unsigned char *)val;
280 pea->value.length = (size_t)sizeret;
284 NTSTATUS get_ea_names_from_fsp(TALLOC_CTX *mem_ctx,
290 /* Get a list of all xattrs. Max namesize is 64k. */
291 size_t ea_namelist_size = 1024;
292 char *ea_namelist = smallbuf;
293 char *to_free = NULL;
298 ssize_t sizeret = -1;
308 * Callers may pass fsp == NULL when passing smb_fname->fsp of a
309 * symlink. This is ok, handle it here, by just return no EA's
315 /* should be the case that fsp != NULL */
316 SMB_ASSERT(fsp != NULL);
318 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
321 if ((sizeret == -1) && (errno == ERANGE)) {
322 ea_namelist_size = 65536;
323 ea_namelist = talloc_array(mem_ctx, char, ea_namelist_size);
324 if (ea_namelist == NULL) {
325 return NT_STATUS_NO_MEMORY;
327 to_free = ea_namelist;
329 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
334 status = map_nt_error_from_unix(errno);
335 TALLOC_FREE(to_free);
339 DBG_DEBUG("ea_namelist size = %zd\n", sizeret);
342 TALLOC_FREE(to_free);
347 * Ensure the result is 0-terminated
350 if (ea_namelist[sizeret-1] != '\0') {
351 TALLOC_FREE(to_free);
352 return NT_STATUS_INTERNAL_ERROR;
360 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
364 *pnum_names = num_names;
366 if (pnames == NULL) {
367 TALLOC_FREE(to_free);
371 names = talloc_array(mem_ctx, char *, num_names);
373 DEBUG(0, ("talloc failed\n"));
374 TALLOC_FREE(to_free);
375 return NT_STATUS_NO_MEMORY;
378 if (ea_namelist == smallbuf) {
379 ea_namelist = talloc_memdup(names, smallbuf, sizeret);
380 if (ea_namelist == NULL) {
382 return NT_STATUS_NO_MEMORY;
385 talloc_steal(names, ea_namelist);
387 ea_namelist = talloc_realloc(names, ea_namelist, char,
389 if (ea_namelist == NULL) {
391 return NT_STATUS_NO_MEMORY;
397 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
398 names[num_names++] = p;
406 /****************************************************************************
407 Return a linked list of the total EA's. Plus the total size
408 ****************************************************************************/
410 static NTSTATUS get_ea_list_from_fsp(TALLOC_CTX *mem_ctx,
412 size_t *pea_total_len,
413 struct ea_list **ea_list)
415 /* Get a list of all xattrs. Max namesize is 64k. */
418 struct ea_list *ea_list_head = NULL;
419 bool posix_pathnames = false;
430 if (!lp_ea_support(SNUM(fsp->conn))) {
434 if (fsp_is_alternate_stream(fsp)) {
435 return NT_STATUS_INVALID_PARAMETER;
438 posix_pathnames = (fsp->fsp_name->flags & SMB_FILENAME_POSIX_PATH);
440 status = get_ea_names_from_fsp(talloc_tos(),
445 if (!NT_STATUS_IS_OK(status)) {
449 if (num_names == 0) {
453 for (i=0; i<num_names; i++) {
454 struct ea_list *listp;
457 if (strnequal(names[i], "system.", 7)
458 || samba_private_attr_name(names[i]))
462 * Filter out any underlying POSIX EA names
463 * that a Windows client can't handle.
465 if (!posix_pathnames &&
466 is_invalid_windows_ea_name(names[i])) {
470 listp = talloc(mem_ctx, struct ea_list);
472 return NT_STATUS_NO_MEMORY;
475 status = get_ea_value_fsp(listp,
480 if (!NT_STATUS_IS_OK(status)) {
485 if (listp->ea.value.length == 0) {
487 * We can never return a zero length EA.
488 * Windows reports the EA's as corrupted.
492 } else if (listp->ea.value.length > 65536) {
494 * SMB clients may report error with file
495 * if large EA is presented to them.
497 DBG_ERR("EA [%s] on file [%s] exceeds "
498 "maximum permitted EA size of 64KiB: %zu\n.",
499 listp->ea.name, fsp_str_dbg(fsp),
500 listp->ea.value.length);
505 push_ascii_fstring(dos_ea_name, listp->ea.name);
508 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
510 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
511 "= %u\n", (unsigned int)*pea_total_len, dos_ea_name,
512 (unsigned int)listp->ea.value.length));
514 DLIST_ADD_END(ea_list_head, listp);
518 /* Add on 4 for total length. */
519 if (*pea_total_len) {
523 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
524 (unsigned int)*pea_total_len));
526 *ea_list = ea_list_head;
530 /****************************************************************************
531 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
533 ****************************************************************************/
535 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
536 connection_struct *conn, struct ea_list *ea_list)
538 unsigned int ret_data_size = 4;
541 SMB_ASSERT(total_data_size >= 4);
543 if (!lp_ea_support(SNUM(conn))) {
548 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
551 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
552 dos_namelen = strlen(dos_ea_name);
553 if (dos_namelen > 255 || dos_namelen == 0) {
556 if (ea_list->ea.value.length > 65535) {
559 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
563 /* We know we have room. */
564 SCVAL(p,0,ea_list->ea.flags);
565 SCVAL(p,1,dos_namelen);
566 SSVAL(p,2,ea_list->ea.value.length);
567 strlcpy(p+4, dos_ea_name, dos_namelen+1);
568 if (ea_list->ea.value.length > 0) {
569 memcpy(p + 4 + dos_namelen + 1,
570 ea_list->ea.value.data,
571 ea_list->ea.value.length);
574 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
575 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
578 ret_data_size = PTR_DIFF(p, pdata);
579 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
580 SIVAL(pdata,0,ret_data_size);
581 return ret_data_size;
584 static NTSTATUS fill_ea_chained_buffer(TALLOC_CTX *mem_ctx,
586 unsigned int total_data_size,
587 unsigned int *ret_data_size,
588 connection_struct *conn,
589 struct ea_list *ea_list)
591 uint8_t *p = (uint8_t *)pdata;
592 uint8_t *last_start = NULL;
593 bool do_store_data = (pdata != NULL);
597 if (!lp_ea_support(SNUM(conn))) {
598 return NT_STATUS_NO_EAS_ON_FILE;
601 for (; ea_list; ea_list = ea_list->next) {
607 if (last_start != NULL && do_store_data) {
608 SIVAL(last_start, 0, PTR_DIFF(p, last_start));
612 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
613 dos_namelen = strlen(dos_ea_name);
614 if (dos_namelen > 255 || dos_namelen == 0) {
615 return NT_STATUS_INTERNAL_ERROR;
617 if (ea_list->ea.value.length > 65535) {
618 return NT_STATUS_INTERNAL_ERROR;
621 this_size = 0x08 + dos_namelen + 1 + ea_list->ea.value.length;
624 pad = (4 - (this_size % 4)) % 4;
629 if (this_size > total_data_size) {
630 return NT_STATUS_INFO_LENGTH_MISMATCH;
633 /* We know we have room. */
634 SIVAL(p, 0x00, 0); /* next offset */
635 SCVAL(p, 0x04, ea_list->ea.flags);
636 SCVAL(p, 0x05, dos_namelen);
637 SSVAL(p, 0x06, ea_list->ea.value.length);
638 strlcpy((char *)(p+0x08), dos_ea_name, dos_namelen+1);
639 memcpy(p + 0x08 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
641 memset(p + 0x08 + dos_namelen + 1 + ea_list->ea.value.length,
645 total_data_size -= this_size;
651 *ret_data_size = PTR_DIFF(p, pdata);
652 DEBUG(10,("fill_ea_chained_buffer: data_size = %u\n", *ret_data_size));
656 unsigned int estimate_ea_size(files_struct *fsp)
658 size_t total_ea_len = 0;
660 struct ea_list *ea_list = NULL;
668 if (!lp_ea_support(SNUM(fsp->conn))) {
672 mem_ctx = talloc_stackframe();
674 /* If this is a stream fsp, then we need to instead find the
675 * estimated ea len from the main file, not the stream
676 * (streams cannot have EAs), but the estimate isn't just 0 in
678 fsp = metadata_fsp(fsp);
679 (void)get_ea_list_from_fsp(mem_ctx,
684 if(fsp->conn->sconn->using_smb2) {
685 unsigned int ret_data_size;
687 * We're going to be using fill_ea_chained_buffer() to
688 * marshall EA's - this size is significantly larger
689 * than the SMB1 buffer. Re-calculate the size without
692 status = fill_ea_chained_buffer(mem_ctx,
698 if (!NT_STATUS_IS_OK(status)) {
701 total_ea_len = ret_data_size;
703 TALLOC_FREE(mem_ctx);
707 /****************************************************************************
708 Ensure the EA name is case insensitive by matching any existing EA name.
709 ****************************************************************************/
711 static void canonicalize_ea_name(files_struct *fsp,
712 fstring unix_ea_name)
715 TALLOC_CTX *mem_ctx = talloc_tos();
716 struct ea_list *ea_list;
717 NTSTATUS status = get_ea_list_from_fsp(mem_ctx,
721 if (!NT_STATUS_IS_OK(status)) {
725 for (; ea_list; ea_list = ea_list->next) {
726 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
727 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
728 &unix_ea_name[5], ea_list->ea.name));
729 strlcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-5);
735 /****************************************************************************
736 Set or delete an extended attribute.
737 ****************************************************************************/
739 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp,
740 struct ea_list *ea_list)
743 bool posix_pathnames = false;
745 if (!lp_ea_support(SNUM(conn))) {
746 return NT_STATUS_EAS_NOT_SUPPORTED;
750 return NT_STATUS_INVALID_HANDLE;
753 posix_pathnames = (fsp->fsp_name->flags & SMB_FILENAME_POSIX_PATH);
755 status = refuse_symlink_fsp(fsp);
756 if (!NT_STATUS_IS_OK(status)) {
760 status = check_access_fsp(fsp, FILE_WRITE_EA);
761 if (!NT_STATUS_IS_OK(status)) {
765 /* Setting EAs on streams isn't supported. */
766 if (fsp_is_alternate_stream(fsp)) {
767 return NT_STATUS_INVALID_PARAMETER;
771 * Filter out invalid Windows EA names - before
772 * we set *any* of them.
775 if (!posix_pathnames && ea_list_has_invalid_name(ea_list)) {
776 return STATUS_INVALID_EA_NAME;
779 for (;ea_list; ea_list = ea_list->next) {
781 fstring unix_ea_name;
783 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
784 fstrcat(unix_ea_name, ea_list->ea.name);
786 canonicalize_ea_name(fsp, unix_ea_name);
788 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
790 if (samba_private_attr_name(unix_ea_name)) {
791 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
792 return NT_STATUS_ACCESS_DENIED;
795 if (ea_list->ea.value.length == 0) {
796 /* Remove the attribute. */
797 DBG_DEBUG("deleting ea name %s on "
798 "file %s by file descriptor.\n",
799 unix_ea_name, fsp_str_dbg(fsp));
800 ret = SMB_VFS_FREMOVEXATTR(fsp, unix_ea_name);
802 /* Removing a non existent attribute always succeeds. */
803 if (ret == -1 && errno == ENOATTR) {
804 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
810 DEBUG(10,("set_ea: setting ea name %s on file "
811 "%s by file descriptor.\n",
812 unix_ea_name, fsp_str_dbg(fsp)));
813 ret = SMB_VFS_FSETXATTR(fsp, unix_ea_name,
814 ea_list->ea.value.data, ea_list->ea.value.length, 0);
819 if (errno == ENOTSUP) {
820 return NT_STATUS_EAS_NOT_SUPPORTED;
823 return map_nt_error_from_unix(errno);
830 /****************************************************************************
831 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
832 ****************************************************************************/
834 struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
836 struct ea_list *ea_list_head = NULL;
838 size_t bytes_used = 0;
840 while (offset < data_size) {
841 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
847 DLIST_ADD_END(ea_list_head, eal);
848 offset += bytes_used;
854 /****************************************************************************
855 Count the total EA size needed.
856 ****************************************************************************/
858 static size_t ea_list_size(struct ea_list *ealist)
861 struct ea_list *listp;
864 for (listp = ealist; listp; listp = listp->next) {
865 push_ascii_fstring(dos_ea_name, listp->ea.name);
866 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
868 /* Add on 4 for total length. */
876 /****************************************************************************
877 Return a union of EA's from a file list and a list of names.
878 The TALLOC context for the two lists *MUST* be identical as we steal
879 memory from one list to add to another. JRA.
880 ****************************************************************************/
882 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
884 struct ea_list *nlistp, *flistp;
886 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
887 for (flistp = file_list; flistp; flistp = flistp->next) {
888 if (strequal(nlistp->ea.name, flistp->ea.name)) {
894 /* Copy the data from this entry. */
895 nlistp->ea.flags = flistp->ea.flags;
896 nlistp->ea.value = flistp->ea.value;
899 nlistp->ea.flags = 0;
900 ZERO_STRUCT(nlistp->ea.value);
904 *total_ea_len = ea_list_size(name_list);
908 /*********************************************************
909 Routine to check if a given string matches exactly.
910 as a special case a mask of "." does NOT match. That
911 is required for correct wildcard semantics
912 Case can be significant or not.
913 **********************************************************/
915 static bool exact_match(bool has_wild,
920 if (mask[0] == '.' && mask[1] == 0) {
928 if (case_sensitive) {
929 return strcmp(str,mask)==0;
931 return strcasecmp_m(str,mask) == 0;
935 /****************************************************************************
936 Return the filetype for UNIX extensions.
937 ****************************************************************************/
939 static uint32_t unix_filetype(mode_t mode)
942 return UNIX_TYPE_FILE;
943 else if(S_ISDIR(mode))
944 return UNIX_TYPE_DIR;
946 else if(S_ISLNK(mode))
947 return UNIX_TYPE_SYMLINK;
950 else if(S_ISCHR(mode))
951 return UNIX_TYPE_CHARDEV;
954 else if(S_ISBLK(mode))
955 return UNIX_TYPE_BLKDEV;
958 else if(S_ISFIFO(mode))
959 return UNIX_TYPE_FIFO;
962 else if(S_ISSOCK(mode))
963 return UNIX_TYPE_SOCKET;
966 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
967 return UNIX_TYPE_UNKNOWN;
970 /****************************************************************************
971 Map wire perms onto standard UNIX permissions. Obey share restrictions.
972 ****************************************************************************/
974 NTSTATUS unix_perms_from_wire(connection_struct *conn,
975 const SMB_STRUCT_STAT *psbuf,
977 enum perm_type ptype,
982 if (perms == SMB_MODE_NO_CHANGE) {
983 if (!VALID_STAT(*psbuf)) {
984 return NT_STATUS_INVALID_PARAMETER;
986 *ret_perms = psbuf->st_ex_mode;
991 ret = wire_perms_to_unix(perms);
993 if (ptype == PERM_NEW_FILE) {
995 * "create mask"/"force create mode" are
996 * only applied to new files, not existing ones.
998 ret &= lp_create_mask(SNUM(conn));
999 /* Add in force bits */
1000 ret |= lp_force_create_mode(SNUM(conn));
1001 } else if (ptype == PERM_NEW_DIR) {
1003 * "directory mask"/"force directory mode" are
1004 * only applied to new directories, not existing ones.
1006 ret &= lp_directory_mask(SNUM(conn));
1007 /* Add in force bits */
1008 ret |= lp_force_directory_mode(SNUM(conn));
1012 return NT_STATUS_OK;
1015 /****************************************************************************
1016 Needed to show the msdfs symlinks as directories. Modifies psbuf
1017 to be a directory if it's a msdfs link.
1018 ****************************************************************************/
1020 static bool check_msdfs_link(struct files_struct *dirfsp,
1021 struct smb_filename *atname,
1022 struct smb_filename *smb_fname)
1024 int saved_errno = errno;
1025 if(lp_host_msdfs() &&
1026 lp_msdfs_root(SNUM(dirfsp->conn)) &&
1027 is_msdfs_link(dirfsp, atname)) {
1030 * Copy the returned stat struct from the relative
1031 * to the full pathname.
1033 smb_fname->st = atname->st;
1035 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1037 smb_fname->base_name));
1038 smb_fname->st.st_ex_mode =
1039 (smb_fname->st.st_ex_mode & 0xFFF) | S_IFDIR;
1040 errno = saved_errno;
1043 errno = saved_errno;
1048 /****************************************************************************
1049 Get a level dependent lanman2 dir entry.
1050 ****************************************************************************/
1052 struct smbd_dirptr_lanman2_state {
1053 connection_struct *conn;
1054 uint32_t info_level;
1055 bool check_mangled_names;
1057 bool got_exact_match;
1058 bool case_sensitive;
1061 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX *ctx,
1067 struct smbd_dirptr_lanman2_state *state =
1068 (struct smbd_dirptr_lanman2_state *)private_data;
1070 char mangled_name[13]; /* mangled 8.3 name. */
1074 /* Mangle fname if it's an illegal name. */
1075 if (mangle_must_mangle(dname, state->conn->params)) {
1077 * Slow path - ensure we can push the original name as UCS2. If
1078 * not, then just don't return this name.
1082 size_t len = (strlen(dname) + 2) * 4; /* Allow enough space. */
1083 uint8_t *tmp = talloc_array(talloc_tos(),
1087 status = srvstr_push(NULL,
1088 FLAGS2_UNICODE_STRINGS,
1097 if (!NT_STATUS_IS_OK(status)) {
1101 ok = name_to_8_3(dname, mangled_name,
1102 true, state->conn->params);
1106 fname = mangled_name;
1111 got_match = exact_match(state->has_wild,
1112 state->case_sensitive,
1114 state->got_exact_match = got_match;
1116 got_match = mask_match(fname, mask,
1117 state->case_sensitive);
1120 if(!got_match && state->check_mangled_names &&
1121 !mangle_is_8_3(fname, false, state->conn->params)) {
1123 * It turns out that NT matches wildcards against
1124 * both long *and* short names. This may explain some
1125 * of the wildcard wierdness from old DOS clients
1126 * that some people have been seeing.... JRA.
1128 /* Force the mangling into 8.3. */
1129 ok = name_to_8_3(fname, mangled_name,
1130 false, state->conn->params);
1135 got_match = exact_match(state->has_wild,
1136 state->case_sensitive,
1137 mangled_name, mask);
1138 state->got_exact_match = got_match;
1140 got_match = mask_match(mangled_name, mask,
1141 state->case_sensitive);
1149 *_fname = talloc_strdup(ctx, fname);
1150 if (*_fname == NULL) {
1157 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX *ctx,
1159 struct files_struct *dirfsp,
1160 struct smb_filename *atname,
1161 struct smb_filename *smb_fname,
1165 struct smbd_dirptr_lanman2_state *state =
1166 (struct smbd_dirptr_lanman2_state *)private_data;
1167 bool ms_dfs_link = false;
1169 if (smb_fname->flags & SMB_FILENAME_POSIX_PATH) {
1170 if (SMB_VFS_LSTAT(state->conn, smb_fname) != 0) {
1171 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1172 "Couldn't lstat [%s] (%s)\n",
1173 smb_fname_str_dbg(smb_fname),
1180 if (!VALID_STAT(smb_fname->st) &&
1181 SMB_VFS_STAT(state->conn, smb_fname) != 0) {
1182 /* Needed to show the msdfs symlinks as
1185 ms_dfs_link = check_msdfs_link(dirfsp,
1189 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1190 "Couldn't stat [%s] (%s)\n",
1191 smb_fname_str_dbg(smb_fname),
1196 *_mode = dos_mode_msdfs(state->conn, smb_fname);
1204 *_mode = fdos_mode(smb_fname->fsp);
1205 smb_fname->st = smb_fname->fsp->fsp_name->st;
1210 static NTSTATUS smbd_marshall_dir_entry(TALLOC_CTX *ctx,
1211 connection_struct *conn,
1213 uint32_t info_level,
1214 struct ea_list *name_list,
1215 bool check_mangled_names,
1216 bool requires_resume_key,
1219 const struct smb_filename *smb_fname,
1220 int space_remaining,
1226 uint64_t *last_entry_off)
1228 char *p, *q, *pdata = *ppdata;
1230 uint64_t file_size = 0;
1231 uint64_t allocation_size = 0;
1232 uint64_t file_id = 0;
1234 struct timespec mdate_ts = {0};
1235 struct timespec adate_ts = {0};
1236 struct timespec cdate_ts = {0};
1237 struct timespec create_date_ts = {0};
1238 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1240 char *last_entry_ptr;
1245 struct readdir_attr_data *readdir_attr_data = NULL;
1247 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
1248 file_size = get_file_size_stat(&smb_fname->st);
1250 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
1253 * Skip SMB_VFS_FREADDIR_ATTR if the directory entry is a symlink or
1256 if (smb_fname->fsp != NULL &&
1257 !(mode & FILE_ATTRIBUTE_REPARSE_POINT)) {
1258 status = SMB_VFS_FREADDIR_ATTR(smb_fname->fsp,
1260 &readdir_attr_data);
1261 if (!NT_STATUS_IS_OK(status)) {
1262 if (!NT_STATUS_EQUAL(NT_STATUS_NOT_SUPPORTED,
1269 file_id = SMB_VFS_FS_FILE_ID(conn, &smb_fname->st);
1271 mdate_ts = smb_fname->st.st_ex_mtime;
1272 adate_ts = smb_fname->st.st_ex_atime;
1273 create_date_ts = get_create_timespec(conn, NULL, smb_fname);
1274 cdate_ts = get_change_timespec(conn, NULL, smb_fname);
1276 if (lp_dos_filetime_resolution(SNUM(conn))) {
1277 dos_filetime_timespec(&create_date_ts);
1278 dos_filetime_timespec(&mdate_ts);
1279 dos_filetime_timespec(&adate_ts);
1280 dos_filetime_timespec(&cdate_ts);
1283 create_date = convert_timespec_to_time_t(create_date_ts);
1284 mdate = convert_timespec_to_time_t(mdate_ts);
1285 adate = convert_timespec_to_time_t(adate_ts);
1287 /* align the record */
1288 SMB_ASSERT(align >= 1);
1290 off = (int)PTR_DIFF(pdata, base_data);
1291 pad = (off + (align-1)) & ~(align-1);
1294 if (pad && pad > space_remaining) {
1295 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1296 "for padding (wanted %u, had %d)\n",
1299 return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
1303 /* initialize padding to 0 */
1305 memset(pdata, 0, pad);
1307 space_remaining -= pad;
1309 DEBUG(10,("smbd_marshall_dir_entry: space_remaining = %d\n",
1319 switch (info_level) {
1320 case SMB_FIND_INFO_STANDARD:
1321 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1322 if(requires_resume_key) {
1326 srv_put_dos_date2(p,0,create_date);
1327 srv_put_dos_date2(p,4,adate);
1328 srv_put_dos_date2(p,8,mdate);
1329 SIVAL(p,12,(uint32_t)file_size);
1330 SIVAL(p,16,(uint32_t)allocation_size);
1334 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1335 p += ucs2_align(base_data, p, 0);
1337 status = srvstr_push(base_data, flags2, p,
1338 fname, PTR_DIFF(end_data, p),
1339 STR_TERMINATE, &len);
1340 if (!NT_STATUS_IS_OK(status)) {
1343 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1345 SCVAL(nameptr, -1, len - 2);
1347 SCVAL(nameptr, -1, 0);
1351 SCVAL(nameptr, -1, len - 1);
1353 SCVAL(nameptr, -1, 0);
1359 case SMB_FIND_EA_SIZE:
1360 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
1361 if (requires_resume_key) {
1365 srv_put_dos_date2(p,0,create_date);
1366 srv_put_dos_date2(p,4,adate);
1367 srv_put_dos_date2(p,8,mdate);
1368 SIVAL(p,12,(uint32_t)file_size);
1369 SIVAL(p,16,(uint32_t)allocation_size);
1372 unsigned int ea_size = estimate_ea_size(smb_fname->fsp);
1373 SIVAL(p,22,ea_size); /* Extended attributes */
1377 status = srvstr_push(base_data, flags2,
1378 p, fname, PTR_DIFF(end_data, p),
1379 STR_TERMINATE | STR_NOALIGN, &len);
1380 if (!NT_STATUS_IS_OK(status)) {
1383 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1396 SCVAL(nameptr,0,len);
1398 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1401 case SMB_FIND_EA_LIST:
1403 struct ea_list *file_list = NULL;
1406 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
1408 return NT_STATUS_INVALID_PARAMETER;
1410 if (requires_resume_key) {
1414 srv_put_dos_date2(p,0,create_date);
1415 srv_put_dos_date2(p,4,adate);
1416 srv_put_dos_date2(p,8,mdate);
1417 SIVAL(p,12,(uint32_t)file_size);
1418 SIVAL(p,16,(uint32_t)allocation_size);
1420 p += 22; /* p now points to the EA area. */
1422 status = get_ea_list_from_fsp(ctx,
1424 &ea_len, &file_list);
1425 if (!NT_STATUS_IS_OK(status)) {
1428 name_list = ea_list_union(name_list, file_list, &ea_len);
1430 /* We need to determine if this entry will fit in the space available. */
1431 /* Max string size is 255 bytes. */
1432 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1433 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1434 "(wanted %u, had %d)\n",
1435 (unsigned int)PTR_DIFF(p + 255 + ea_len,pdata),
1437 return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
1440 /* Push the ea_data followed by the name. */
1441 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1443 status = srvstr_push(base_data, flags2,
1444 p + 1, fname, PTR_DIFF(end_data, p+1),
1445 STR_TERMINATE | STR_NOALIGN, &len);
1446 if (!NT_STATUS_IS_OK(status)) {
1449 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1462 SCVAL(nameptr,0,len);
1464 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1468 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1469 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1470 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1472 SIVAL(p,0,reskey); p += 4;
1473 put_long_date_full_timespec(conn->ts_res,p,&create_date_ts); p += 8;
1474 put_long_date_full_timespec(conn->ts_res,p,&adate_ts); p += 8;
1475 put_long_date_full_timespec(conn->ts_res,p,&mdate_ts); p += 8;
1476 put_long_date_full_timespec(conn->ts_res,p,&cdate_ts); p += 8;
1477 SOFF_T(p,0,file_size); p += 8;
1478 SOFF_T(p,0,allocation_size); p += 8;
1479 SIVAL(p,0,mode); p += 4;
1480 q = p; p += 4; /* q is placeholder for name length. */
1481 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
1482 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
1484 unsigned int ea_size = estimate_ea_size(smb_fname->fsp);
1485 SIVAL(p,0,ea_size); /* Extended attributes */
1488 /* Clear the short name buffer. This is
1489 * IMPORTANT as not doing so will trigger
1490 * a Win2k client bug. JRA.
1492 if (!was_8_3 && check_mangled_names) {
1493 char mangled_name[13]; /* mangled 8.3 name. */
1494 if (!name_to_8_3(fname,mangled_name,True,
1496 /* Error - mangle failed ! */
1497 memset(mangled_name,'\0',12);
1499 mangled_name[12] = 0;
1500 status = srvstr_push(base_data, flags2,
1501 p+2, mangled_name, 24,
1502 STR_UPPER|STR_UNICODE, &len);
1503 if (!NT_STATUS_IS_OK(status)) {
1507 memset(p + 2 + len,'\0',24 - len);
1514 status = srvstr_push(base_data, flags2, p,
1515 fname, PTR_DIFF(end_data, p),
1516 STR_TERMINATE_ASCII, &len);
1517 if (!NT_STATUS_IS_OK(status)) {
1523 len = PTR_DIFF(p, pdata);
1524 pad = (len + (align-1)) & ~(align-1);
1526 * offset to the next entry, the caller
1527 * will overwrite it for the last entry
1528 * that's why we always include the padding
1532 * set padding to zero
1535 memset(p, 0, pad - len);
1542 case SMB_FIND_FILE_DIRECTORY_INFO:
1543 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1545 SIVAL(p,0,reskey); p += 4;
1546 put_long_date_full_timespec(conn->ts_res,p,&create_date_ts); p += 8;
1547 put_long_date_full_timespec(conn->ts_res,p,&adate_ts); p += 8;
1548 put_long_date_full_timespec(conn->ts_res,p,&mdate_ts); p += 8;
1549 put_long_date_full_timespec(conn->ts_res,p,&cdate_ts); p += 8;
1550 SOFF_T(p,0,file_size); p += 8;
1551 SOFF_T(p,0,allocation_size); p += 8;
1552 SIVAL(p,0,mode); p += 4;
1553 status = srvstr_push(base_data, flags2,
1554 p + 4, fname, PTR_DIFF(end_data, p+4),
1555 STR_TERMINATE_ASCII, &len);
1556 if (!NT_STATUS_IS_OK(status)) {
1562 len = PTR_DIFF(p, pdata);
1563 pad = (len + (align-1)) & ~(align-1);
1565 * offset to the next entry, the caller
1566 * will overwrite it for the last entry
1567 * that's why we always include the padding
1571 * set padding to zero
1574 memset(p, 0, pad - len);
1581 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1582 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1584 SIVAL(p,0,reskey); p += 4;
1585 put_long_date_full_timespec(conn->ts_res,p,&create_date_ts); p += 8;
1586 put_long_date_full_timespec(conn->ts_res,p,&adate_ts); p += 8;
1587 put_long_date_full_timespec(conn->ts_res,p,&mdate_ts); p += 8;
1588 put_long_date_full_timespec(conn->ts_res,p,&cdate_ts); p += 8;
1589 SOFF_T(p,0,file_size); p += 8;
1590 SOFF_T(p,0,allocation_size); p += 8;
1591 SIVAL(p,0,mode); p += 4;
1592 q = p; p += 4; /* q is placeholder for name length. */
1593 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
1594 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
1596 unsigned int ea_size = estimate_ea_size(smb_fname->fsp);
1597 SIVAL(p,0,ea_size); /* Extended attributes */
1600 status = srvstr_push(base_data, flags2, p,
1601 fname, PTR_DIFF(end_data, p),
1602 STR_TERMINATE_ASCII, &len);
1603 if (!NT_STATUS_IS_OK(status)) {
1609 len = PTR_DIFF(p, pdata);
1610 pad = (len + (align-1)) & ~(align-1);
1612 * offset to the next entry, the caller
1613 * will overwrite it for the last entry
1614 * that's why we always include the padding
1618 * set padding to zero
1621 memset(p, 0, pad - len);
1628 case SMB_FIND_FILE_NAMES_INFO:
1629 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1631 SIVAL(p,0,reskey); p += 4;
1633 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1634 acl on a dir (tridge) */
1635 status = srvstr_push(base_data, flags2, p,
1636 fname, PTR_DIFF(end_data, p),
1637 STR_TERMINATE_ASCII, &len);
1638 if (!NT_STATUS_IS_OK(status)) {
1644 len = PTR_DIFF(p, pdata);
1645 pad = (len + (align-1)) & ~(align-1);
1647 * offset to the next entry, the caller
1648 * will overwrite it for the last entry
1649 * that's why we always include the padding
1653 * set padding to zero
1656 memset(p, 0, pad - len);
1663 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1664 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1666 SIVAL(p,0,reskey); p += 4;
1667 put_long_date_full_timespec(conn->ts_res,p,&create_date_ts); p += 8;
1668 put_long_date_full_timespec(conn->ts_res,p,&adate_ts); p += 8;
1669 put_long_date_full_timespec(conn->ts_res,p,&mdate_ts); p += 8;
1670 put_long_date_full_timespec(conn->ts_res,p,&cdate_ts); p += 8;
1671 SOFF_T(p,0,file_size); p += 8;
1672 SOFF_T(p,0,allocation_size); p += 8;
1673 SIVAL(p,0,mode); p += 4;
1674 q = p; p += 4; /* q is placeholder for name length. */
1675 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
1676 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
1678 unsigned int ea_size = estimate_ea_size(smb_fname->fsp);
1679 SIVAL(p,0,ea_size); /* Extended attributes */
1682 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1683 SBVAL(p,0,file_id); p += 8;
1684 status = srvstr_push(base_data, flags2, p,
1685 fname, PTR_DIFF(end_data, p),
1686 STR_TERMINATE_ASCII, &len);
1687 if (!NT_STATUS_IS_OK(status)) {
1693 len = PTR_DIFF(p, pdata);
1694 pad = (len + (align-1)) & ~(align-1);
1696 * offset to the next entry, the caller
1697 * will overwrite it for the last entry
1698 * that's why we always include the padding
1702 * set padding to zero
1705 memset(p, 0, pad - len);
1712 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1713 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1714 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1716 SIVAL(p,0,reskey); p += 4;
1717 put_long_date_full_timespec(conn->ts_res,p,&create_date_ts); p += 8;
1718 put_long_date_full_timespec(conn->ts_res,p,&adate_ts); p += 8;
1719 put_long_date_full_timespec(conn->ts_res,p,&mdate_ts); p += 8;
1720 put_long_date_full_timespec(conn->ts_res,p,&cdate_ts); p += 8;
1721 SOFF_T(p,0,file_size); p += 8;
1722 SOFF_T(p,0,allocation_size); p += 8;
1723 SIVAL(p,0,mode); p += 4;
1724 q = p; p += 4; /* q is placeholder for name length */
1725 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
1726 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
1727 } else if (readdir_attr_data &&
1728 readdir_attr_data->type == RDATTR_AAPL) {
1730 * OS X specific SMB2 extension negotiated via
1731 * AAPL create context: return max_access in
1734 SIVAL(p, 0, readdir_attr_data->attr_data.aapl.max_access);
1736 unsigned int ea_size = estimate_ea_size(smb_fname->fsp);
1737 SIVAL(p,0,ea_size); /* Extended attributes */
1741 if (readdir_attr_data &&
1742 readdir_attr_data->type == RDATTR_AAPL) {
1744 * OS X specific SMB2 extension negotiated via
1745 * AAPL create context: return resource fork
1746 * length and compressed FinderInfo in
1749 * According to documentation short_name_len
1750 * should be 0, but on the wire behaviour
1751 * shows its set to 24 by clients.
1755 /* Resourefork length */
1756 SBVAL(p, 2, readdir_attr_data->attr_data.aapl.rfork_size);
1758 /* Compressed FinderInfo */
1759 memcpy(p + 10, &readdir_attr_data->attr_data.aapl.finder_info, 16);
1760 } else if (!was_8_3 && check_mangled_names) {
1761 char mangled_name[13]; /* mangled 8.3 name. */
1762 if (!name_to_8_3(fname,mangled_name,True,
1764 /* Error - mangle failed ! */
1765 memset(mangled_name,'\0',12);
1767 mangled_name[12] = 0;
1768 status = srvstr_push(base_data, flags2,
1769 p+2, mangled_name, 24,
1770 STR_UPPER|STR_UNICODE, &len);
1771 if (!NT_STATUS_IS_OK(status)) {
1776 memset(p + 2 + len,'\0',24 - len);
1780 /* Clear the short name buffer. This is
1781 * IMPORTANT as not doing so will trigger
1782 * a Win2k client bug. JRA.
1789 if (readdir_attr_data &&
1790 readdir_attr_data->type == RDATTR_AAPL) {
1792 * OS X specific SMB2 extension negotiated via
1793 * AAPL create context: return UNIX mode in
1796 uint16_t aapl_mode = (uint16_t)readdir_attr_data->attr_data.aapl.unix_mode;
1797 SSVAL(p, 0, aapl_mode);
1803 SBVAL(p,0,file_id); p += 8;
1804 status = srvstr_push(base_data, flags2, p,
1805 fname, PTR_DIFF(end_data, p),
1806 STR_TERMINATE_ASCII, &len);
1807 if (!NT_STATUS_IS_OK(status)) {
1813 len = PTR_DIFF(p, pdata);
1814 pad = (len + (align-1)) & ~(align-1);
1816 * offset to the next entry, the caller
1817 * will overwrite it for the last entry
1818 * that's why we always include the padding
1822 * set padding to zero
1825 memset(p, 0, pad - len);
1832 /* CIFS UNIX Extension. */
1834 case SMB_FIND_FILE_UNIX:
1835 case SMB_FIND_FILE_UNIX_INFO2:
1837 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1839 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1841 if (info_level == SMB_FIND_FILE_UNIX) {
1842 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
1843 p = store_file_unix_basic(conn, p,
1844 NULL, &smb_fname->st);
1845 status = srvstr_push(base_data, flags2, p,
1846 fname, PTR_DIFF(end_data, p),
1847 STR_TERMINATE, &len);
1848 if (!NT_STATUS_IS_OK(status)) {
1852 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
1853 p = store_file_unix_basic_info2(conn, p,
1854 NULL, &smb_fname->st);
1857 status = srvstr_push(base_data, flags2, p, fname,
1858 PTR_DIFF(end_data, p), 0, &len);
1859 if (!NT_STATUS_IS_OK(status)) {
1862 SIVAL(nameptr, 0, len);
1867 len = PTR_DIFF(p, pdata);
1868 pad = (len + (align-1)) & ~(align-1);
1870 * offset to the next entry, the caller
1871 * will overwrite it for the last entry
1872 * that's why we always include the padding
1876 * set padding to zero
1879 memset(p, 0, pad - len);
1884 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1889 return NT_STATUS_INVALID_LEVEL;
1892 if (PTR_DIFF(p,pdata) > space_remaining) {
1893 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1894 "(wanted %u, had %d)\n",
1895 (unsigned int)PTR_DIFF(p,pdata),
1897 return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
1900 /* Setup the last entry pointer, as an offset from base_data */
1901 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
1902 /* Advance the data pointer to the next slot */
1905 return NT_STATUS_OK;
1908 NTSTATUS smbd_dirptr_lanman2_entry(TALLOC_CTX *ctx,
1909 connection_struct *conn,
1910 struct dptr_struct *dirptr,
1912 const char *path_mask,
1915 int requires_resume_key,
1924 int space_remaining,
1925 struct smb_filename **_smb_fname,
1926 bool *got_exact_match,
1927 int *_last_entry_off,
1928 struct ea_list *name_list,
1929 struct file_id *file_id)
1932 const char *mask = NULL;
1933 long prev_dirpos = 0;
1936 struct smb_filename *smb_fname = NULL;
1937 struct smbd_dirptr_lanman2_state state;
1939 uint64_t last_entry_off = 0;
1941 enum mangled_names_options mangled_names;
1942 bool marshall_with_83_names;
1944 mangled_names = lp_mangled_names(conn->params);
1948 state.info_level = info_level;
1949 if (mangled_names != MANGLED_NAMES_NO) {
1950 state.check_mangled_names = true;
1952 state.has_wild = dptr_has_wild(dirptr);
1953 state.got_exact_match = false;
1954 state.case_sensitive = dptr_case_sensitive(dirptr);
1956 *got_exact_match = false;
1958 p = strrchr_m(path_mask,'/');
1969 ok = smbd_dirptr_get_entry(ctx,
1976 smbd_dirptr_lanman2_match_fn,
1977 smbd_dirptr_lanman2_mode_fn,
1984 return NT_STATUS_END_OF_FILE;
1987 *got_exact_match = state.got_exact_match;
1989 marshall_with_83_names = (mangled_names == MANGLED_NAMES_YES);
1991 status = smbd_marshall_dir_entry(ctx,
1996 marshall_with_83_names,
1997 requires_resume_key,
2008 if (NT_STATUS_EQUAL(status, NT_STATUS_ILLEGAL_CHARACTER)) {
2009 DEBUG(1,("Conversion error: illegal character: %s\n",
2010 smb_fname_str_dbg(smb_fname)));
2013 if (file_id != NULL) {
2014 *file_id = vfs_file_id_from_sbuf(conn, &smb_fname->st);
2017 if (!NT_STATUS_IS_OK(status) &&
2018 !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES))
2020 TALLOC_FREE(smb_fname);
2025 if (_smb_fname != NULL) {
2027 * smb_fname is already talloc'ed off ctx.
2028 * We just need to make sure we don't return
2029 * any stream_name, and replace base_name
2030 * with fname in case base_name got mangled.
2031 * This allows us to preserve any smb_fname->fsp
2032 * for asynchronous handle lookups.
2034 TALLOC_FREE(smb_fname->stream_name);
2035 TALLOC_FREE(smb_fname->base_name);
2036 smb_fname->base_name = talloc_strdup(smb_fname, fname);
2038 if (smb_fname->base_name == NULL) {
2039 TALLOC_FREE(smb_fname);
2041 return NT_STATUS_NO_MEMORY;
2043 *_smb_fname = smb_fname;
2045 TALLOC_FREE(smb_fname);
2049 if (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
2050 dptr_SeekDir(dirptr, prev_dirpos);
2054 *_last_entry_off = last_entry_off;
2055 return NT_STATUS_OK;
2058 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
2060 const struct loadparm_substitution *lp_sub =
2061 loadparm_s3_global_substitution();
2063 E_md4hash(lp_servicename(talloc_tos(), lp_sub, SNUM(conn)),objid);
2067 static void samba_extended_info_version(struct smb_extended_info *extended_info)
2069 SMB_ASSERT(extended_info != NULL);
2071 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
2072 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
2073 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
2074 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
2075 #ifdef SAMBA_VERSION_REVISION
2076 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
2078 extended_info->samba_subversion = 0;
2079 #ifdef SAMBA_VERSION_RC_RELEASE
2080 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
2082 #ifdef SAMBA_VERSION_PRE_RELEASE
2083 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
2086 #ifdef SAMBA_VERSION_VENDOR_PATCH
2087 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
2089 extended_info->samba_gitcommitdate = 0;
2090 #ifdef SAMBA_VERSION_COMMIT_TIME
2091 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_COMMIT_TIME);
2094 memset(extended_info->samba_version_string, 0,
2095 sizeof(extended_info->samba_version_string));
2097 snprintf (extended_info->samba_version_string,
2098 sizeof(extended_info->samba_version_string),
2099 "%s", samba_version_string());
2102 NTSTATUS smbd_do_qfsinfo(struct smbXsrv_connection *xconn,
2103 connection_struct *conn,
2104 TALLOC_CTX *mem_ctx,
2105 uint16_t info_level,
2107 unsigned int max_data_bytes,
2108 size_t *fixed_portion,
2109 struct smb_filename *fname,
2113 const struct loadparm_substitution *lp_sub =
2114 loadparm_s3_global_substitution();
2115 char *pdata, *end_data;
2118 const char *vname = volume_label(talloc_tos(), SNUM(conn));
2119 int snum = SNUM(conn);
2120 const char *fstype = lp_fstype(SNUM(conn));
2121 const char *filename = NULL;
2122 const uint64_t bytes_per_sector = 512;
2123 uint32_t additional_flags = 0;
2124 struct smb_filename smb_fname;
2126 NTSTATUS status = NT_STATUS_OK;
2130 if (fname == NULL || fname->base_name == NULL) {
2133 filename = fname->base_name;
2137 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2138 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
2139 "info level (0x%x) on IPC$.\n",
2140 (unsigned int)info_level));
2141 return NT_STATUS_ACCESS_DENIED;
2145 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
2147 smb_fname = (struct smb_filename) {
2148 .base_name = discard_const_p(char, filename),
2149 .flags = fname ? fname->flags : 0,
2150 .twrp = fname ? fname->twrp : 0,
2153 if(info_level != SMB_FS_QUOTA_INFORMATION
2154 && SMB_VFS_STAT(conn, &smb_fname) != 0) {
2155 DEBUG(2,("stat of . failed (%s)\n", strerror(errno)));
2156 return map_nt_error_from_unix(errno);
2161 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
2162 return NT_STATUS_INVALID_PARAMETER;
2165 *ppdata = (char *)SMB_REALLOC(
2166 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2167 if (*ppdata == NULL) {
2168 return NT_STATUS_NO_MEMORY;
2172 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2173 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2177 switch (info_level) {
2178 case SMB_INFO_ALLOCATION:
2180 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
2182 df_ret = get_dfree_info(conn, &smb_fname, &bsize,
2184 if (df_ret == (uint64_t)-1) {
2185 return map_nt_error_from_unix(errno);
2188 block_size = lp_block_size(snum);
2189 if (bsize < block_size) {
2190 uint64_t factor = block_size/bsize;
2195 if (bsize > block_size) {
2196 uint64_t factor = bsize/block_size;
2201 sectors_per_unit = bsize/bytes_per_sector;
2203 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2204 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2205 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2208 * For large drives, return max values and not modulo.
2210 dsize = MIN(dsize, UINT32_MAX);
2211 dfree = MIN(dfree, UINT32_MAX);
2213 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
2214 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2215 SIVAL(pdata,l1_cUnit,dsize);
2216 SIVAL(pdata,l1_cUnitAvail,dfree);
2217 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2221 case SMB_INFO_VOLUME:
2222 /* Return volume name */
2224 * Add volume serial number - hash of a combination of
2225 * the called hostname and the service name.
2227 serial = generate_volume_serial_number(lp_sub, snum);
2228 SIVAL(pdata,0,serial);
2230 * Win2k3 and previous mess this up by sending a name length
2231 * one byte short. I believe only older clients (OS/2 Win9x) use
2232 * this call so try fixing this by adding a terminating null to
2233 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2235 status = srvstr_push(
2237 pdata+l2_vol_szVolLabel, vname,
2238 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
2239 STR_NOALIGN|STR_TERMINATE, &len);
2240 if (!NT_STATUS_IS_OK(status)) {
2243 SCVAL(pdata,l2_vol_cch,len);
2244 data_len = l2_vol_szVolLabel + len;
2245 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %u, "
2246 "name = %s serial = 0x%04"PRIx32"\n",
2247 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
2248 (unsigned)len, vname, serial));
2251 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2252 case SMB_FS_ATTRIBUTE_INFORMATION:
2254 additional_flags = 0;
2255 #if defined(HAVE_SYS_QUOTAS)
2256 additional_flags |= FILE_VOLUME_QUOTAS;
2259 if(lp_nt_acl_support(SNUM(conn))) {
2260 additional_flags |= FILE_PERSISTENT_ACLS;
2263 /* Capabilities are filled in at connection time through STATVFS call */
2264 additional_flags |= conn->fs_capabilities;
2265 additional_flags |= lp_parm_int(conn->params->service,
2266 "share", "fake_fscaps",
2269 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2270 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
2271 additional_flags); /* FS ATTRIBUTES */
2273 SIVAL(pdata,4,255); /* Max filename component length */
2274 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2275 and will think we can't do long filenames */
2276 status = srvstr_push(pdata, flags2, pdata+12, fstype,
2277 PTR_DIFF(end_data, pdata+12),
2279 if (!NT_STATUS_IS_OK(status)) {
2283 data_len = 12 + len;
2284 if (max_data_bytes >= 16 && data_len > max_data_bytes) {
2285 /* the client only requested a portion of the
2287 data_len = max_data_bytes;
2288 status = STATUS_BUFFER_OVERFLOW;
2290 *fixed_portion = 16;
2293 case SMB_QUERY_FS_LABEL_INFO:
2294 case SMB_FS_LABEL_INFORMATION:
2295 status = srvstr_push(pdata, flags2, pdata+4, vname,
2296 PTR_DIFF(end_data, pdata+4), 0, &len);
2297 if (!NT_STATUS_IS_OK(status)) {
2304 case SMB_QUERY_FS_VOLUME_INFO:
2305 case SMB_FS_VOLUME_INFORMATION:
2306 put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER,
2307 pdata, &st.st_ex_btime);
2309 * Add volume serial number - hash of a combination of
2310 * the called hostname and the service name.
2312 serial = generate_volume_serial_number(lp_sub, snum);
2313 SIVAL(pdata,8,serial);
2315 /* Max label len is 32 characters. */
2316 status = srvstr_push(pdata, flags2, pdata+18, vname,
2317 PTR_DIFF(end_data, pdata+18),
2319 if (!NT_STATUS_IS_OK(status)) {
2322 SIVAL(pdata,12,len);
2325 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO "
2326 "namelen = %d, vol=%s serv=%s "
2327 "serial=0x%04"PRIx32"\n",
2328 (int)strlen(vname),vname,
2329 lp_servicename(talloc_tos(), lp_sub, snum),
2331 if (max_data_bytes >= 24 && data_len > max_data_bytes) {
2332 /* the client only requested a portion of the
2334 data_len = max_data_bytes;
2335 status = STATUS_BUFFER_OVERFLOW;
2337 *fixed_portion = 24;
2340 case SMB_QUERY_FS_SIZE_INFO:
2341 case SMB_FS_SIZE_INFORMATION:
2343 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
2345 df_ret = get_dfree_info(conn, &smb_fname, &bsize,
2347 if (df_ret == (uint64_t)-1) {
2348 return map_nt_error_from_unix(errno);
2350 block_size = lp_block_size(snum);
2351 if (bsize < block_size) {
2352 uint64_t factor = block_size/bsize;
2357 if (bsize > block_size) {
2358 uint64_t factor = bsize/block_size;
2363 sectors_per_unit = bsize/bytes_per_sector;
2364 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2365 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2366 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2367 SBIG_UINT(pdata,0,dsize);
2368 SBIG_UINT(pdata,8,dfree);
2369 SIVAL(pdata,16,sectors_per_unit);
2370 SIVAL(pdata,20,bytes_per_sector);
2371 *fixed_portion = 24;
2375 case SMB_FS_FULL_SIZE_INFORMATION:
2377 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
2379 df_ret = get_dfree_info(conn, &smb_fname, &bsize,
2381 if (df_ret == (uint64_t)-1) {
2382 return map_nt_error_from_unix(errno);
2384 block_size = lp_block_size(snum);
2385 if (bsize < block_size) {
2386 uint64_t factor = block_size/bsize;
2391 if (bsize > block_size) {
2392 uint64_t factor = bsize/block_size;
2397 sectors_per_unit = bsize/bytes_per_sector;
2398 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2399 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2400 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2401 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2402 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2403 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2404 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2405 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2406 *fixed_portion = 32;
2410 case SMB_QUERY_FS_DEVICE_INFO:
2411 case SMB_FS_DEVICE_INFORMATION:
2413 uint32_t characteristics = FILE_DEVICE_IS_MOUNTED;
2415 if (!CAN_WRITE(conn)) {
2416 characteristics |= FILE_READ_ONLY_DEVICE;
2419 SIVAL(pdata,0,FILE_DEVICE_DISK); /* dev type */
2420 SIVAL(pdata,4,characteristics);
2425 #ifdef HAVE_SYS_QUOTAS
2426 case SMB_FS_QUOTA_INFORMATION:
2428 * what we have to send --metze:
2430 * Unknown1: 24 NULL bytes
2431 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
2432 * Hard Quota Limit: 8 bytes seems like uint64_t or so
2433 * Quota Flags: 2 byte :
2434 * Unknown3: 6 NULL bytes
2438 * details for Quota Flags:
2440 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2441 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2442 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2443 * 0x0001 Enable Quotas: enable quota for this fs
2447 /* we need to fake up a fsp here,
2448 * because its not send in this call
2451 SMB_NTQUOTA_STRUCT quotas;
2454 ZERO_STRUCT(quotas);
2457 fsp.fnum = FNUM_FIELD_INVALID;
2460 if (get_current_uid(conn) != 0) {
2461 DEBUG(0,("get_user_quota: access_denied "
2462 "service [%s] user [%s]\n",
2463 lp_servicename(talloc_tos(), lp_sub, SNUM(conn)),
2464 conn->session_info->unix_info->unix_name));
2465 return NT_STATUS_ACCESS_DENIED;
2468 status = vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE,
2470 if (!NT_STATUS_IS_OK(status)) {
2471 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), lp_sub, SNUM(conn))));
2477 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
2478 lp_servicename(talloc_tos(), lp_sub, SNUM(conn))));
2480 /* Unknown1 24 NULL bytes*/
2481 SBIG_UINT(pdata,0,(uint64_t)0);
2482 SBIG_UINT(pdata,8,(uint64_t)0);
2483 SBIG_UINT(pdata,16,(uint64_t)0);
2485 /* Default Soft Quota 8 bytes */
2486 SBIG_UINT(pdata,24,quotas.softlim);
2488 /* Default Hard Quota 8 bytes */
2489 SBIG_UINT(pdata,32,quotas.hardlim);
2491 /* Quota flag 2 bytes */
2492 SSVAL(pdata,40,quotas.qflags);
2494 /* Unknown3 6 NULL bytes */
2500 #endif /* HAVE_SYS_QUOTAS */
2501 case SMB_FS_OBJECTID_INFORMATION:
2503 unsigned char objid[16];
2504 struct smb_extended_info extended_info;
2505 memcpy(pdata,create_volume_objectid(conn, objid),16);
2506 samba_extended_info_version (&extended_info);
2507 SIVAL(pdata,16,extended_info.samba_magic);
2508 SIVAL(pdata,20,extended_info.samba_version);
2509 SIVAL(pdata,24,extended_info.samba_subversion);
2510 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
2511 memcpy(pdata+36,extended_info.samba_version_string,28);
2516 case SMB_FS_SECTOR_SIZE_INFORMATION:
2520 * These values match a physical Windows Server 2012
2521 * share backed by NTFS atop spinning rust.
2523 DEBUG(5, ("SMB_FS_SECTOR_SIZE_INFORMATION:"));
2524 /* logical_bytes_per_sector */
2525 SIVAL(pdata, 0, bytes_per_sector);
2526 /* phys_bytes_per_sector_atomic */
2527 SIVAL(pdata, 4, bytes_per_sector);
2528 /* phys_bytes_per_sector_perf */
2529 SIVAL(pdata, 8, bytes_per_sector);
2530 /* fs_effective_phys_bytes_per_sector_atomic */
2531 SIVAL(pdata, 12, bytes_per_sector);
2533 SIVAL(pdata, 16, SSINFO_FLAGS_ALIGNED_DEVICE
2534 | SSINFO_FLAGS_PARTITION_ALIGNED_ON_DEVICE);
2535 /* byte_off_sector_align */
2536 SIVAL(pdata, 20, 0);
2537 /* byte_off_partition_align */
2538 SIVAL(pdata, 24, 0);
2539 *fixed_portion = 28;
2544 #if defined(WITH_SMB1SERVER)
2546 * Query the version and capabilities of the CIFS UNIX extensions
2550 case SMB_QUERY_CIFS_UNIX_INFO:
2552 bool large_write = lp_min_receive_file_size() &&
2553 !smb1_srv_is_signing_active(xconn);
2554 bool large_read = !smb1_srv_is_signing_active(xconn);
2555 int encrypt_caps = 0;
2557 if (!lp_smb1_unix_extensions()) {
2558 return NT_STATUS_INVALID_LEVEL;
2561 switch (conn->encrypt_level) {
2562 case SMB_SIGNING_OFF:
2565 case SMB_SIGNING_DESIRED:
2566 case SMB_SIGNING_IF_REQUIRED:
2567 case SMB_SIGNING_DEFAULT:
2568 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
2570 case SMB_SIGNING_REQUIRED:
2571 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
2572 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
2573 large_write = false;
2579 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2580 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2582 /* We have POSIX ACLs, pathname, encryption,
2583 * large read/write, and locking capability. */
2585 SBIG_UINT(pdata,4,((uint64_t)(
2586 CIFS_UNIX_POSIX_ACLS_CAP|
2587 CIFS_UNIX_POSIX_PATHNAMES_CAP|
2588 CIFS_UNIX_FCNTL_LOCKS_CAP|
2589 CIFS_UNIX_EXTATTR_CAP|
2590 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
2592 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
2594 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
2599 case SMB_QUERY_POSIX_FS_INFO:
2602 struct vfs_statvfs_struct svfs;
2604 if (!lp_smb1_unix_extensions()) {
2605 return NT_STATUS_INVALID_LEVEL;
2608 rc = SMB_VFS_STATVFS(conn, &smb_fname, &svfs);
2612 SIVAL(pdata,0,svfs.OptimalTransferSize);
2613 SIVAL(pdata,4,svfs.BlockSize);
2614 SBIG_UINT(pdata,8,svfs.TotalBlocks);
2615 SBIG_UINT(pdata,16,svfs.BlocksAvail);
2616 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
2617 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
2618 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
2619 SBIG_UINT(pdata,48,svfs.FsIdentifier);
2620 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
2622 } else if (rc == EOPNOTSUPP) {
2623 return NT_STATUS_INVALID_LEVEL;
2624 #endif /* EOPNOTSUPP */
2626 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(talloc_tos(), lp_sub, SNUM(conn))));
2627 return NT_STATUS_DOS(ERRSRV, ERRerror);
2632 case SMB_QUERY_POSIX_WHOAMI:
2638 if (!lp_smb1_unix_extensions()) {
2639 return NT_STATUS_INVALID_LEVEL;
2642 if (max_data_bytes < 40) {
2643 return NT_STATUS_BUFFER_TOO_SMALL;
2646 if (security_session_user_level(conn->session_info, NULL) < SECURITY_USER) {
2647 flags |= SMB_WHOAMI_GUEST;
2650 /* NOTE: 8 bytes for UID/GID, irrespective of native
2651 * platform size. This matches
2652 * SMB_QUERY_FILE_UNIX_BASIC and friends.
2654 data_len = 4 /* flags */
2661 + 4 /* pad/reserved */
2662 + (conn->session_info->unix_token->ngroups * 8)
2664 + (conn->session_info->security_token->num_sids *
2668 SIVAL(pdata, 0, flags);
2669 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
2671 (uint64_t)conn->session_info->unix_token->uid);
2672 SBIG_UINT(pdata, 16,
2673 (uint64_t)conn->session_info->unix_token->gid);
2676 if (data_len >= max_data_bytes) {
2677 /* Potential overflow, skip the GIDs and SIDs. */
2679 SIVAL(pdata, 24, 0); /* num_groups */
2680 SIVAL(pdata, 28, 0); /* num_sids */
2681 SIVAL(pdata, 32, 0); /* num_sid_bytes */
2682 SIVAL(pdata, 36, 0); /* reserved */
2688 SIVAL(pdata, 24, conn->session_info->unix_token->ngroups);
2689 SIVAL(pdata, 28, conn->session_info->security_token->num_sids);
2691 /* We walk the SID list twice, but this call is fairly
2692 * infrequent, and I don't expect that it's performance
2693 * sensitive -- jpeach
2695 for (i = 0, sid_bytes = 0;
2696 i < conn->session_info->security_token->num_sids; ++i) {
2697 sid_bytes += ndr_size_dom_sid(
2698 &conn->session_info->security_token->sids[i],
2702 /* SID list byte count */
2703 SIVAL(pdata, 32, sid_bytes);
2705 /* 4 bytes pad/reserved - must be zero */
2706 SIVAL(pdata, 36, 0);
2710 for (i = 0; i < conn->session_info->unix_token->ngroups; ++i) {
2711 SBIG_UINT(pdata, data_len,
2712 (uint64_t)conn->session_info->unix_token->groups[i]);
2718 i < conn->session_info->security_token->num_sids; ++i) {
2719 int sid_len = ndr_size_dom_sid(
2720 &conn->session_info->security_token->sids[i],
2723 sid_linearize((uint8_t *)(pdata + data_len),
2725 &conn->session_info->security_token->sids[i]);
2726 data_len += sid_len;
2732 case SMB_MAC_QUERY_FS_INFO:
2734 * Thursby MAC extension... ONLY on NTFS filesystems
2735 * once we do streams then we don't need this
2737 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
2739 SIVAL(pdata,84,0x100); /* Don't support mac... */
2745 return NT_STATUS_INVALID_LEVEL;
2748 *ret_data_len = data_len;
2752 NTSTATUS smb_set_fsquota(connection_struct *conn,
2753 struct smb_request *req,
2755 const DATA_BLOB *qdata)
2757 const struct loadparm_substitution *lp_sub =
2758 loadparm_s3_global_substitution();
2760 SMB_NTQUOTA_STRUCT quotas;
2762 ZERO_STRUCT(quotas);
2765 if ((get_current_uid(conn) != 0) || !CAN_WRITE(conn)) {
2766 DEBUG(3, ("set_fsquota: access_denied service [%s] user [%s]\n",
2767 lp_servicename(talloc_tos(), lp_sub, SNUM(conn)),
2768 conn->session_info->unix_info->unix_name));
2769 return NT_STATUS_ACCESS_DENIED;
2772 if (!check_fsp_ntquota_handle(conn, req,
2774 DEBUG(1, ("set_fsquota: no valid QUOTA HANDLE\n"));
2775 return NT_STATUS_INVALID_HANDLE;
2778 /* note: normally there're 48 bytes,
2779 * but we didn't use the last 6 bytes for now
2782 if (qdata->length < 42) {
2783 DEBUG(0,("set_fsquota: requires total_data(%u) >= 42 bytes!\n",
2784 (unsigned int)qdata->length));
2785 return NT_STATUS_INVALID_PARAMETER;
2788 /* unknown_1 24 NULL bytes in pdata*/
2790 /* the soft quotas 8 bytes (uint64_t)*/
2791 quotas.softlim = BVAL(qdata->data,24);
2793 /* the hard quotas 8 bytes (uint64_t)*/
2794 quotas.hardlim = BVAL(qdata->data,32);
2796 /* quota_flags 2 bytes **/
2797 quotas.qflags = SVAL(qdata->data,40);
2799 /* unknown_2 6 NULL bytes follow*/
2801 /* now set the quotas */
2802 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
2803 DEBUG(1, ("vfs_set_ntquota() failed for service [%s]\n",
2804 lp_servicename(talloc_tos(), lp_sub, SNUM(conn))));
2805 status = map_nt_error_from_unix(errno);
2807 status = NT_STATUS_OK;
2812 NTSTATUS smbd_do_setfsinfo(connection_struct *conn,
2813 struct smb_request *req,
2814 TALLOC_CTX *mem_ctx,
2815 uint16_t info_level,
2817 const DATA_BLOB *pdata)
2819 switch (info_level) {
2820 case SMB_FS_QUOTA_INFORMATION:
2822 return smb_set_fsquota(conn,
2831 return NT_STATUS_INVALID_LEVEL;
2834 #if defined(HAVE_POSIX_ACLS)
2835 /****************************************************************************
2836 Utility function to count the number of entries in a POSIX acl.
2837 ****************************************************************************/
2839 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
2841 unsigned int ace_count = 0;
2842 int entry_id = SMB_ACL_FIRST_ENTRY;
2843 SMB_ACL_ENTRY_T entry;
2845 while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
2847 if (entry_id == SMB_ACL_FIRST_ENTRY) {
2848 entry_id = SMB_ACL_NEXT_ENTRY;
2855 /****************************************************************************
2856 Utility function to marshall a POSIX acl into wire format.
2857 ****************************************************************************/
2859 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
2861 int entry_id = SMB_ACL_FIRST_ENTRY;
2862 SMB_ACL_ENTRY_T entry;
2864 while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
2865 SMB_ACL_TAG_T tagtype;
2866 SMB_ACL_PERMSET_T permset;
2867 unsigned char perms = 0;
2868 unsigned int own_grp;
2871 if (entry_id == SMB_ACL_FIRST_ENTRY) {
2872 entry_id = SMB_ACL_NEXT_ENTRY;
2875 if (sys_acl_get_tag_type(entry, &tagtype) == -1) {
2876 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
2880 if (sys_acl_get_permset(entry, &permset) == -1) {
2881 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
2885 perms |= (sys_acl_get_perm(permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
2886 perms |= (sys_acl_get_perm(permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
2887 perms |= (sys_acl_get_perm(permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
2889 SCVAL(pdata,1,perms);
2892 case SMB_ACL_USER_OBJ:
2893 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
2894 own_grp = (unsigned int)pst->st_ex_uid;
2895 SIVAL(pdata,2,own_grp);
2900 uid_t *puid = (uid_t *)sys_acl_get_qualifier(entry);
2902 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
2905 own_grp = (unsigned int)*puid;
2906 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
2907 SIVAL(pdata,2,own_grp);
2911 case SMB_ACL_GROUP_OBJ:
2912 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
2913 own_grp = (unsigned int)pst->st_ex_gid;
2914 SIVAL(pdata,2,own_grp);
2919 gid_t *pgid= (gid_t *)sys_acl_get_qualifier(entry);
2921 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
2924 own_grp = (unsigned int)*pgid;
2925 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
2926 SIVAL(pdata,2,own_grp);
2931 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
2932 SIVAL(pdata,2,0xFFFFFFFF);
2933 SIVAL(pdata,6,0xFFFFFFFF);
2936 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
2937 SIVAL(pdata,2,0xFFFFFFFF);
2938 SIVAL(pdata,6,0xFFFFFFFF);
2941 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
2944 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
2951 /****************************************************************************
2952 Store the FILE_UNIX_BASIC info.
2953 ****************************************************************************/
2955 static char *store_file_unix_basic(connection_struct *conn,
2958 const SMB_STRUCT_STAT *psbuf)
2962 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
2963 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
2965 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
2968 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
2971 put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata, &psbuf->st_ex_ctime); /* Change Time 64 Bit */
2972 put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER ,pdata+8, &psbuf->st_ex_atime); /* Last access time 64 Bit */
2973 put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+16, &psbuf->st_ex_mtime); /* Last modification time 64 Bit */
2976 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
2980 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
2984 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
2987 if (S_ISBLK(psbuf->st_ex_mode) || S_ISCHR(psbuf->st_ex_mode)) {
2988 devno = psbuf->st_ex_rdev;
2990 devno = psbuf->st_ex_dev;
2993 SIVAL(pdata,0,unix_dev_major(devno)); /* Major device number if type is device */
2997 SIVAL(pdata,0,unix_dev_minor(devno)); /* Minor device number if type is device */
3001 SINO_T_VAL(pdata, 0, psbuf->st_ex_ino); /* inode number */
3004 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
3008 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
3015 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3016 * the chflags(2) (or equivalent) flags.
3018 * XXX: this really should be behind the VFS interface. To do this, we would
3019 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3020 * Each VFS module could then implement its own mapping as appropriate for the
3021 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3023 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
3027 { UF_NODUMP, EXT_DO_NOT_BACKUP },
3031 { UF_IMMUTABLE, EXT_IMMUTABLE },
3035 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
3039 { UF_HIDDEN, EXT_HIDDEN },
3042 /* Do not remove. We need to guarantee that this array has at least one
3043 * entry to build on HP-UX.
3049 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
3050 uint32_t *smb_fflags, uint32_t *smb_fmask)
3054 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3055 *smb_fmask |= info2_flags_map[i].smb_fflag;
3056 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
3057 *smb_fflags |= info2_flags_map[i].smb_fflag;
3062 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
3063 const uint32_t smb_fflags,
3064 const uint32_t smb_fmask,
3067 uint32_t max_fmask = 0;
3070 *stat_fflags = psbuf->st_ex_flags;
3072 /* For each flags requested in smb_fmask, check the state of the
3073 * corresponding flag in smb_fflags and set or clear the matching
3077 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3078 max_fmask |= info2_flags_map[i].smb_fflag;
3079 if (smb_fmask & info2_flags_map[i].smb_fflag) {
3080 if (smb_fflags & info2_flags_map[i].smb_fflag) {
3081 *stat_fflags |= info2_flags_map[i].stat_fflag;
3083 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
3088 /* If smb_fmask is asking to set any bits that are not supported by
3089 * our flag mappings, we should fail.
3091 if ((smb_fmask & max_fmask) != smb_fmask) {
3099 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
3100 * of file flags and birth (create) time.
3102 static char *store_file_unix_basic_info2(connection_struct *conn,
3105 const SMB_STRUCT_STAT *psbuf)
3107 uint32_t file_flags = 0;
3108 uint32_t flags_mask = 0;
3110 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
3112 /* Create (birth) time 64 bit */
3113 put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER,pdata, &psbuf->st_ex_btime);
3116 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
3117 SIVAL(pdata, 0, file_flags); /* flags */
3118 SIVAL(pdata, 4, flags_mask); /* mask */
3124 static NTSTATUS marshall_stream_info(unsigned int num_streams,
3125 const struct stream_struct *streams,
3127 unsigned int max_data_bytes,
3128 unsigned int *data_size)
3131 unsigned int ofs = 0;
3133 if (max_data_bytes < 32) {
3134 return NT_STATUS_INFO_LENGTH_MISMATCH;
3137 for (i = 0; i < num_streams; i++) {
3138 unsigned int next_offset;
3140 smb_ucs2_t *namebuf;
3142 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
3143 streams[i].name, &namelen) ||
3146 return NT_STATUS_INVALID_PARAMETER;
3150 * name_buf is now null-terminated, we need to marshall as not
3157 * We cannot overflow ...
3159 if ((ofs + 24 + namelen) > max_data_bytes) {
3160 DEBUG(10, ("refusing to overflow reply at stream %u\n",
3162 TALLOC_FREE(namebuf);
3163 return STATUS_BUFFER_OVERFLOW;
3166 SIVAL(data, ofs+4, namelen);
3167 SOFF_T(data, ofs+8, streams[i].size);
3168 SOFF_T(data, ofs+16, streams[i].alloc_size);
3169 memcpy(data+ofs+24, namebuf, namelen);
3170 TALLOC_FREE(namebuf);
3172 next_offset = ofs + 24 + namelen;
3174 if (i == num_streams-1) {
3175 SIVAL(data, ofs, 0);
3178 unsigned int align = ndr_align_size(next_offset, 8);
3180 if ((next_offset + align) > max_data_bytes) {
3181 DEBUG(10, ("refusing to overflow align "
3182 "reply at stream %u\n",
3184 TALLOC_FREE(namebuf);
3185 return STATUS_BUFFER_OVERFLOW;
3188 memset(data+next_offset, 0, align);
3189 next_offset += align;
3191 SIVAL(data, ofs, next_offset - ofs);
3198 DEBUG(10, ("max_data: %u, data_size: %u\n", max_data_bytes, ofs));
3202 return NT_STATUS_OK;
3205 static NTSTATUS smb_unix_read_symlink(connection_struct *conn,
3206 struct smb_request *req,
3207 struct smb_filename *smb_fname,
3209 unsigned int data_size_in,
3210 unsigned int *pdata_size_out)
3215 struct smb_filename *parent_fname = NULL;
3216 struct smb_filename *base_name = NULL;
3218 char *buffer = talloc_array(talloc_tos(), char, PATH_MAX+1);
3221 return NT_STATUS_NO_MEMORY;
3224 DBG_DEBUG("SMB_QUERY_FILE_UNIX_LINK for file %s\n",
3225 smb_fname_str_dbg(smb_fname));
3227 if(!S_ISLNK(smb_fname->st.st_ex_mode)) {
3228 TALLOC_FREE(buffer);
3229 return NT_STATUS_DOS(ERRSRV, ERRbadlink);
3232 status = parent_pathref(talloc_tos(),
3237 if (!NT_STATUS_IS_OK(status)) {
3238 TALLOC_FREE(buffer);
3242 link_len = SMB_VFS_READLINKAT(conn,
3248 TALLOC_FREE(parent_fname);
3250 if (link_len == -1) {
3251 TALLOC_FREE(buffer);
3252 return map_nt_error_from_unix(errno);
3255 buffer[link_len] = 0;
3256 status = srvstr_push(pdata,
3263 TALLOC_FREE(buffer);
3264 if (!NT_STATUS_IS_OK(status)) {
3267 *pdata_size_out = len;
3269 return NT_STATUS_OK;
3272 #if defined(HAVE_POSIX_ACLS)
3273 static NTSTATUS smb_query_posix_acl(connection_struct *conn,
3274 struct smb_request *req,
3276 struct smb_filename *smb_fname,
3278 unsigned int data_size_in,
3279 unsigned int *pdata_size_out)
3281 SMB_ACL_T file_acl = NULL;
3282 SMB_ACL_T def_acl = NULL;
3283 uint16_t num_file_acls = 0;
3284 uint16_t num_def_acls = 0;
3285 unsigned int size_needed = 0;
3288 bool close_fsp = false;
3291 * Ensure we always operate on a file descriptor, not just
3294 if (fsp == NULL || !fsp->fsp_flags.is_fsa) {
3295 uint32_t access_mask = SEC_STD_READ_CONTROL|
3296 FILE_READ_ATTRIBUTES|
3297 FILE_WRITE_ATTRIBUTES;
3299 status = get_posix_fsp(conn,
3305 if (!NT_STATUS_IS_OK(status)) {
3311 SMB_ASSERT(fsp != NULL);
3313 status = refuse_symlink_fsp(fsp);
3314 if (!NT_STATUS_IS_OK(status)) {
3318 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp, SMB_ACL_TYPE_ACCESS,
3321 if (file_acl == NULL && no_acl_syscall_error(errno)) {
3322 DBG_INFO("ACLs not implemented on "
3323 "filesystem containing %s\n",
3325 status = NT_STATUS_NOT_IMPLEMENTED;
3329 if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
3331 * We can only have default POSIX ACLs on
3334 if (!fsp->fsp_flags.is_directory) {
3335 DBG_INFO("Non-directory open %s\n",
3337 status = NT_STATUS_INVALID_HANDLE;
3340 def_acl = SMB_VFS_SYS_ACL_GET_FD(fsp,
3341 SMB_ACL_TYPE_DEFAULT,
3343 def_acl = free_empty_sys_acl(conn, def_acl);
3346 num_file_acls = count_acl_entries(conn, file_acl);
3347 num_def_acls = count_acl_entries(conn, def_acl);
3350 if (num_file_acls + num_def_acls < num_file_acls) {
3351 status = NT_STATUS_INVALID_PARAMETER;
3355 size_needed = num_file_acls + num_def_acls;
3358 * (size_needed * SMB_POSIX_ACL_ENTRY_SIZE) must be less
3359 * than UINT_MAX, so check by division.
3361 if (size_needed > (UINT_MAX/SMB_POSIX_ACL_ENTRY_SIZE)) {
3362 status = NT_STATUS_INVALID_PARAMETER;
3366 size_needed = size_needed*SMB_POSIX_ACL_ENTRY_SIZE;
3367 if (size_needed + SMB_POSIX_ACL_HEADER_SIZE < size_needed) {
3368 status = NT_STATUS_INVALID_PARAMETER;
3371 size_needed += SMB_POSIX_ACL_HEADER_SIZE;
3373 if ( data_size_in < size_needed) {
3374 DBG_INFO("data_size too small (%u) need %u\n",
3377 status = NT_STATUS_BUFFER_TOO_SMALL;
3381 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
3382 SSVAL(pdata,2,num_file_acls);
3383 SSVAL(pdata,4,num_def_acls);
3384 pdata += SMB_POSIX_ACL_HEADER_SIZE;
3386 ok = marshall_posix_acl(conn,
3391 status = NT_STATUS_INTERNAL_ERROR;
3394 pdata += (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE);
3396 ok = marshall_posix_acl(conn,
3401 status = NT_STATUS_INTERNAL_ERROR;
3405 *pdata_size_out = size_needed;
3406 status = NT_STATUS_OK;
3412 * Ensure the stat struct in smb_fname is up to
3413 * date. Structure copy.
3415 smb_fname->st = fsp->fsp_name->st;
3416 (void)close_file_free(req, &fsp, NORMAL_CLOSE);
3419 TALLOC_FREE(file_acl);
3420 TALLOC_FREE(def_acl);
3425 NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
3426 TALLOC_CTX *mem_ctx,
3427 struct smb_request *req,
3428 uint16_t info_level,
3430 struct smb_filename *smb_fname,
3431 bool delete_pending,
3432 struct timespec write_time_ts,
3433 struct ea_list *ea_list,
3434 int lock_data_count,
3437 unsigned int max_data_bytes,
3438 size_t *fixed_portion,
3440 unsigned int *pdata_size)
3442 char *pdata = *ppdata;
3443 char *dstart, *dend;
3444 unsigned int data_size;
3445 struct timespec create_time_ts, mtime_ts, atime_ts, ctime_ts;
3446 time_t create_time, mtime, atime, c_time;
3447 SMB_STRUCT_STAT *psbuf = NULL;
3448 SMB_STRUCT_STAT *base_sp = NULL;
3455 uint64_t file_size = 0;
3457 uint64_t allocation_size = 0;
3458 uint64_t file_id = 0;
3459 uint32_t access_mask = 0;
3462 if (INFO_LEVEL_IS_UNIX(info_level)) {
3463 if (!lp_smb1_unix_extensions()) {
3464 return NT_STATUS_INVALID_LEVEL;
3466 if (!req->posix_pathnames) {
3467 return NT_STATUS_INVALID_LEVEL;
3471 DEBUG(5,("smbd_do_qfilepathinfo: %s (%s) level=%d max_data=%u\n",
3472 smb_fname_str_dbg(smb_fname),
3474 info_level, max_data_bytes));
3477 * In case of querying a symlink in POSIX context,
3478 * fsp will be NULL. fdos_mode() deals with it.
3481 smb_fname = fsp->fsp_name;
3483 mode = fdos_mode(fsp);
3484 psbuf = &smb_fname->st;
3487 base_sp = fsp->base_fsp ?
3488 &fsp->base_fsp->fsp_name->st :
3491 base_sp = &smb_fname->st;
3494 nlink = psbuf->st_ex_nlink;
3496 if (nlink && (mode&FILE_ATTRIBUTE_DIRECTORY)) {
3500 if ((nlink > 0) && delete_pending) {
3504 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
3505 return NT_STATUS_INVALID_PARAMETER;
3508 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3509 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
3510 if (*ppdata == NULL) {
3511 return NT_STATUS_NO_MEMORY;
3515 dend = dstart + data_size - 1;
3517 if (!is_omit_timespec(&write_time_ts) &&
3518 !INFO_LEVEL_IS_UNIX(info_level))
3520 update_stat_ex_mtime(psbuf, write_time_ts);
3523 create_time_ts = get_create_timespec(conn, fsp, smb_fname);
3524 mtime_ts = psbuf->st_ex_mtime;
3525 atime_ts = psbuf->st_ex_atime;
3526 ctime_ts = get_change_timespec(conn, fsp, smb_fname);
3528 if (lp_dos_filetime_resolution(SNUM(conn))) {
3529 dos_filetime_timespec(&create_time_ts);
3530 dos_filetime_timespec(&mtime_ts);
3531 dos_filetime_timespec(&atime_ts);
3532 dos_filetime_timespec(&ctime_ts);
3535 create_time = convert_timespec_to_time_t(create_time_ts);
3536 mtime = convert_timespec_to_time_t(mtime_ts);
3537 atime = convert_timespec_to_time_t(atime_ts);
3538 c_time = convert_timespec_to_time_t(ctime_ts);
3540 p = strrchr_m(smb_fname->base_name,'/');
3542 base_name = smb_fname->base_name;
3546 /* NT expects the name to be in an exact form of the *full*
3547 filename. See the trans2 torture test */
3548 if (ISDOT(base_name)) {
3549 dos_fname = talloc_strdup(mem_ctx, "\\");
3551 return NT_STATUS_NO_MEMORY;
3554 dos_fname = talloc_asprintf(mem_ctx,
3556 smb_fname->base_name);
3558 return NT_STATUS_NO_MEMORY;
3560 if (is_named_stream(smb_fname)) {
3561 dos_fname = talloc_asprintf(dos_fname, "%s",
3562 smb_fname->stream_name);
3564 return NT_STATUS_NO_MEMORY;
3568 string_replace(dos_fname, '/', '\\');
3571 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, psbuf);
3573 if (fsp == NULL || !fsp->fsp_flags.is_fsa) {
3574 /* Do we have this path open ? */
3576 struct file_id fileid = vfs_file_id_from_sbuf(conn, psbuf);
3577 fsp1 = file_find_di_first(conn->sconn, fileid, true);
3578 if (fsp1 && fsp1->initial_allocation_size) {
3579 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, psbuf);
3583 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
3584 file_size = get_file_size_stat(psbuf);
3588 pos = fh_get_position_information(fsp->fh);
3592 access_mask = fsp->access_mask;
3594 /* GENERIC_EXECUTE mapping from Windows */
3595 access_mask = 0x12019F;
3598 /* This should be an index number - looks like
3601 I think this causes us to fail the IFSKIT
3602 BasicFileInformationTest. -tpot */
3603 file_id = SMB_VFS_FS_FILE_ID(conn, base_sp);
3607 switch (info_level) {
3608 case SMB_INFO_STANDARD:
3609 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
3611 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
3612 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
3613 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
3614 SIVAL(pdata,l1_cbFile,(uint32_t)file_size);
3615 SIVAL(pdata,l1_cbFileAlloc,(uint32_t)allocation_size);
3616 SSVAL(pdata,l1_attrFile,mode);
3619 case SMB_INFO_QUERY_EA_SIZE:
3621 unsigned int ea_size =
3622 estimate_ea_size(smb_fname->fsp);
3623 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
3625 srv_put_dos_date2(pdata,0,create_time);
3626 srv_put_dos_date2(pdata,4,atime);
3627 srv_put_dos_date2(pdata,8,mtime); /* write time */
3628 SIVAL(pdata,12,(uint32_t)file_size);
3629 SIVAL(pdata,16,(uint32_t)allocation_size);
3630 SSVAL(pdata,20,mode);
3631 SIVAL(pdata,22,ea_size);
3635 case SMB_INFO_IS_NAME_VALID:
3636 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
3638 /* os/2 needs this ? really ?*/
3639 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
3641 /* This is only reached for qpathinfo */
3645 case SMB_INFO_QUERY_EAS_FROM_LIST:
3647 size_t total_ea_len = 0;
3648 struct ea_list *ea_file_list = NULL;
3649 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
3652 get_ea_list_from_fsp(mem_ctx,
3654 &total_ea_len, &ea_file_list);
3655 if (!NT_STATUS_IS_OK(status)) {
3659 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
3661 if (!ea_list || (total_ea_len > data_size)) {
3663 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
3667 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
3671 case SMB_INFO_QUERY_ALL_EAS:
3673 /* We have data_size bytes to put EA's into. */
3674 size_t total_ea_len = 0;
3675 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
3677 status = get_ea_list_from_fsp(mem_ctx,
3679 &total_ea_len, &ea_list);
3680 if (!NT_STATUS_IS_OK(status)) {
3684 if (!ea_list || (total_ea_len > data_size)) {
3686 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
3690 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
3694 case SMB2_FILE_FULL_EA_INFORMATION:
3696 /* We have data_size bytes to put EA's into. */
3697 size_t total_ea_len = 0;
3698 struct ea_list *ea_file_list = NULL;
3700 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
3702 /*TODO: add filtering and index handling */
3705 get_ea_list_from_fsp(mem_ctx,
3707 &total_ea_len, &ea_file_list);
3708 if (!NT_STATUS_IS_OK(status)) {
3711 if (!ea_file_list) {
3712 return NT_STATUS_NO_EAS_ON_FILE;
3715 status = fill_ea_chained_buffer(mem_ctx,
3719 conn, ea_file_list);
3720 if (!NT_STATUS_IS_OK(status)) {
3726 case SMB_FILE_BASIC_INFORMATION:
3727 case SMB_QUERY_FILE_BASIC_INFO:
3729 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
3730 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
3731 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
3733 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
3737 put_long_date_full_timespec(conn->ts_res,pdata,&create_time_ts);
3738 put_long_date_full_timespec(conn->ts_res,pdata+8,&atime_ts);
3739 put_long_date_full_timespec(conn->ts_res,pdata+16,&mtime_ts); /* write time */
3740 put_long_date_full_timespec(conn->ts_res,pdata+24,&ctime_ts); /* change time */
3741 SIVAL(pdata,32,mode);
3743 DEBUG(5,("SMB_QFBI - "));
3744 DEBUG(5,("create: %s ", ctime(&create_time)));
3745 DEBUG(5,("access: %s ", ctime(&atime)));
3746 DEBUG(5,("write: %s ", ctime(&mtime)));
3747 DEBUG(5,("change: %s ", ctime(&c_time)));
3748 DEBUG(5,("mode: %x\n", mode));
3749 *fixed_portion = data_size;
3752 case SMB_FILE_STANDARD_INFORMATION:
3753 case SMB_QUERY_FILE_STANDARD_INFO:
3755 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
3757 SOFF_T(pdata,0,allocation_size);
3758 SOFF_T(pdata,8,file_size);
3759 SIVAL(pdata,16,nlink);
3760 SCVAL(pdata,20,delete_pending?1:0);
3761 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
3762 SSVAL(pdata,22,0); /* Padding. */
3763 *fixed_portion = 24;
3766 case SMB_FILE_EA_INFORMATION:
3767 case SMB_QUERY_FILE_EA_INFO:
3769 unsigned int ea_size =
3770 estimate_ea_size(smb_fname->fsp);
3771 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
3774 SIVAL(pdata,0,ea_size);
3778 /* Get the 8.3 name - used if NT SMB was negotiated. */
3779 case SMB_QUERY_FILE_ALT_NAME_INFO:
3780 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
3782 char mangled_name[13];
3783 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
3784 if (!name_to_8_3(base_name,mangled_name,
3785 True,conn->params)) {
3786 return NT_STATUS_NO_MEMORY;
3788 status = srvstr_push(dstart, flags2,
3789 pdata+4, mangled_name,
3790 PTR_DIFF(dend, pdata+4),
3792 if (!NT_STATUS_IS_OK(status)) {
3795 data_size = 4 + len;
3801 case SMB_QUERY_FILE_NAME_INFO:
3804 this must be *exactly* right for ACLs on mapped drives to work
3806 status = srvstr_push(dstart, flags2,
3808 PTR_DIFF(dend, pdata+4),
3810 if (!NT_STATUS_IS_OK(status)) {
3813 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
3814 data_size = 4 + len;
3819 case SMB_FILE_NORMALIZED_NAME_INFORMATION:
3821 char *nfname = NULL;
3823 if (fsp == NULL || !fsp->conn->sconn->using_smb2) {
3824 return NT_STATUS_INVALID_LEVEL;
3827 nfname = talloc_strdup(mem_ctx, smb_fname->base_name);
3828 if (nfname == NULL) {
3829 return NT_STATUS_NO_MEMORY;
3832 if (ISDOT(nfname)) {
3835 string_replace(nfname, '/', '\\');
3837 if (fsp_is_alternate_stream(fsp)) {
3838 const char *s = smb_fname->stream_name;
3839 const char *e = NULL;
3842 SMB_ASSERT(s[0] != '\0');
3845 * smb_fname->stream_name is in form
3846 * of ':StrEam:$DATA', but we should only
3847 * append ':StrEam' here.
3850 e = strchr(&s[1], ':');
3856 nfname = talloc_strndup_append(nfname, s, n);
3857 if (nfname == NULL) {
3858 return NT_STATUS_NO_MEMORY;
3862 status = srvstr_push(dstart, flags2,
3864 PTR_DIFF(dend, pdata+4),
3866 if (!NT_STATUS_IS_OK(status)) {
3869 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NORMALIZED_NAME_INFORMATION\n"));
3870 data_size = 4 + len;
3876 case SMB_FILE_ALLOCATION_INFORMATION:
3877 case SMB_QUERY_FILE_ALLOCATION_INFO:
3878 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
3880 SOFF_T(pdata,0,allocation_size);
3883 case SMB_FILE_END_OF_FILE_INFORMATION:
3884 case SMB_QUERY_FILE_END_OF_FILEINFO:
3885 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
3887 SOFF_T(pdata,0,file_size);
3890 case SMB_QUERY_FILE_ALL_INFO:
3891 case SMB_FILE_ALL_INFORMATION:
3893 unsigned int ea_size =
3894 estimate_ea_size(smb_fname->fsp);
3895 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
3896 put_long_date_full_timespec(conn->ts_res,pdata,&create_time_ts);
3897 put_long_date_full_timespec(conn->ts_res,pdata+8,&atime_ts);
3898 put_long_date_full_timespec(conn->ts_res,pdata+16,&mtime_ts); /* write time */
3899 put_long_date_full_timespec(conn->ts_res,pdata+24,&ctime_ts); /* change time */
3900 SIVAL(pdata,32,mode);
3901 SIVAL(pdata,36,0); /* padding. */
3903 SOFF_T(pdata,0,allocation_size);
3904 SOFF_T(pdata,8,file_size);
3905 SIVAL(pdata,16,nlink);
3906 SCVAL(pdata,20,delete_pending);
3907 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
3910 SIVAL(pdata,0,ea_size);
3911 pdata += 4; /* EA info */
3912 status = srvstr_push(dstart, flags2,
3914 PTR_DIFF(dend, pdata+4),
3916 if (!NT_STATUS_IS_OK(status)) {
3921 data_size = PTR_DIFF(pdata,(*ppdata));
3922 *fixed_portion = 10;
3926 case SMB2_FILE_ALL_INFORMATION:
3928 unsigned int ea_size =
3929 estimate_ea_size(smb_fname->fsp);
3930 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
3931 put_long_date_full_timespec(conn->ts_res,pdata+0x00,&create_time_ts);
3932 put_long_date_full_timespec(conn->ts_res,pdata+0x08,&atime_ts);
3933 put_long_date_full_timespec(conn->ts_res,pdata+0x10,&mtime_ts); /* write time */
3934 put_long_date_full_timespec(conn->ts_res,pdata+0x18,&ctime_ts); /* change time */
3935 SIVAL(pdata, 0x20, mode);
3936 SIVAL(pdata, 0x24, 0); /* padding. */
3937 SBVAL(pdata, 0x28, allocation_size);
3938 SBVAL(pdata, 0x30, file_size);
3939 SIVAL(pdata, 0x38, nlink);
3940 SCVAL(pdata, 0x3C, delete_pending);
3941 SCVAL(pdata, 0x3D, (mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
3942 SSVAL(pdata, 0x3E, 0); /* padding */
3943 SBVAL(pdata, 0x40, file_id);
3944 SIVAL(pdata, 0x48, ea_size);
3945 SIVAL(pdata, 0x4C, access_mask);
3946 SBVAL(pdata, 0x50, pos);
3947 SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
3948 SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
3952 status = srvstr_push(dstart, flags2,
3954 PTR_DIFF(dend, pdata+4),
3956 if (!NT_STATUS_IS_OK(status)) {
3961 data_size = PTR_DIFF(pdata,(*ppdata));
3962 *fixed_portion = 104;
3965 case SMB_FILE_INTERNAL_INFORMATION:
3967 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
3968 SBVAL(pdata, 0, file_id);
3973 case SMB_FILE_ACCESS_INFORMATION:
3974 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
3975 SIVAL(pdata, 0, access_mask);
3980 case SMB_FILE_NAME_INFORMATION:
3981 /* Pathname with leading '\'. */
3984 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
3985 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
3986 SIVAL(pdata,0,byte_len);
3987 data_size = 4 + byte_len;
3991 case SMB_FILE_DISPOSITION_INFORMATION:
3992 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
3994 SCVAL(pdata,0,delete_pending);
3998 case SMB_FILE_POSITION_INFORMATION:
3999 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4001 SOFF_T(pdata,0,pos);
4005 case SMB_FILE_MODE_INFORMATION:
4006 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4007 SIVAL(pdata,0,mode);
4012 case SMB_FILE_ALIGNMENT_INFORMATION:
4013 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4014 SIVAL(pdata,0,0); /* No alignment needed. */
4020 * NT4 server just returns "invalid query" to this - if we try
4021 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4024 /* The first statement above is false - verified using Thursby
4025 * client against NT4 -- gcolley.
4027 case SMB_QUERY_FILE_STREAM_INFO:
4028 case SMB_FILE_STREAM_INFORMATION: {
4029 unsigned int num_streams = 0;
4030 struct stream_struct *streams = NULL;
4032 DEBUG(10,("smbd_do_qfilepathinfo: "
4033 "SMB_FILE_STREAM_INFORMATION\n"));
4035 if (is_ntfs_stream_smb_fname(smb_fname)) {
4036 return NT_STATUS_INVALID_PARAMETER;
4039 status = vfs_fstreaminfo(fsp,
4044 if (!NT_STATUS_IS_OK(status)) {
4045 DEBUG(10, ("could not get stream info: %s\n",
4046 nt_errstr(status)));
4050 status = marshall_stream_info(num_streams, streams,
4051 pdata, max_data_bytes,
4054 if (!NT_STATUS_IS_OK(status)) {
4055 DEBUG(10, ("marshall_stream_info failed: %s\n",
4056 nt_errstr(status)));
4057 TALLOC_FREE(streams);
4061 TALLOC_FREE(streams);
4063 *fixed_portion = 32;
4067 case SMB_QUERY_COMPRESSION_INFO:
4068 case SMB_FILE_COMPRESSION_INFORMATION:
4069 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4070 SOFF_T(pdata,0,file_size);
4071 SIVAL(pdata,8,0); /* ??? */
4072 SIVAL(pdata,12,0); /* ??? */
4074 *fixed_portion = 16;
4077 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4078 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4079 put_long_date_full_timespec(conn->ts_res,pdata,&create_time_ts);
4080 put_long_date_full_timespec(conn->ts_res,pdata+8,&atime_ts);
4081 put_long_date_full_timespec(conn->ts_res,pdata+16,&mtime_ts); /* write time */
4082 put_long_date_full_timespec(conn->ts_res,pdata+24,&ctime_ts); /* change time */
4083 SOFF_T(pdata,32,allocation_size);
4084 SOFF_T(pdata,40,file_size);
4085 SIVAL(pdata,48,mode);
4086 SIVAL(pdata,52,0); /* ??? */
4088 *fixed_portion = 56;
4091 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4092 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4093 SIVAL(pdata,0,mode);
4100 * CIFS UNIX Extensions.
4103 case SMB_QUERY_FILE_UNIX_BASIC:
4105 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4106 data_size = PTR_DIFF(pdata,(*ppdata));
4108 DEBUG(4,("smbd_do_qfilepathinfo: "
4109 "SMB_QUERY_FILE_UNIX_BASIC\n"));
4110 dump_data(4, (uint8_t *)(*ppdata), data_size);
4114 case SMB_QUERY_FILE_UNIX_INFO2:
4116 pdata = store_file_unix_basic_info2(conn, pdata, fsp, psbuf);
4117 data_size = PTR_DIFF(pdata,(*ppdata));
4121 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4123 for (i=0; i<100; i++)
4124 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4130 case SMB_QUERY_FILE_UNIX_LINK:
4132 status = smb_unix_read_symlink(conn,
4138 if (!NT_STATUS_IS_OK(status)) {
4144 #if defined(HAVE_POSIX_ACLS)
4145 case SMB_QUERY_POSIX_ACL:
4147 status = smb_query_posix_acl(conn,
4154 if (!NT_STATUS_IS_OK(status)) {
4162 case SMB_QUERY_POSIX_LOCK:
4167 enum brl_type lock_type;
4169 /* We need an open file with a real fd for this. */
4171 fsp->fsp_flags.is_pathref ||
4172 fsp_get_io_fd(fsp) == -1)
4174 return NT_STATUS_INVALID_LEVEL;
4177 if (lock_data_count != POSIX_LOCK_DATA_SIZE) {
4178 return NT_STATUS_INVALID_PARAMETER;
4181 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4182 case POSIX_LOCK_TYPE_READ:
4183 lock_type = READ_LOCK;
4185 case POSIX_LOCK_TYPE_WRITE:
4186 lock_type = WRITE_LOCK;
4188 case POSIX_LOCK_TYPE_UNLOCK:
4190 /* There's no point in asking for an unlock... */
4191 return NT_STATUS_INVALID_PARAMETER;
4194 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4195 offset = BVAL(pdata,POSIX_LOCK_START_OFFSET);
4196 count = BVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4198 status = query_lock(fsp,
4205 if (ERROR_WAS_LOCK_DENIED(status)) {
4206 /* Here we need to report who has it locked... */
4207 data_size = POSIX_LOCK_DATA_SIZE;
4209 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
4210 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
4211 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, (uint32_t)smblctx);
4212 SBVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
4213 SBVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
4215 } else if (NT_STATUS_IS_OK(status)) {
4216 /* For success we just return a copy of what we sent
4217 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4218 data_size = POSIX_LOCK_DATA_SIZE;
4219 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
4220 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
4228 return NT_STATUS_INVALID_LEVEL;
4231 *pdata_size = data_size;
4232 return NT_STATUS_OK;
4235 /****************************************************************************
4236 Set a hard link (called by UNIX extensions and by NT rename with HARD link
4238 ****************************************************************************/
4240 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
4241 connection_struct *conn,
4242 struct smb_request *req,
4243 bool overwrite_if_exists,
4244 struct files_struct *old_dirfsp,
4245 const struct smb_filename *smb_fname_old,
4246 struct files_struct *new_dirfsp,
4247 struct smb_filename *smb_fname_new)
4249 NTSTATUS status = NT_STATUS_OK;
4252 struct smb_filename *parent_fname_old = NULL;
4253 struct smb_filename *base_name_old = NULL;
4254 struct smb_filename *parent_fname_new = NULL;
4255 struct smb_filename *base_name_new = NULL;
4257 /* source must already exist. */
4258 if (!VALID_STAT(smb_fname_old->st)) {
4259 status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
4263 /* No links from a directory. */
4264 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
4265 status = NT_STATUS_FILE_IS_A_DIRECTORY;
4269 /* Setting a hardlink to/from a stream isn't currently supported. */
4270 ok = is_ntfs_stream_smb_fname(smb_fname_old);
4272 DBG_DEBUG("Old name has streams\n");
4273 status = NT_STATUS_INVALID_PARAMETER;
4276 ok = is_ntfs_stream_smb_fname(smb_fname_new);
4278 DBG_DEBUG("New name has streams\n");
4279 status = NT_STATUS_INVALID_PARAMETER;
4283 status = parent_pathref(talloc_tos(),
4288 if (!NT_STATUS_IS_OK(status)) {
4292 status = parent_pathref(talloc_tos(),
4297 if (!NT_STATUS_IS_OK(status)) {
4301 if (VALID_STAT(smb_fname_new->st)) {
4302 if (overwrite_if_exists) {
4303 if (S_ISDIR(smb_fname_new->st.st_ex_mode)) {
4304 status = NT_STATUS_FILE_IS_A_DIRECTORY;
4307 status = unlink_internals(conn,
4309 FILE_ATTRIBUTE_NORMAL,
4310 NULL, /* new_dirfsp */
4312 if (!NT_STATUS_IS_OK(status)) {
4316 /* Disallow if newname already exists. */
4317 status = NT_STATUS_OBJECT_NAME_COLLISION;
4322 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
4323 smb_fname_old->base_name, smb_fname_new->base_name));
4325 ret = SMB_VFS_LINKAT(conn,
4326 parent_fname_old->fsp,
4328 parent_fname_new->fsp,
4333 status = map_nt_error_from_unix(errno);
4334 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
4335 nt_errstr(status), smb_fname_old->base_name,
4336 smb_fname_new->base_name));
4341 TALLOC_FREE(parent_fname_old);
4342 TALLOC_FREE(parent_fname_new);
4346 /****************************************************************************
4347 Deal with setting the time from any of the setfilepathinfo functions.
4348 NOTE !!!! The check for FILE_WRITE_ATTRIBUTES access must be done *before*
4349 calling this function.
4350 ****************************************************************************/
4352 NTSTATUS smb_set_file_time(connection_struct *conn,
4354 struct smb_filename *smb_fname,
4355 struct smb_file_time *ft,
4356 bool setting_write_time)
4358 struct files_struct *set_fsp = NULL;
4359 struct timeval_buf tbuf[4];
4361 FILE_NOTIFY_CHANGE_LAST_ACCESS
4362 |FILE_NOTIFY_CHANGE_LAST_WRITE
4363 |FILE_NOTIFY_CHANGE_CREATION;
4366 if (!VALID_STAT(smb_fname->st)) {
4367 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4372 return NT_STATUS_OK;
4375 set_fsp = metadata_fsp(fsp);
4377 /* get some defaults (no modifications) if any info is zero or -1. */
4378 if (is_omit_timespec(&ft->create_time)) {
4379 action &= ~FILE_NOTIFY_CHANGE_CREATION;
4382 if (is_omit_timespec(&ft->atime)) {
4383 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
4386 if (is_omit_timespec(&ft->mtime)) {
4387 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4390 if (!setting_write_time) {
4391 /* ft->mtime comes from change time, not write time. */
4392 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4395 /* Ensure the resolution is the correct for
4396 * what we can store on this filesystem. */
4398 round_timespec(conn->ts_res, &ft->create_time);
4399 round_timespec(conn->ts_res, &ft->ctime);
4400 round_timespec(conn->ts_res, &ft->atime);
4401 round_timespec(conn->ts_res, &ft->mtime);
4403 DBG_DEBUG("smb_set_filetime: actime: %s\n ",
4404 timespec_string_buf(&ft->atime, true, &tbuf[0]));
4405 DBG_DEBUG("smb_set_filetime: modtime: %s\n ",
4406 timespec_string_buf(&ft->mtime, true, &tbuf[1]));
4407 DBG_DEBUG("smb_set_filetime: ctime: %s\n ",
4408 timespec_string_buf(&ft->ctime, true, &tbuf[2]));
4409 DBG_DEBUG("smb_set_file_time: createtime: %s\n ",
4410 timespec_string_buf(&ft->create_time, true, &tbuf[3]));
4412 if (setting_write_time) {
4414 * This was a Windows setfileinfo on an open file.
4415 * NT does this a lot. We also need to
4416 * set the time here, as it can be read by
4417 * FindFirst/FindNext and with the patch for bug #2045
4418 * in smbd/fileio.c it ensures that this timestamp is
4419 * kept sticky even after a write. We save the request
4420 * away and will set it on file close and after a write. JRA.
4423 DBG_DEBUG("setting pending modtime to %s\n",
4424 timespec_string_buf(&ft->mtime, true, &tbuf[0]));
4426 if (set_fsp != NULL) {
4427 set_sticky_write_time_fsp(set_fsp, ft->mtime);
4429 set_sticky_write_time_path(
4430 vfs_file_id_from_sbuf(conn, &smb_fname->st),
4435 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
4437 ret = file_ntimes(conn, set_fsp, ft);
4439 return map_nt_error_from_unix(errno);
4442 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
4443 smb_fname->base_name);
4444 return NT_STATUS_OK;
4447 /****************************************************************************
4448 Deal with setting the dosmode from any of the setfilepathinfo functions.
4449 NB. The check for FILE_WRITE_ATTRIBUTES access on this path must have been
4450 done before calling this function.
4451 ****************************************************************************/
4453 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
4454 struct files_struct *fsp,
4457 struct files_struct *dos_fsp = NULL;
4458 uint32_t current_dosmode;
4461 if (!VALID_STAT(fsp->fsp_name->st)) {
4462 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4465 dos_fsp = metadata_fsp(fsp);
4468 if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
4469 dosmode |= FILE_ATTRIBUTE_DIRECTORY;
4471 dosmode &= ~FILE_ATTRIBUTE_DIRECTORY;
4475 DBG_DEBUG("dosmode: 0x%" PRIx32 "\n", dosmode);
4477 /* check the mode isn't different, before changing it */
4479 return NT_STATUS_OK;
4481 current_dosmode = fdos_mode(dos_fsp);
4482 if (dosmode == current_dosmode) {
4483 return NT_STATUS_OK;
4486 DBG_DEBUG("file %s : setting dos mode 0x%" PRIx32 "\n",
4487 fsp_str_dbg(dos_fsp), dosmode);
4489 ret = file_set_dosmode(conn, dos_fsp->fsp_name, dosmode, NULL, false);
4491 DBG_WARNING("file_set_dosmode of %s failed: %s\n",
4492 fsp_str_dbg(dos_fsp), strerror(errno));
4493 return map_nt_error_from_unix(errno);
4496 return NT_STATUS_OK;
4499 /****************************************************************************
4500 Deal with setting the size from any of the setfilepathinfo functions.
4501 ****************************************************************************/
4503 static NTSTATUS smb_set_file_size(connection_struct *conn,
4504 struct smb_request *req,
4506 struct smb_filename *smb_fname,
4507 const SMB_STRUCT_STAT *psbuf,
4509 bool fail_after_createfile)
4511 NTSTATUS status = NT_STATUS_OK;
4512 files_struct *new_fsp = NULL;
4514 if (!VALID_STAT(*psbuf)) {
4515 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4518 DBG_INFO("size: %"PRIu64", file_size_stat=%"PRIu64"\n",
4520 get_file_size_stat(psbuf));
4522 if (size == get_file_size_stat(psbuf)) {
4524 return NT_STATUS_OK;
4526 if (!fsp->fsp_flags.modified) {
4527 return NT_STATUS_OK;
4529 trigger_write_time_update_immediate(fsp);
4530 return NT_STATUS_OK;
4533 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
4534 smb_fname_str_dbg(smb_fname), (double)size));
4537 !fsp->fsp_flags.is_pathref &&
4538 fsp_get_io_fd(fsp) != -1)
4540 /* Handle based call. */
4541 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
4542 return NT_STATUS_ACCESS_DENIED;
4545 if (vfs_set_filelen(fsp, size) == -1) {
4546 return map_nt_error_from_unix(errno);
4548 trigger_write_time_update_immediate(fsp);
4549 return NT_STATUS_OK;
4552 status = SMB_VFS_CREATE_FILE(
4556 smb_fname, /* fname */
4557 FILE_WRITE_DATA, /* access_mask */
4558 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
4560 FILE_OPEN, /* create_disposition*/
4561 0, /* create_options */
4562 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
4563 0, /* oplock_request */
4565 0, /* allocation_size */
4566 0, /* private_flags */
4569 &new_fsp, /* result */
4571 NULL, NULL); /* create context */
4573 if (!NT_STATUS_IS_OK(status)) {
4574 /* NB. We check for open_was_deferred in the caller. */
4578 /* See RAW-SFILEINFO-END-OF-FILE */
4579 if (fail_after_createfile) {
4580 close_file_free(req, &new_fsp, NORMAL_CLOSE);
4581 return NT_STATUS_INVALID_LEVEL;
4584 if (vfs_set_filelen(new_fsp, size) == -1) {
4585 status = map_nt_error_from_unix(errno);
4586 close_file_free(req, &new_fsp, NORMAL_CLOSE);
4590 trigger_write_time_update_immediate(new_fsp);
4591 close_file_free(req, &new_fsp, NORMAL_CLOSE);
4592 return NT_STATUS_OK;
4595 /****************************************************************************
4596 Deal with SMB_INFO_SET_EA.
4597 ****************************************************************************/
4599 static NTSTATUS smb_info_set_ea(connection_struct *conn,
4603 struct smb_filename *smb_fname)
4605 struct ea_list *ea_list = NULL;
4606 TALLOC_CTX *ctx = NULL;
4607 NTSTATUS status = NT_STATUS_OK;
4609 if (total_data < 10) {
4611 /* OS/2 workplace shell seems to send SET_EA requests of "null"
4612 length. They seem to have no effect. Bug #3212. JRA */
4614 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
4615 /* We're done. We only get EA info in this call. */
4616 return NT_STATUS_OK;
4619 return NT_STATUS_INVALID_PARAMETER;
4622 if (IVAL(pdata,0) > total_data) {
4623 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
4624 IVAL(pdata,0), (unsigned int)total_data));
4625 return NT_STATUS_INVALID_PARAMETER;
4629 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
4631 return NT_STATUS_INVALID_PARAMETER;
4636 * The only way fsp can be NULL here is if
4637 * smb_fname points at a symlink and
4638 * and we're in POSIX context.
4639 * Ensure this is the case.
4641 * In this case we cannot set the EA.
4643 SMB_ASSERT(smb_fname->flags & SMB_FILENAME_POSIX_PATH);
4644 return NT_STATUS_ACCESS_DENIED;
4647 status = set_ea(conn, fsp, ea_list);
4652 /****************************************************************************
4653 Deal with SMB_FILE_FULL_EA_INFORMATION set.
4654 ****************************************************************************/
4656 static NTSTATUS smb_set_file_full_ea_info(connection_struct *conn,
4661 struct ea_list *ea_list = NULL;
4665 return NT_STATUS_INVALID_HANDLE;
4668 if (!lp_ea_support(SNUM(conn))) {
4669 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
4670 "EA's not supported.\n",
4671 (unsigned int)total_data));
4672 return NT_STATUS_EAS_NOT_SUPPORTED;
4675 if (total_data < 10) {
4676 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
4678 (unsigned int)total_data));
4679 return NT_STATUS_INVALID_PARAMETER;
4682 ea_list = read_nttrans_ea_list(talloc_tos(),
4687 return NT_STATUS_INVALID_PARAMETER;
4690 status = set_ea(conn, fsp, ea_list);
4692 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
4693 smb_fname_str_dbg(fsp->fsp_name),
4694 nt_errstr(status) ));
4700 /****************************************************************************
4701 Deal with SMB_SET_FILE_DISPOSITION_INFO.
4702 ****************************************************************************/
4704 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
4708 struct smb_filename *smb_fname)
4710 NTSTATUS status = NT_STATUS_OK;
4711 bool delete_on_close;
4712 uint32_t dosmode = 0;
4714 if (total_data < 1) {
4715 return NT_STATUS_INVALID_PARAMETER;
4719 return NT_STATUS_INVALID_HANDLE;
4722 delete_on_close = (CVAL(pdata,0) ? True : False);
4723 dosmode = fdos_mode(fsp);
4725 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
4726 "delete_on_close = %u\n",
4727 smb_fname_str_dbg(smb_fname),
4728 (unsigned int)dosmode,
4729 (unsigned int)delete_on_close ));
4731 if (delete_on_close) {
4732 status = can_set_delete_on_close(fsp, dosmode);
4733 if (!NT_STATUS_IS_OK(status)) {
4738 /* The set is across all open files on this dev/inode pair. */
4739 if (!set_delete_on_close(fsp, delete_on_close,
4740 conn->session_info->security_token,
4741 conn->session_info->unix_token)) {
4742 return NT_STATUS_ACCESS_DENIED;
4744 return NT_STATUS_OK;
4747 /****************************************************************************
4748 Deal with SMB_FILE_POSITION_INFORMATION.
4749 ****************************************************************************/
4751 static NTSTATUS smb_file_position_information(connection_struct *conn,
4756 uint64_t position_information;
4758 if (total_data < 8) {
4759 return NT_STATUS_INVALID_PARAMETER;
4763 /* Ignore on pathname based set. */
4764 return NT_STATUS_OK;
4767 position_information = (uint64_t)IVAL(pdata,0);
4768 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
4770 DEBUG(10,("smb_file_position_information: Set file position "
4771 "information for file %s to %.0f\n", fsp_str_dbg(fsp),
4772 (double)position_information));
4773 fh_set_position_information(fsp->fh, position_information);
4774 return NT_STATUS_OK;
4777 /****************************************************************************
4778 Deal with SMB_FILE_MODE_INFORMATION.
4779 ****************************************************************************/
4781 static NTSTATUS smb_file_mode_information(connection_struct *conn,
4787 if (total_data < 4) {
4788 return NT_STATUS_INVALID_PARAMETER;
4790 mode = IVAL(pdata,0);
4791 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
4792 return NT_STATUS_INVALID_PARAMETER;
4794 return NT_STATUS_OK;
4797 /****************************************************************************
4798 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
4799 ****************************************************************************/
4801 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
4802 struct smb_request *req,
4805 struct smb_filename *new_smb_fname)
4807 char *link_target = NULL;
4808 struct smb_filename target_fname;
4809 TALLOC_CTX *ctx = talloc_tos();
4812 struct smb_filename *parent_fname = NULL;
4813 struct smb_filename *base_name = NULL;
4815 /* Set a symbolic link. */
4816 /* Don't allow this if follow links is false. */
4818 if (total_data == 0) {
4819 return NT_STATUS_INVALID_PARAMETER;
4822 if (!lp_follow_symlinks(SNUM(conn))) {
4823 return NT_STATUS_ACCESS_DENIED;
4826 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
4827 total_data, STR_TERMINATE);
4830 return NT_STATUS_INVALID_PARAMETER;
4833 target_fname = (struct smb_filename) {
4834 .base_name = link_target,
4837 /* Removes @GMT tokens if any */
4838 status = canonicalize_snapshot_path(&target_fname, UCF_GMT_PATHNAME, 0);
4839 if (!NT_STATUS_IS_OK(status)) {
4843 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
4844 new_smb_fname->base_name, link_target ));
4846 status = parent_pathref(talloc_tos(),
4851 if (!NT_STATUS_IS_OK(status)) {
4855 ret = SMB_VFS_SYMLINKAT(conn,
4860 TALLOC_FREE(parent_fname);
4861 return map_nt_error_from_unix(errno);
4864 TALLOC_FREE(parent_fname);
4865 return NT_STATUS_OK;
4868 /****************************************************************************
4869 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
4870 ****************************************************************************/
4872 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
4873 struct smb_request *req,
4874 const char *pdata, int total_data,
4875 struct smb_filename *smb_fname_new)
4877 char *oldname = NULL;
4878 struct files_struct *src_dirfsp = NULL;
4879 struct smb_filename *smb_fname_old = NULL;
4880 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
4881 NTTIME old_twrp = 0;
4882 TALLOC_CTX *ctx = talloc_tos();
4883 NTSTATUS status = NT_STATUS_OK;
4885 /* Set a hard link. */
4886 if (total_data == 0) {
4887 return NT_STATUS_INVALID_PARAMETER;
4890 if (req->posix_pathnames) {
4891 srvstr_get_path_posix(ctx,
4900 srvstr_get_path(ctx,
4909 if (!NT_STATUS_IS_OK(status)) {
4913 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
4914 smb_fname_str_dbg(smb_fname_new), oldname));
4916 if (ucf_flags & UCF_GMT_PATHNAME) {
4917 extract_snapshot_token(oldname, &old_twrp);
4919 status = filename_convert_dirfsp(ctx,
4926 if (!NT_STATUS_IS_OK(status)) {
4930 return hardlink_internals(ctx,
4936 NULL, /* new_dirfsp */
4940 /****************************************************************************
4941 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
4942 ****************************************************************************/
4944 static NTSTATUS smb2_file_rename_information(connection_struct *conn,
4945 struct smb_request *req,
4949 struct smb_filename *smb_fname_src)
4953 char *newname = NULL;
4954 struct files_struct *dst_dirfsp = NULL;
4955 struct smb_filename *smb_fname_dst = NULL;
4956 const char *dst_original_lcomp = NULL;
4957 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
4958 NTTIME dst_twrp = 0;
4959 NTSTATUS status = NT_STATUS_OK;
4960 TALLOC_CTX *ctx = talloc_tos();
4963 return NT_STATUS_INVALID_HANDLE;
4966 if (total_data < 20) {
4967 return NT_STATUS_INVALID_PARAMETER;
4970 overwrite = (CVAL(pdata,0) ? True : False);
4971 len = IVAL(pdata,16);
4973 if (len > (total_data - 20) || (len == 0)) {
4974 return NT_STATUS_INVALID_PARAMETER;
4977 if (req->posix_pathnames) {
4978 srvstr_get_path_posix(ctx,
4987 srvstr_get_path(ctx,
4996 if (!NT_STATUS_IS_OK(status)) {
5000 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
5003 if (newname[0] == ':') {
5004 /* Create an smb_fname to call rename_internals_fsp() with. */
5005 smb_fname_dst = synthetic_smb_fname(talloc_tos(),
5006 fsp->base_fsp->fsp_name->base_name,
5009 fsp->base_fsp->fsp_name->twrp,
5010 fsp->base_fsp->fsp_name->flags);
5011 if (smb_fname_dst == NULL) {
5012 status = NT_STATUS_NO_MEMORY;
5016 if (ucf_flags & UCF_GMT_PATHNAME) {
5017 extract_snapshot_token(newname, &dst_twrp);
5019 status = filename_convert_dirfsp(ctx,
5026 if (!NT_STATUS_IS_OK(status)) {
5032 * Set the original last component, since
5033 * rename_internals_fsp() requires it.
5035 dst_original_lcomp = get_original_lcomp(smb_fname_dst,
5039 if (dst_original_lcomp == NULL) {
5040 status = NT_STATUS_NO_MEMORY;
5044 DEBUG(10,("smb2_file_rename_information: "
5045 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
5046 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
5047 smb_fname_str_dbg(smb_fname_dst)));
5048 status = rename_internals_fsp(conn,
5050 NULL, /* dst_dirfsp */
5053 (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM),
5057 TALLOC_FREE(smb_fname_dst);
5061 static NTSTATUS smb_file_link_information(connection_struct *conn,
5062 struct smb_request *req,
5066 struct smb_filename *smb_fname_src)
5070 char *newname = NULL;
5071 struct files_struct *dst_dirfsp = NULL;
5072 struct smb_filename *smb_fname_dst = NULL;
5073 NTSTATUS status = NT_STATUS_OK;
5074 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
5075 NTTIME dst_twrp = 0;
5076 TALLOC_CTX *ctx = talloc_tos();
5079 return NT_STATUS_INVALID_HANDLE;
5082 if (total_data < 20) {
5083 return NT_STATUS_INVALID_PARAMETER;
5086 overwrite = (CVAL(pdata,0) ? true : false);
5087 len = IVAL(pdata,16);
5089 if (len > (total_data - 20) || (len == 0)) {
5090 return NT_STATUS_INVALID_PARAMETER;
5093 if (smb_fname_src->flags & SMB_FILENAME_POSIX_PATH) {
5094 srvstr_get_path_posix(ctx,
5102 ucf_flags |= UCF_POSIX_PATHNAMES;
5104 srvstr_get_path(ctx,
5113 if (!NT_STATUS_IS_OK(status)) {
5117 DEBUG(10,("smb_file_link_information: got name |%s|\n",
5120 if (ucf_flags & UCF_GMT_PATHNAME) {
5121 extract_snapshot_token(newname, &dst_twrp);
5123 status = filename_convert_dirfsp(ctx,
5130 if (!NT_STATUS_IS_OK(status)) {
5134 if (fsp->base_fsp) {
5135 /* No stream names. */
5136 return NT_STATUS_NOT_SUPPORTED;
5139 DEBUG(10,("smb_file_link_information: "
5140 "SMB_FILE_LINK_INFORMATION (%s) %s -> %s\n",
5141 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
5142 smb_fname_str_dbg(smb_fname_dst)));
5143 status = hardlink_internals(ctx,
5147 NULL, /* src_dirfsp */
5149 dst_dirfsp, /* dst_dirfsp */
5152 TALLOC_FREE(smb_fname_dst);
5156 /****************************************************************************
5157 Deal with SMB_FILE_RENAME_INFORMATION.
5158 ****************************************************************************/
5160 static NTSTATUS smb_file_rename_information(connection_struct *conn,
5161 struct smb_request *req,
5165 struct smb_filename *smb_fname_src)
5170 char *newname = NULL;
5171 struct files_struct *dst_dirfsp = NULL;
5172 struct smb_filename *smb_fname_dst = NULL;
5173 const char *dst_original_lcomp = NULL;
5174 NTSTATUS status = NT_STATUS_OK;
5176 TALLOC_CTX *ctx = talloc_tos();
5178 if (total_data < 13) {
5179 return NT_STATUS_INVALID_PARAMETER;
5182 overwrite = (CVAL(pdata,0) != 0);
5183 root_fid = IVAL(pdata,4);
5184 len = IVAL(pdata,8);
5186 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
5187 return NT_STATUS_INVALID_PARAMETER;
5190 if (req->posix_pathnames) {
5191 srvstr_get_path_posix(ctx,
5200 srvstr_get_path(ctx,
5209 if (!NT_STATUS_IS_OK(status)) {
5213 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
5216 /* Check the new name has no '/' characters. */
5217 if (strchr_m(newname, '/')) {
5218 return NT_STATUS_NOT_SUPPORTED;
5221 if (fsp && fsp->base_fsp) {
5222 /* newname must be a stream name. */
5223 if (newname[0] != ':') {
5224 return NT_STATUS_NOT_SUPPORTED;
5227 /* Create an smb_fname to call rename_internals_fsp() with. */
5228 smb_fname_dst = synthetic_smb_fname(talloc_tos(),
5229 fsp->base_fsp->fsp_name->base_name,
5232 fsp->base_fsp->fsp_name->twrp,
5233 fsp->base_fsp->fsp_name->flags);
5234 if (smb_fname_dst == NULL) {
5235 status = NT_STATUS_NO_MEMORY;
5240 * Get the original last component, since
5241 * rename_internals_fsp() requires it.
5243 dst_original_lcomp = get_original_lcomp(smb_fname_dst,
5247 if (dst_original_lcomp == NULL) {
5248 status = NT_STATUS_NO_MEMORY;
5254 * Build up an smb_fname_dst based on the filename passed in.
5255 * We basically just strip off the last component, and put on
5256 * the newname instead.
5258 char *base_name = NULL;
5259 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
5260 NTTIME dst_twrp = 0;
5262 /* newname must *not* be a stream name. */
5263 if (newname[0] == ':') {
5264 return NT_STATUS_NOT_SUPPORTED;
5268 * Strip off the last component (filename) of the path passed
5271 base_name = talloc_strdup(ctx, smb_fname_src->base_name);
5273 return NT_STATUS_NO_MEMORY;
5275 p = strrchr_m(base_name, '/');
5279 base_name = talloc_strdup(ctx, "");
5281 return NT_STATUS_NO_MEMORY;
5284 /* Append the new name. */
5285 base_name = talloc_asprintf_append(base_name,
5289 return NT_STATUS_NO_MEMORY;
5292 if (ucf_flags & UCF_GMT_PATHNAME) {
5293 extract_snapshot_token(base_name, &dst_twrp);
5295 status = filename_convert_dirfsp(ctx,
5303 if (!NT_STATUS_IS_OK(status)) {
5306 dst_original_lcomp = get_original_lcomp(smb_fname_dst,
5310 if (dst_original_lcomp == NULL) {
5311 status = NT_STATUS_NO_MEMORY;
5316 if (fsp != NULL && fsp->fsp_flags.is_fsa) {
5317 DEBUG(10,("smb_file_rename_information: "
5318 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
5319 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
5320 smb_fname_str_dbg(smb_fname_dst)));
5321 status = rename_internals_fsp(conn,
5329 DEBUG(10,("smb_file_rename_information: "
5330 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
5331 smb_fname_str_dbg(smb_fname_src),
5332 smb_fname_str_dbg(smb_fname_dst)));
5333 status = rename_internals(ctx,
5336 NULL, /* src_dirfsp */
5343 FILE_WRITE_ATTRIBUTES);
5346 TALLOC_FREE(smb_fname_dst);
5350 /****************************************************************************
5351 Deal with SMB_SET_POSIX_ACL.
5352 ****************************************************************************/
5354 #if defined(HAVE_POSIX_ACLS)
5355 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
5356 struct smb_request *req,
5360 struct smb_filename *smb_fname)
5362 uint16_t posix_acl_version;
5363 uint16_t num_file_acls;
5364 uint16_t num_def_acls;
5365 bool valid_file_acls = true;
5366 bool valid_def_acls = true;
5368 unsigned int size_needed;
5369 unsigned int total_data;
5370 bool close_fsp = false;
5372 if (total_data_in < 0) {
5373 status = NT_STATUS_INVALID_PARAMETER;
5377 total_data = total_data_in;
5379 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
5380 status = NT_STATUS_INVALID_PARAMETER;
5383 posix_acl_version = SVAL(pdata,0);
5384 num_file_acls = SVAL(pdata,2);
5385 num_def_acls = SVAL(pdata,4);
5387 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5388 valid_file_acls = false;
5392 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5393 valid_def_acls = false;
5397 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
5398 status = NT_STATUS_INVALID_PARAMETER;
5403 if (num_file_acls + num_def_acls < num_file_acls) {
5404 status = NT_STATUS_INVALID_PARAMETER;
5408 size_needed = num_file_acls + num_def_acls;
5411 * (size_needed * SMB_POSIX_ACL_ENTRY_SIZE) must be less
5412 * than UINT_MAX, so check by division.
5414 if (size_needed > (UINT_MAX/SMB_POSIX_ACL_ENTRY_SIZE)) {
5415 status = NT_STATUS_INVALID_PARAMETER;
5419 size_needed = size_needed*SMB_POSIX_ACL_ENTRY_SIZE;
5420 if (size_needed + SMB_POSIX_ACL_HEADER_SIZE < size_needed) {
5421 status = NT_STATUS_INVALID_PARAMETER;
5424 size_needed += SMB_POSIX_ACL_HEADER_SIZE;
5426 if (total_data < size_needed) {
5427 status = NT_STATUS_INVALID_PARAMETER;
5432 * Ensure we always operate on a file descriptor, not just
5435 if (fsp == NULL || !fsp->fsp_flags.is_fsa) {
5436 uint32_t access_mask = SEC_STD_WRITE_OWNER|
5438 SEC_STD_READ_CONTROL|
5439 FILE_READ_ATTRIBUTES|
5440 FILE_WRITE_ATTRIBUTES;
5442 status = get_posix_fsp(conn,
5448 if (!NT_STATUS_IS_OK(status)) {
5454 /* Here we know fsp != NULL */
5455 SMB_ASSERT(fsp != NULL);
5457 status = refuse_symlink_fsp(fsp);
5458 if (!NT_STATUS_IS_OK(status)) {
5462 /* If we have a default acl, this *must* be a directory. */
5463 if (valid_def_acls && !fsp->fsp_flags.is_directory) {
5464 DBG_INFO("Can't set default acls on "
5465 "non-directory %s\n",
5467 return NT_STATUS_INVALID_HANDLE;
5470 DBG_DEBUG("file %s num_file_acls = %"PRIu16", "
5471 "num_def_acls = %"PRIu16"\n",
5476 /* Move pdata to the start of the file ACL entries. */
5477 pdata += SMB_POSIX_ACL_HEADER_SIZE;
5479 if (valid_file_acls) {
5480 status = set_unix_posix_acl(conn,
5484 if (!NT_STATUS_IS_OK(status)) {
5489 /* Move pdata to the start of the default ACL entries. */
5490 pdata += (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE);
5492 if (valid_def_acls) {
5493 status = set_unix_posix_default_acl(conn,
5497 if (!NT_STATUS_IS_OK(status)) {
5502 status = NT_STATUS_OK;
5507 (void)close_file_free(req, &fsp, NORMAL_CLOSE);
5513 /****************************************************************************
5514 Deal with SMB_SET_FILE_BASIC_INFO.
5515 ****************************************************************************/
5517 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
5521 struct smb_filename *smb_fname)
5523 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
5524 struct smb_file_time ft;
5525 uint32_t dosmode = 0;
5526 NTSTATUS status = NT_STATUS_OK;
5528 init_smb_file_time(&ft);
5530 if (total_data < 36) {
5531 return NT_STATUS_INVALID_PARAMETER;
5535 return NT_STATUS_INVALID_HANDLE;
5538 status = check_access_fsp(fsp, FILE_WRITE_ATTRIBUTES);
5539 if (!NT_STATUS_IS_OK(status)) {
5543 /* Set the attributes */
5544 dosmode = IVAL(pdata,32);
5545 status = smb_set_file_dosmode(conn, fsp, dosmode);
5546 if (!NT_STATUS_IS_OK(status)) {
5551 ft.create_time = pull_long_date_full_timespec(pdata);
5554 ft.atime = pull_long_date_full_timespec(pdata+8);
5557 ft.mtime = pull_long_date_full_timespec(pdata+16);
5560 ft.ctime = pull_long_date_full_timespec(pdata+24);
5562 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
5563 smb_fname_str_dbg(smb_fname)));
5565 status = smb_set_file_time(conn, fsp, smb_fname, &ft, true);
5566 if (!NT_STATUS_IS_OK(status)) {
5570 if (fsp->fsp_flags.modified) {
5571 trigger_write_time_update_immediate(fsp);
5573 return NT_STATUS_OK;
5576 /****************************************************************************
5577 Deal with SMB_INFO_STANDARD.
5578 ****************************************************************************/
5580 static NTSTATUS smb_set_info_standard(connection_struct *conn,
5584 struct smb_filename *smb_fname)
5587 struct smb_file_time ft;
5589 init_smb_file_time(&ft);
5591 if (total_data < 12) {
5592 return NT_STATUS_INVALID_PARAMETER;
5596 return NT_STATUS_INVALID_HANDLE;
5600 ft.create_time = time_t_to_full_timespec(srv_make_unix_date2(pdata));
5602 ft.atime = time_t_to_full_timespec(srv_make_unix_date2(pdata+4));
5604 ft.mtime = time_t_to_full_timespec(srv_make_unix_date2(pdata+8));
5606 DEBUG(10,("smb_set_info_standard: file %s\n",
5607 smb_fname_str_dbg(smb_fname)));
5609 status = check_access_fsp(fsp, FILE_WRITE_ATTRIBUTES);
5610 if (!NT_STATUS_IS_OK(status)) {
5614 status = smb_set_file_time(conn, fsp, smb_fname, &ft, true);
5615 if (!NT_STATUS_IS_OK(status)) {
5619 if (fsp->fsp_flags.modified) {
5620 trigger_write_time_update_immediate(fsp);
5622 return NT_STATUS_OK;
5625 /****************************************************************************
5626 Deal with SMB_SET_FILE_ALLOCATION_INFO.
5627 ****************************************************************************/
5629 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
5630 struct smb_request *req,
5634 struct smb_filename *smb_fname)
5636 uint64_t allocation_size = 0;
5637 NTSTATUS status = NT_STATUS_OK;
5638 files_struct *new_fsp = NULL;
5640 if (!VALID_STAT(smb_fname->st)) {
5641 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5644 if (total_data < 8) {
5645 return NT_STATUS_INVALID_PARAMETER;
5648 allocation_size = (uint64_t)IVAL(pdata,0);
5649 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
5650 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
5651 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
5652 (double)allocation_size));
5654 if (allocation_size) {
5655 allocation_size = smb_roundup(conn, allocation_size);
5658 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
5659 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
5660 (double)allocation_size));
5663 !fsp->fsp_flags.is_pathref &&
5664 fsp_get_io_fd(fsp) != -1)
5666 /* Open file handle. */
5667 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
5668 return NT_STATUS_ACCESS_DENIED;
5671 /* Only change if needed. */
5672 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
5673 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
5674 return map_nt_error_from_unix(errno);
5677 /* But always update the time. */
5679 * This is equivalent to a write. Ensure it's seen immediately
5680 * if there are no pending writes.
5682 trigger_write_time_update_immediate(fsp);
5683 return NT_STATUS_OK;
5686 /* Pathname or stat or directory file. */
5687 status = SMB_VFS_CREATE_FILE(
5691 smb_fname, /* fname */
5692 FILE_WRITE_DATA, /* access_mask */
5693 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5695 FILE_OPEN, /* create_disposition*/
5696 0, /* create_options */
5697 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5698 0, /* oplock_request */
5700 0, /* allocation_size */
5701 0, /* private_flags */
5704 &new_fsp, /* result */
5706 NULL, NULL); /* create context */
5708 if (!NT_STATUS_IS_OK(status)) {
5709 /* NB. We check for open_was_deferred in the caller. */
5713 /* Only change if needed. */
5714 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
5715 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
5716 status = map_nt_error_from_unix(errno);
5717 close_file_free(req, &new_fsp, NORMAL_CLOSE);
5722 /* Changing the allocation size should set the last mod time. */
5724 * This is equivalent to a write. Ensure it's seen immediately
5725 * if there are no pending writes.
5727 trigger_write_time_update_immediate(new_fsp);
5728 close_file_free(req, &new_fsp, NORMAL_CLOSE);
5729 return NT_STATUS_OK;
5732 /****************************************************************************
5733 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
5734 ****************************************************************************/
5736 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
5737 struct smb_request *req,
5741 struct smb_filename *smb_fname,
5742 bool fail_after_createfile)
5746 if (total_data < 8) {
5747 return NT_STATUS_INVALID_PARAMETER;
5750 size = IVAL(pdata,0);
5751 size |= (((off_t)IVAL(pdata,4)) << 32);
5752 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
5753 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
5756 return smb_set_file_size(conn, req,
5761 fail_after_createfile);
5764 /****************************************************************************
5765 Allow a UNIX info mknod.
5766 ****************************************************************************/
5768 static NTSTATUS smb_unix_mknod(connection_struct *conn,
5771 const struct smb_filename *smb_fname)
5773 uint32_t file_type = IVAL(pdata,56);
5774 #if defined(HAVE_MAKEDEV)
5775 uint32_t dev_major = IVAL(pdata,60);
5776 uint32_t dev_minor = IVAL(pdata,68);
5778 SMB_DEV_T dev = (SMB_DEV_T)0;
5779 uint32_t raw_unixmode = IVAL(pdata,84);
5783 struct smb_filename *parent_fname = NULL;
5784 struct smb_filename *base_name = NULL;
5786 if (total_data < 100) {
5787 return NT_STATUS_INVALID_PARAMETER;
5790 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
5791 PERM_NEW_FILE, &unixmode);
5792 if (!NT_STATUS_IS_OK(status)) {
5796 #if defined(HAVE_MAKEDEV)
5797 dev = makedev(dev_major, dev_minor);
5800 switch (file_type) {
5801 /* We can't create other objects here. */
5802 case UNIX_TYPE_FILE:
5804 case UNIX_TYPE_SYMLINK:
5805 return NT_STATUS_ACCESS_DENIED;
5806 #if defined(S_IFIFO)
5807 case UNIX_TYPE_FIFO:
5808 unixmode |= S_IFIFO;
5811 #if defined(S_IFSOCK)
5812 case UNIX_TYPE_SOCKET:
5813 unixmode |= S_IFSOCK;
5816 #if defined(S_IFCHR)
5817 case UNIX_TYPE_CHARDEV:
5818 /* This is only allowed for root. */
5819 if (get_current_uid(conn) != sec_initial_uid()) {
5820 return NT_STATUS_ACCESS_DENIED;
5822 unixmode |= S_IFCHR;
5825 #if defined(S_IFBLK)
5826 case UNIX_TYPE_BLKDEV:
5827 if (get_current_uid(conn) != sec_initial_uid()) {
5828 return NT_STATUS_ACCESS_DENIED;
5830 unixmode |= S_IFBLK;
5834 return NT_STATUS_INVALID_PARAMETER;
5837 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
5838 "%.0f mode 0%o for file %s\n", (double)dev,
5839 (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
5841 status = parent_pathref(talloc_tos(),
5846 if (!NT_STATUS_IS_OK(status)) {
5850 /* Ok - do the mknod. */
5851 ret = SMB_VFS_MKNODAT(conn,
5858 TALLOC_FREE(parent_fname);
5859 return map_nt_error_from_unix(errno);
5862 /* If any of the other "set" calls fail we
5863 * don't want to end up with a half-constructed mknod.
5866 if (lp_inherit_permissions(SNUM(conn))) {
5867 inherit_access_posix_acl(conn,
5872 TALLOC_FREE(parent_fname);
5874 return NT_STATUS_OK;
5877 /****************************************************************************
5878 Deal with SMB_SET_FILE_UNIX_BASIC.
5879 ****************************************************************************/
5881 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
5882 struct smb_request *req,
5886 struct smb_filename *smb_fname)
5888 struct smb_file_time ft;
5889 uint32_t raw_unixmode;
5892 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
5893 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
5894 NTSTATUS status = NT_STATUS_OK;
5895 enum perm_type ptype;
5896 files_struct *all_fsps = NULL;
5897 bool modify_mtime = true;
5899 SMB_STRUCT_STAT sbuf;
5901 init_smb_file_time(&ft);
5903 if (total_data < 100) {
5904 return NT_STATUS_INVALID_PARAMETER;
5907 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
5908 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
5909 size=IVAL(pdata,0); /* first 8 Bytes are size */
5910 size |= (((off_t)IVAL(pdata,4)) << 32);
5913 ft.atime = pull_long_date_full_timespec(pdata+24); /* access_time */
5914 ft.mtime = pull_long_date_full_timespec(pdata+32); /* modification_time */
5915 set_owner = (uid_t)IVAL(pdata,40);
5916 set_grp = (gid_t)IVAL(pdata,48);
5917 raw_unixmode = IVAL(pdata,84);
5919 if (VALID_STAT(smb_fname->st)) {
5920 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
5921 ptype = PERM_EXISTING_DIR;
5923 ptype = PERM_EXISTING_FILE;
5926 ptype = PERM_NEW_FILE;
5929 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
5931 if (!NT_STATUS_IS_OK(status)) {
5935 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
5936 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
5937 smb_fname_str_dbg(smb_fname), (double)size,
5938 (unsigned int)set_owner, (unsigned int)set_grp,
5939 (int)raw_unixmode));
5941 sbuf = smb_fname->st;
5943 if (!VALID_STAT(sbuf)) {
5945 * The only valid use of this is to create character and block
5946 * devices, and named pipes. This is deprecated (IMHO) and
5947 * a new info level should be used for mknod. JRA.
5950 return smb_unix_mknod(conn,
5957 /* Horrible backwards compatibility hack as an old server bug
5958 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
5962 size = get_file_size_stat(&sbuf);
5967 * Deal with the UNIX specific mode set.
5970 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
5973 if (fsp == NULL || S_ISLNK(smb_fname->st.st_ex_mode)) {
5974 DBG_WARNING("Can't set mode on symlink %s\n",
5975 smb_fname_str_dbg(smb_fname));
5976 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5979 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
5980 "setting mode 0%o for file %s\n",
5981 (unsigned int)unixmode,
5982 smb_fname_str_dbg(smb_fname)));
5983 ret = SMB_VFS_FCHMOD(fsp, unixmode);
5985 return map_nt_error_from_unix(errno);
5990 * Deal with the UNIX specific uid set.
5993 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
5994 (sbuf.st_ex_uid != set_owner)) {
5997 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
5998 "changing owner %u for path %s\n",
5999 (unsigned int)set_owner,
6000 smb_fname_str_dbg(smb_fname)));
6003 !fsp->fsp_flags.is_pathref &&
6004 fsp_get_io_fd(fsp) != -1)
6006 ret = SMB_VFS_FCHOWN(fsp, set_owner, (gid_t)-1);
6009 * UNIX extensions calls must always operate
6012 ret = SMB_VFS_LCHOWN(conn, smb_fname,
6013 set_owner, (gid_t)-1);
6017 status = map_nt_error_from_unix(errno);
6023 * Deal with the UNIX specific gid set.
6026 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
6027 (sbuf.st_ex_gid != set_grp)) {
6030 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6031 "changing group %u for file %s\n",
6032 (unsigned int)set_grp,
6033 smb_fname_str_dbg(smb_fname)));
6035 !fsp->fsp_flags.is_pathref &&
6036 fsp_get_io_fd(fsp) != -1)
6038 ret = SMB_VFS_FCHOWN(fsp, (uid_t)-1, set_grp);
6041 * UNIX extensions calls must always operate
6044 ret = SMB_VFS_LCHOWN(conn, smb_fname, (uid_t)-1,
6048 status = map_nt_error_from_unix(errno);
6053 /* Deal with any size changes. */
6055 if (S_ISREG(sbuf.st_ex_mode)) {
6056 status = smb_set_file_size(conn, req,
6062 if (!NT_STATUS_IS_OK(status)) {
6067 /* Deal with any time changes. */
6068 if (is_omit_timespec(&ft.mtime) && is_omit_timespec(&ft.atime)) {
6069 /* No change, don't cancel anything. */
6073 id = vfs_file_id_from_sbuf(conn, &sbuf);
6074 for(all_fsps = file_find_di_first(conn->sconn, id, true); all_fsps;
6075 all_fsps = file_find_di_next(all_fsps, true)) {
6077 * We're setting the time explicitly for UNIX.
6078 * Cancel any pending changes over all handles.
6080 all_fsps->fsp_flags.update_write_time_on_close = false;
6081 TALLOC_FREE(all_fsps->update_write_time_event);
6085 * Override the "setting_write_time"
6086 * parameter here as it almost does what
6087 * we need. Just remember if we modified
6088 * mtime and send the notify ourselves.
6090 if (is_omit_timespec(&ft.mtime)) {
6091 modify_mtime = false;
6094 status = smb_set_file_time(conn,
6100 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
6101 FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
6106 /****************************************************************************
6107 Deal with SMB_SET_FILE_UNIX_INFO2.
6108 ****************************************************************************/
6110 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
6111 struct smb_request *req,
6115 struct smb_filename *smb_fname)
6118 uint32_t smb_fflags;
6121 if (total_data < 116) {
6122 return NT_STATUS_INVALID_PARAMETER;
6125 /* Start by setting all the fields that are common between UNIX_BASIC
6128 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
6130 if (!NT_STATUS_IS_OK(status)) {
6134 smb_fflags = IVAL(pdata, 108);
6135 smb_fmask = IVAL(pdata, 112);
6137 /* NB: We should only attempt to alter the file flags if the client
6138 * sends a non-zero mask.
6140 if (smb_fmask != 0) {
6141 int stat_fflags = 0;
6143 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
6144 smb_fmask, &stat_fflags)) {
6145 /* Client asked to alter a flag we don't understand. */
6146 return NT_STATUS_INVALID_PARAMETER;
6149 if (fsp == NULL || S_ISLNK(smb_fname->st.st_ex_mode)) {
6150 DBG_WARNING("Can't change flags on symlink %s\n",
6151 smb_fname_str_dbg(smb_fname));
6152 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6154 if (SMB_VFS_FCHFLAGS(fsp, stat_fflags) != 0) {
6155 return map_nt_error_from_unix(errno);
6159 /* XXX: need to add support for changing the create_time here. You
6160 * can do this for paths on Darwin with setattrlist(2). The right way
6161 * to hook this up is probably by extending the VFS utimes interface.
6164 return NT_STATUS_OK;
6167 /****************************************************************************
6168 Create a directory with POSIX semantics.
6169 ****************************************************************************/
6171 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
6172 struct smb_request *req,
6175 struct smb_filename *smb_fname,
6176 int *pdata_return_size)
6178 NTSTATUS status = NT_STATUS_OK;
6179 uint32_t raw_unixmode = 0;
6180 mode_t unixmode = (mode_t)0;
6181 files_struct *fsp = NULL;
6182 uint16_t info_level_return = 0;
6184 char *pdata = *ppdata;
6185 struct smb2_create_blobs *posx = NULL;
6187 if (total_data < 18) {
6188 return NT_STATUS_INVALID_PARAMETER;
6191 raw_unixmode = IVAL(pdata,8);
6192 /* Next 4 bytes are not yet defined. */
6194 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6195 PERM_NEW_DIR, &unixmode);
6196 if (!NT_STATUS_IS_OK(status)) {
6200 status = make_smb2_posix_create_ctx(talloc_tos(), &posx, unixmode);
6201 if (!NT_STATUS_IS_OK(status)) {
6202 DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
6207 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
6208 smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
6210 status = SMB_VFS_CREATE_FILE(
6214 smb_fname, /* fname */
6215 FILE_READ_ATTRIBUTES, /* access_mask */
6216 FILE_SHARE_NONE, /* share_access */
6217 FILE_CREATE, /* create_disposition*/
6218 FILE_DIRECTORY_FILE, /* create_options */
6219 0, /* file_attributes */
6220 0, /* oplock_request */
6222 0, /* allocation_size */
6223 0, /* private_flags */
6228 posx, /* in_context_blobs */
6229 NULL); /* out_context_blobs */
6233 if (NT_STATUS_IS_OK(status)) {
6234 close_file_free(req, &fsp, NORMAL_CLOSE);
6237 info_level_return = SVAL(pdata,16);
6239 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6240 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6241 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6242 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6244 *pdata_return_size = 12;
6247 /* Realloc the data size */
6248 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6249 if (*ppdata == NULL) {
6250 *pdata_return_size = 0;
6251 return NT_STATUS_NO_MEMORY;
6255 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6256 SSVAL(pdata,2,0); /* No fnum. */
6257 SIVAL(pdata,4,info); /* Was directory created. */
6259 switch (info_level_return) {
6260 case SMB_QUERY_FILE_UNIX_BASIC:
6261 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6262 SSVAL(pdata,10,0); /* Padding. */
6263 store_file_unix_basic(conn, pdata + 12, fsp,
6266 case SMB_QUERY_FILE_UNIX_INFO2:
6267 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6268 SSVAL(pdata,10,0); /* Padding. */
6269 store_file_unix_basic_info2(conn, pdata + 12, fsp,
6273 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6274 SSVAL(pdata,10,0); /* Padding. */
6281 /****************************************************************************
6282 Open/Create a file with POSIX semantics.
6283 ****************************************************************************/
6285 #define SMB_O_RDONLY_MAPPING (FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA)
6286 #define SMB_O_WRONLY_MAPPING (FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA)
6288 static NTSTATUS smb_posix_open(connection_struct *conn,
6289 struct smb_request *req,
6292 struct smb_filename *smb_fname,
6293 int *pdata_return_size)
6295 bool extended_oplock_granted = False;
6296 char *pdata = *ppdata;
6298 uint32_t wire_open_mode = 0;
6299 uint32_t raw_unixmode = 0;
6300 uint32_t attributes = 0;
6301 uint32_t create_disp = 0;
6302 uint32_t access_mask = 0;
6303 uint32_t create_options = FILE_NON_DIRECTORY_FILE;
6304 NTSTATUS status = NT_STATUS_OK;
6305 mode_t unixmode = (mode_t)0;
6306 files_struct *fsp = NULL;
6307 int oplock_request = 0;
6309 uint16_t info_level_return = 0;
6310 struct smb2_create_blobs *posx = NULL;
6312 if (total_data < 18) {
6313 return NT_STATUS_INVALID_PARAMETER;
6316 flags = IVAL(pdata,0);
6317 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
6318 if (oplock_request) {
6319 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
6322 wire_open_mode = IVAL(pdata,4);
6324 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
6325 return smb_posix_mkdir(conn, req,
6332 switch (wire_open_mode & SMB_ACCMODE) {
6334 access_mask = SMB_O_RDONLY_MAPPING;
6337 access_mask = SMB_O_WRONLY_MAPPING;
6340 access_mask = (SMB_O_RDONLY_MAPPING|
6341 SMB_O_WRONLY_MAPPING);
6344 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
6345 (unsigned int)wire_open_mode ));
6346 return NT_STATUS_INVALID_PARAMETER;
6349 wire_open_mode &= ~SMB_ACCMODE;
6351 /* First take care of O_CREAT|O_EXCL interactions. */
6352 switch (wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) {
6353 case (SMB_O_CREAT | SMB_O_EXCL):
6354 /* File exists fail. File not exist create. */
6355 create_disp = FILE_CREATE;
6358 /* File exists open. File not exist create. */
6359 create_disp = FILE_OPEN_IF;
6362 /* O_EXCL on its own without O_CREAT is undefined.
6363 We deliberately ignore it as some versions of
6364 Linux CIFSFS can send a bare O_EXCL on the
6365 wire which other filesystems in the kernel
6366 ignore. See bug 9519 for details. */
6371 /* File exists open. File not exist fail. */
6372 create_disp = FILE_OPEN;
6375 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
6376 (unsigned int)wire_open_mode ));
6377 return NT_STATUS_INVALID_PARAMETER;
6380 /* Next factor in the effects of O_TRUNC. */
6381 wire_open_mode &= ~(SMB_O_CREAT | SMB_O_EXCL);
6383 if (wire_open_mode & SMB_O_TRUNC) {
6384 switch (create_disp) {
6386 /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
6387 /* Leave create_disp alone as
6388 (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
6390 /* File exists fail. File not exist create. */
6393 /* SMB_O_CREAT | SMB_O_TRUNC */
6394 /* File exists overwrite. File not exist create. */
6395 create_disp = FILE_OVERWRITE_IF;
6399 /* File exists overwrite. File not exist fail. */
6400 create_disp = FILE_OVERWRITE;
6403 /* Cannot get here. */
6404 smb_panic("smb_posix_open: logic error");
6405 return NT_STATUS_INVALID_PARAMETER;
6409 raw_unixmode = IVAL(pdata,8);
6410 /* Next 4 bytes are not yet defined. */
6412 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6413 (VALID_STAT(smb_fname->st) ?
6414 PERM_EXISTING_FILE : PERM_NEW_FILE),
6417 if (!NT_STATUS_IS_OK(status)) {
6421 status = make_smb2_posix_create_ctx(talloc_tos(), &posx, unixmode);
6422 if (!NT_STATUS_IS_OK(status)) {
6423 DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
6428 if (wire_open_mode & SMB_O_SYNC) {
6429 create_options |= FILE_WRITE_THROUGH;
6431 if (wire_open_mode & SMB_O_APPEND) {
6432 access_mask |= FILE_APPEND_DATA;
6434 if (wire_open_mode & SMB_O_DIRECT) {
6435 attributes |= FILE_FLAG_NO_BUFFERING;
6438 if ((wire_open_mode & SMB_O_DIRECTORY) ||
6439 VALID_STAT_OF_DIR(smb_fname->st)) {
6440 if (access_mask != SMB_O_RDONLY_MAPPING) {
6441 return NT_STATUS_FILE_IS_A_DIRECTORY;
6443 create_options &= ~FILE_NON_DIRECTORY_FILE;
6444 create_options |= FILE_DIRECTORY_FILE;
6447 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
6448 smb_fname_str_dbg(smb_fname),
6449 (unsigned int)wire_open_mode,
6450 (unsigned int)unixmode ));
6452 status = SMB_VFS_CREATE_FILE(
6456 smb_fname, /* fname */
6457 access_mask, /* access_mask */
6458 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6460 create_disp, /* create_disposition*/
6461 create_options, /* create_options */
6462 attributes, /* file_attributes */
6463 oplock_request, /* oplock_request */
6465 0, /* allocation_size */
6466 0, /* private_flags */
6471 posx, /* in_context_blobs */
6472 NULL); /* out_context_blobs */
6476 if (!NT_STATUS_IS_OK(status)) {
6480 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
6481 extended_oplock_granted = True;
6484 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
6485 extended_oplock_granted = True;
6488 info_level_return = SVAL(pdata,16);
6490 /* Allocate the correct return size. */
6492 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6493 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6494 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6495 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6497 *pdata_return_size = 12;
6500 /* Realloc the data size */
6501 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6502 if (*ppdata == NULL) {
6503 close_file_free(req, &fsp, ERROR_CLOSE);
6504 *pdata_return_size = 0;
6505 return NT_STATUS_NO_MEMORY;
6509 if (extended_oplock_granted) {
6510 if (flags & REQUEST_BATCH_OPLOCK) {
6511 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
6513 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
6515 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
6516 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
6518 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6521 SSVAL(pdata,2,fsp->fnum);
6522 SIVAL(pdata,4,info); /* Was file created etc. */
6524 switch (info_level_return) {
6525 case SMB_QUERY_FILE_UNIX_BASIC:
6526 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6527 SSVAL(pdata,10,0); /* padding. */
6528 store_file_unix_basic(conn, pdata + 12, fsp,
6531 case SMB_QUERY_FILE_UNIX_INFO2:
6532 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6533 SSVAL(pdata,10,0); /* padding. */
6534 store_file_unix_basic_info2(conn, pdata + 12, fsp,
6538 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6539 SSVAL(pdata,10,0); /* padding. */
6542 return NT_STATUS_OK;
6545 /****************************************************************************
6546 Delete a file with POSIX semantics.
6547 ****************************************************************************/
6549 static NTSTATUS smb_posix_unlink(connection_struct *conn,
6550 struct smb_request *req,
6553 struct smb_filename *smb_fname)
6555 NTSTATUS status = NT_STATUS_OK;
6556 files_struct *fsp = NULL;
6560 int create_options = 0;
6561 struct share_mode_lock *lck = NULL;
6562 bool other_nonposix_opens;
6563 struct smb2_create_blobs *posx = NULL;
6565 if (total_data < 2) {
6566 return NT_STATUS_INVALID_PARAMETER;
6569 flags = SVAL(pdata,0);
6571 if (!VALID_STAT(smb_fname->st)) {
6572 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6575 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
6576 !VALID_STAT_OF_DIR(smb_fname->st)) {
6577 return NT_STATUS_NOT_A_DIRECTORY;
6580 DEBUG(10,("smb_posix_unlink: %s %s\n",
6581 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
6582 smb_fname_str_dbg(smb_fname)));
6584 if (VALID_STAT_OF_DIR(smb_fname->st)) {
6585 create_options |= FILE_DIRECTORY_FILE;
6588 status = make_smb2_posix_create_ctx(talloc_tos(), &posx, 0777);
6589 if (!NT_STATUS_IS_OK(status)) {
6590 DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
6595 status = SMB_VFS_CREATE_FILE(
6599 smb_fname, /* fname */
6600 DELETE_ACCESS, /* access_mask */
6601 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6603 FILE_OPEN, /* create_disposition*/
6604 create_options, /* create_options */
6605 0, /* file_attributes */
6606 0, /* oplock_request */
6608 0, /* allocation_size */
6609 0, /* private_flags */
6614 posx, /* in_context_blobs */
6615 NULL); /* out_context_blobs */
6619 if (!NT_STATUS_IS_OK(status)) {
6624 * Don't lie to client. If we can't really delete due to
6625 * non-POSIX opens return SHARING_VIOLATION.
6628 lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
6630 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
6631 "lock for file %s\n", fsp_str_dbg(fsp)));
6632 close_file_free(req, &fsp, NORMAL_CLOSE);
6633 return NT_STATUS_INVALID_PARAMETER;
6636 other_nonposix_opens = has_other_nonposix_opens(lck, fsp);
6637 if (other_nonposix_opens) {
6638 /* Fail with sharing violation. */
6640 close_file_free(req, &fsp, NORMAL_CLOSE);
6641 return NT_STATUS_SHARING_VIOLATION;
6645 * Set the delete on close.
6647 status = smb_set_file_disposition_info(conn,
6655 if (!NT_STATUS_IS_OK(status)) {
6656 close_file_free(req, &fsp, NORMAL_CLOSE);
6659 return close_file_free(req, &fsp, NORMAL_CLOSE);
6662 static NTSTATUS smbd_do_posix_setfilepathinfo(struct connection_struct *conn,
6663 struct smb_request *req,
6664 TALLOC_CTX *mem_ctx,
6665 uint16_t info_level,
6666 struct smb_filename *smb_fname,
6672 char *pdata = *ppdata;
6673 NTSTATUS status = NT_STATUS_OK;
6674 int data_return_size = 0;
6678 if (!CAN_WRITE(conn)) {
6679 /* Allow POSIX opens. The open path will deny
6680 * any non-readonly opens. */
6681 if (info_level != SMB_POSIX_PATH_OPEN) {
6682 return NT_STATUS_DOS(ERRSRV, ERRaccess);
6686 DBG_DEBUG("file=%s (%s) info_level=%d totdata=%d\n",
6687 smb_fname_str_dbg(smb_fname),
6692 switch (info_level) {
6693 case SMB_SET_FILE_UNIX_BASIC:
6695 status = smb_set_file_unix_basic(conn, req,
6703 case SMB_SET_FILE_UNIX_INFO2:
6705 status = smb_set_file_unix_info2(conn, req,
6713 case SMB_SET_FILE_UNIX_LINK:
6715 if (smb_fname == NULL) {
6716 /* We must have a pathname for this. */
6717 return NT_STATUS_INVALID_LEVEL;
6719 status = smb_set_file_unix_link(conn, req, pdata,
6720 total_data, smb_fname);
6724 case SMB_SET_FILE_UNIX_HLINK:
6726 if (smb_fname == NULL) {
6727 /* We must have a pathname for this. */
6728 return NT_STATUS_INVALID_LEVEL;
6730 status = smb_set_file_unix_hlink(conn, req,
6736 #if defined(HAVE_POSIX_ACLS)
6737 case SMB_SET_POSIX_ACL:
6739 status = smb_set_posix_acl(conn,
6749 #if defined(WITH_SMB1SERVER)
6750 case SMB_SET_POSIX_LOCK:
6753 return NT_STATUS_INVALID_LEVEL;
6755 status = smb_set_posix_lock(conn, req,
6756 pdata, total_data, fsp);
6761 case SMB_POSIX_PATH_OPEN:
6763 if (smb_fname == NULL) {
6764 /* We must have a pathname for this. */
6765 return NT_STATUS_INVALID_LEVEL;
6768 status = smb_posix_open(conn, req,
6776 case SMB_POSIX_PATH_UNLINK:
6778 if (smb_fname == NULL) {
6779 /* We must have a pathname for this. */
6780 return NT_STATUS_INVALID_LEVEL;
6783 status = smb_posix_unlink(conn, req,
6791 return NT_STATUS_INVALID_LEVEL;
6794 if (!NT_STATUS_IS_OK(status)) {
6798 *ret_data_size = data_return_size;
6799 return NT_STATUS_OK;
6802 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
6803 struct smb_request *req,
6804 TALLOC_CTX *mem_ctx,
6805 uint16_t info_level,
6807 struct smb_filename *smb_fname,
6808 char **ppdata, int total_data,
6811 char *pdata = *ppdata;
6812 NTSTATUS status = NT_STATUS_OK;
6813 int data_return_size = 0;
6815 if (INFO_LEVEL_IS_UNIX(info_level)) {
6816 if (!lp_smb1_unix_extensions()) {
6817 return NT_STATUS_INVALID_LEVEL;
6819 if (!req->posix_pathnames) {
6820 return NT_STATUS_INVALID_LEVEL;
6822 status = smbd_do_posix_setfilepathinfo(conn,
6831 if (!NT_STATUS_IS_OK(status)) {
6834 *ret_data_size = data_return_size;
6835 return NT_STATUS_OK;
6840 DEBUG(3,("smbd_do_setfilepathinfo: %s (%s) info_level=%d "
6841 "totdata=%d\n", smb_fname_str_dbg(smb_fname),
6843 info_level, total_data));
6845 switch (info_level) {
6847 case SMB_INFO_STANDARD:
6849 status = smb_set_info_standard(conn,
6857 case SMB_INFO_SET_EA:
6859 status = smb_info_set_ea(conn,
6867 case SMB_SET_FILE_BASIC_INFO:
6868 case SMB_FILE_BASIC_INFORMATION:
6870 status = smb_set_file_basic_info(conn,
6878 case SMB_FILE_ALLOCATION_INFORMATION:
6879 case SMB_SET_FILE_ALLOCATION_INFO:
6881 status = smb_set_file_allocation_info(conn, req,
6889 case SMB_FILE_END_OF_FILE_INFORMATION:
6890 case SMB_SET_FILE_END_OF_FILE_INFO:
6893 * XP/Win7 both fail after the createfile with
6894 * SMB_SET_FILE_END_OF_FILE_INFO but not
6895 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
6896 * The level is known here, so pass it down
6900 (info_level == SMB_SET_FILE_END_OF_FILE_INFO);
6902 status = smb_set_file_end_of_file_info(conn, req,
6911 case SMB_FILE_DISPOSITION_INFORMATION:
6912 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
6915 /* JRA - We used to just ignore this on a path ?
6916 * Shouldn't this be invalid level on a pathname
6919 if (tran_call != TRANSACT2_SETFILEINFO) {
6920 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6923 status = smb_set_file_disposition_info(conn,
6931 case SMB_FILE_POSITION_INFORMATION:
6933 status = smb_file_position_information(conn,
6940 case SMB_FILE_FULL_EA_INFORMATION:
6942 status = smb_set_file_full_ea_info(conn,
6949 /* From tridge Samba4 :
6950 * MODE_INFORMATION in setfileinfo (I have no
6951 * idea what "mode information" on a file is - it takes a value of 0,
6952 * 2, 4 or 6. What could it be?).
6955 case SMB_FILE_MODE_INFORMATION:
6957 status = smb_file_mode_information(conn,
6963 /* [MS-SMB2] 3.3.5.21.1 states we MUST fail with STATUS_NOT_SUPPORTED. */
6964 case SMB_FILE_VALID_DATA_LENGTH_INFORMATION:
6965 case SMB_FILE_SHORT_NAME_INFORMATION:
6966 return NT_STATUS_NOT_SUPPORTED;
6968 case SMB_FILE_RENAME_INFORMATION:
6970 status = smb_file_rename_information(conn, req,
6976 case SMB2_FILE_RENAME_INFORMATION_INTERNAL:
6978 /* SMB2 rename information. */
6979 status = smb2_file_rename_information(conn, req,
6985 case SMB_FILE_LINK_INFORMATION:
6987 status = smb_file_link_information(conn, req,
6994 return NT_STATUS_INVALID_LEVEL;
6997 if (!NT_STATUS_IS_OK(status)) {
7001 *ret_data_size = data_return_size;
7002 return NT_STATUS_OK;
7005 static uint32_t generate_volume_serial_number(
7006 const struct loadparm_substitution *lp_sub,
7009 int serial = lp_volume_serial_number(snum);
7010 return serial != -1 ? serial:
7011 str_checksum(lp_servicename(talloc_tos(), lp_sub, snum)) ^
7012 (str_checksum(get_local_machine_name())<<16);