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 const struct smb_filename *smb_fname_old,
4245 struct smb_filename *smb_fname_new)
4247 NTSTATUS status = NT_STATUS_OK;
4250 struct smb_filename *parent_fname_old = NULL;
4251 struct smb_filename *base_name_old = NULL;
4252 struct smb_filename *parent_fname_new = NULL;
4253 struct smb_filename *base_name_new = NULL;
4255 /* source must already exist. */
4256 if (!VALID_STAT(smb_fname_old->st)) {
4257 status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
4261 /* No links from a directory. */
4262 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
4263 status = NT_STATUS_FILE_IS_A_DIRECTORY;
4267 /* Setting a hardlink to/from a stream isn't currently supported. */
4268 ok = is_ntfs_stream_smb_fname(smb_fname_old);
4270 DBG_DEBUG("Old name has streams\n");
4271 status = NT_STATUS_INVALID_PARAMETER;
4274 ok = is_ntfs_stream_smb_fname(smb_fname_new);
4276 DBG_DEBUG("New name has streams\n");
4277 status = NT_STATUS_INVALID_PARAMETER;
4281 status = parent_pathref(talloc_tos(),
4286 if (!NT_STATUS_IS_OK(status)) {
4290 status = parent_pathref(talloc_tos(),
4295 if (!NT_STATUS_IS_OK(status)) {
4299 if (VALID_STAT(smb_fname_new->st)) {
4300 if (overwrite_if_exists) {
4301 if (S_ISDIR(smb_fname_new->st.st_ex_mode)) {
4302 status = NT_STATUS_FILE_IS_A_DIRECTORY;
4305 status = unlink_internals(conn,
4307 FILE_ATTRIBUTE_NORMAL,
4309 if (!NT_STATUS_IS_OK(status)) {
4313 /* Disallow if newname already exists. */
4314 status = NT_STATUS_OBJECT_NAME_COLLISION;
4319 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
4320 smb_fname_old->base_name, smb_fname_new->base_name));
4322 ret = SMB_VFS_LINKAT(conn,
4323 parent_fname_old->fsp,
4325 parent_fname_new->fsp,
4330 status = map_nt_error_from_unix(errno);
4331 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
4332 nt_errstr(status), smb_fname_old->base_name,
4333 smb_fname_new->base_name));
4338 TALLOC_FREE(parent_fname_old);
4339 TALLOC_FREE(parent_fname_new);
4343 /****************************************************************************
4344 Deal with setting the time from any of the setfilepathinfo functions.
4345 NOTE !!!! The check for FILE_WRITE_ATTRIBUTES access must be done *before*
4346 calling this function.
4347 ****************************************************************************/
4349 NTSTATUS smb_set_file_time(connection_struct *conn,
4351 struct smb_filename *smb_fname,
4352 struct smb_file_time *ft,
4353 bool setting_write_time)
4355 struct files_struct *set_fsp = NULL;
4356 struct timeval_buf tbuf[4];
4358 FILE_NOTIFY_CHANGE_LAST_ACCESS
4359 |FILE_NOTIFY_CHANGE_LAST_WRITE
4360 |FILE_NOTIFY_CHANGE_CREATION;
4363 if (!VALID_STAT(smb_fname->st)) {
4364 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4369 return NT_STATUS_OK;
4372 set_fsp = metadata_fsp(fsp);
4374 /* get some defaults (no modifications) if any info is zero or -1. */
4375 if (is_omit_timespec(&ft->create_time)) {
4376 action &= ~FILE_NOTIFY_CHANGE_CREATION;
4379 if (is_omit_timespec(&ft->atime)) {
4380 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
4383 if (is_omit_timespec(&ft->mtime)) {
4384 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4387 if (!setting_write_time) {
4388 /* ft->mtime comes from change time, not write time. */
4389 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4392 /* Ensure the resolution is the correct for
4393 * what we can store on this filesystem. */
4395 round_timespec(conn->ts_res, &ft->create_time);
4396 round_timespec(conn->ts_res, &ft->ctime);
4397 round_timespec(conn->ts_res, &ft->atime);
4398 round_timespec(conn->ts_res, &ft->mtime);
4400 DBG_DEBUG("smb_set_filetime: actime: %s\n ",
4401 timespec_string_buf(&ft->atime, true, &tbuf[0]));
4402 DBG_DEBUG("smb_set_filetime: modtime: %s\n ",
4403 timespec_string_buf(&ft->mtime, true, &tbuf[1]));
4404 DBG_DEBUG("smb_set_filetime: ctime: %s\n ",
4405 timespec_string_buf(&ft->ctime, true, &tbuf[2]));
4406 DBG_DEBUG("smb_set_file_time: createtime: %s\n ",
4407 timespec_string_buf(&ft->create_time, true, &tbuf[3]));
4409 if (setting_write_time) {
4411 * This was a Windows setfileinfo on an open file.
4412 * NT does this a lot. We also need to
4413 * set the time here, as it can be read by
4414 * FindFirst/FindNext and with the patch for bug #2045
4415 * in smbd/fileio.c it ensures that this timestamp is
4416 * kept sticky even after a write. We save the request
4417 * away and will set it on file close and after a write. JRA.
4420 DBG_DEBUG("setting pending modtime to %s\n",
4421 timespec_string_buf(&ft->mtime, true, &tbuf[0]));
4423 if (set_fsp != NULL) {
4424 set_sticky_write_time_fsp(set_fsp, ft->mtime);
4426 set_sticky_write_time_path(
4427 vfs_file_id_from_sbuf(conn, &smb_fname->st),
4432 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
4434 ret = file_ntimes(conn, set_fsp, ft);
4436 return map_nt_error_from_unix(errno);
4439 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
4440 smb_fname->base_name);
4441 return NT_STATUS_OK;
4444 /****************************************************************************
4445 Deal with setting the dosmode from any of the setfilepathinfo functions.
4446 NB. The check for FILE_WRITE_ATTRIBUTES access on this path must have been
4447 done before calling this function.
4448 ****************************************************************************/
4450 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
4451 struct files_struct *fsp,
4454 struct files_struct *dos_fsp = NULL;
4455 uint32_t current_dosmode;
4458 if (!VALID_STAT(fsp->fsp_name->st)) {
4459 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4462 dos_fsp = metadata_fsp(fsp);
4465 if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
4466 dosmode |= FILE_ATTRIBUTE_DIRECTORY;
4468 dosmode &= ~FILE_ATTRIBUTE_DIRECTORY;
4472 DBG_DEBUG("dosmode: 0x%" PRIx32 "\n", dosmode);
4474 /* check the mode isn't different, before changing it */
4476 return NT_STATUS_OK;
4478 current_dosmode = fdos_mode(dos_fsp);
4479 if (dosmode == current_dosmode) {
4480 return NT_STATUS_OK;
4483 DBG_DEBUG("file %s : setting dos mode 0x%" PRIx32 "\n",
4484 fsp_str_dbg(dos_fsp), dosmode);
4486 ret = file_set_dosmode(conn, dos_fsp->fsp_name, dosmode, NULL, false);
4488 DBG_WARNING("file_set_dosmode of %s failed: %s\n",
4489 fsp_str_dbg(dos_fsp), strerror(errno));
4490 return map_nt_error_from_unix(errno);
4493 return NT_STATUS_OK;
4496 /****************************************************************************
4497 Deal with setting the size from any of the setfilepathinfo functions.
4498 ****************************************************************************/
4500 static NTSTATUS smb_set_file_size(connection_struct *conn,
4501 struct smb_request *req,
4503 struct smb_filename *smb_fname,
4504 const SMB_STRUCT_STAT *psbuf,
4506 bool fail_after_createfile)
4508 NTSTATUS status = NT_STATUS_OK;
4509 files_struct *new_fsp = NULL;
4511 if (!VALID_STAT(*psbuf)) {
4512 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4515 DBG_INFO("size: %"PRIu64", file_size_stat=%"PRIu64"\n",
4517 get_file_size_stat(psbuf));
4519 if (size == get_file_size_stat(psbuf)) {
4521 return NT_STATUS_OK;
4523 if (!fsp->fsp_flags.modified) {
4524 return NT_STATUS_OK;
4526 trigger_write_time_update_immediate(fsp);
4527 return NT_STATUS_OK;
4530 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
4531 smb_fname_str_dbg(smb_fname), (double)size));
4534 !fsp->fsp_flags.is_pathref &&
4535 fsp_get_io_fd(fsp) != -1)
4537 /* Handle based call. */
4538 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
4539 return NT_STATUS_ACCESS_DENIED;
4542 if (vfs_set_filelen(fsp, size) == -1) {
4543 return map_nt_error_from_unix(errno);
4545 trigger_write_time_update_immediate(fsp);
4546 return NT_STATUS_OK;
4549 status = SMB_VFS_CREATE_FILE(
4553 smb_fname, /* fname */
4554 FILE_WRITE_DATA, /* access_mask */
4555 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
4557 FILE_OPEN, /* create_disposition*/
4558 0, /* create_options */
4559 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
4560 0, /* oplock_request */
4562 0, /* allocation_size */
4563 0, /* private_flags */
4566 &new_fsp, /* result */
4568 NULL, NULL); /* create context */
4570 if (!NT_STATUS_IS_OK(status)) {
4571 /* NB. We check for open_was_deferred in the caller. */
4575 /* See RAW-SFILEINFO-END-OF-FILE */
4576 if (fail_after_createfile) {
4577 close_file_free(req, &new_fsp, NORMAL_CLOSE);
4578 return NT_STATUS_INVALID_LEVEL;
4581 if (vfs_set_filelen(new_fsp, size) == -1) {
4582 status = map_nt_error_from_unix(errno);
4583 close_file_free(req, &new_fsp, NORMAL_CLOSE);
4587 trigger_write_time_update_immediate(new_fsp);
4588 close_file_free(req, &new_fsp, NORMAL_CLOSE);
4589 return NT_STATUS_OK;
4592 /****************************************************************************
4593 Deal with SMB_INFO_SET_EA.
4594 ****************************************************************************/
4596 static NTSTATUS smb_info_set_ea(connection_struct *conn,
4600 struct smb_filename *smb_fname)
4602 struct ea_list *ea_list = NULL;
4603 TALLOC_CTX *ctx = NULL;
4604 NTSTATUS status = NT_STATUS_OK;
4606 if (total_data < 10) {
4608 /* OS/2 workplace shell seems to send SET_EA requests of "null"
4609 length. They seem to have no effect. Bug #3212. JRA */
4611 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
4612 /* We're done. We only get EA info in this call. */
4613 return NT_STATUS_OK;
4616 return NT_STATUS_INVALID_PARAMETER;
4619 if (IVAL(pdata,0) > total_data) {
4620 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
4621 IVAL(pdata,0), (unsigned int)total_data));
4622 return NT_STATUS_INVALID_PARAMETER;
4626 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
4628 return NT_STATUS_INVALID_PARAMETER;
4633 * The only way fsp can be NULL here is if
4634 * smb_fname points at a symlink and
4635 * and we're in POSIX context.
4636 * Ensure this is the case.
4638 * In this case we cannot set the EA.
4640 SMB_ASSERT(smb_fname->flags & SMB_FILENAME_POSIX_PATH);
4641 return NT_STATUS_ACCESS_DENIED;
4644 status = set_ea(conn, fsp, ea_list);
4649 /****************************************************************************
4650 Deal with SMB_FILE_FULL_EA_INFORMATION set.
4651 ****************************************************************************/
4653 static NTSTATUS smb_set_file_full_ea_info(connection_struct *conn,
4658 struct ea_list *ea_list = NULL;
4662 return NT_STATUS_INVALID_HANDLE;
4665 if (!lp_ea_support(SNUM(conn))) {
4666 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
4667 "EA's not supported.\n",
4668 (unsigned int)total_data));
4669 return NT_STATUS_EAS_NOT_SUPPORTED;
4672 if (total_data < 10) {
4673 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
4675 (unsigned int)total_data));
4676 return NT_STATUS_INVALID_PARAMETER;
4679 ea_list = read_nttrans_ea_list(talloc_tos(),
4684 return NT_STATUS_INVALID_PARAMETER;
4687 status = set_ea(conn, fsp, ea_list);
4689 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
4690 smb_fname_str_dbg(fsp->fsp_name),
4691 nt_errstr(status) ));
4697 /****************************************************************************
4698 Deal with SMB_SET_FILE_DISPOSITION_INFO.
4699 ****************************************************************************/
4701 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
4705 struct smb_filename *smb_fname)
4707 NTSTATUS status = NT_STATUS_OK;
4708 bool delete_on_close;
4709 uint32_t dosmode = 0;
4711 if (total_data < 1) {
4712 return NT_STATUS_INVALID_PARAMETER;
4716 return NT_STATUS_INVALID_HANDLE;
4719 delete_on_close = (CVAL(pdata,0) ? True : False);
4720 dosmode = fdos_mode(fsp);
4722 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
4723 "delete_on_close = %u\n",
4724 smb_fname_str_dbg(smb_fname),
4725 (unsigned int)dosmode,
4726 (unsigned int)delete_on_close ));
4728 if (delete_on_close) {
4729 status = can_set_delete_on_close(fsp, dosmode);
4730 if (!NT_STATUS_IS_OK(status)) {
4735 /* The set is across all open files on this dev/inode pair. */
4736 if (!set_delete_on_close(fsp, delete_on_close,
4737 conn->session_info->security_token,
4738 conn->session_info->unix_token)) {
4739 return NT_STATUS_ACCESS_DENIED;
4741 return NT_STATUS_OK;
4744 /****************************************************************************
4745 Deal with SMB_FILE_POSITION_INFORMATION.
4746 ****************************************************************************/
4748 static NTSTATUS smb_file_position_information(connection_struct *conn,
4753 uint64_t position_information;
4755 if (total_data < 8) {
4756 return NT_STATUS_INVALID_PARAMETER;
4760 /* Ignore on pathname based set. */
4761 return NT_STATUS_OK;
4764 position_information = (uint64_t)IVAL(pdata,0);
4765 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
4767 DEBUG(10,("smb_file_position_information: Set file position "
4768 "information for file %s to %.0f\n", fsp_str_dbg(fsp),
4769 (double)position_information));
4770 fh_set_position_information(fsp->fh, position_information);
4771 return NT_STATUS_OK;
4774 /****************************************************************************
4775 Deal with SMB_FILE_MODE_INFORMATION.
4776 ****************************************************************************/
4778 static NTSTATUS smb_file_mode_information(connection_struct *conn,
4784 if (total_data < 4) {
4785 return NT_STATUS_INVALID_PARAMETER;
4787 mode = IVAL(pdata,0);
4788 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
4789 return NT_STATUS_INVALID_PARAMETER;
4791 return NT_STATUS_OK;
4794 /****************************************************************************
4795 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
4796 ****************************************************************************/
4798 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
4799 struct smb_request *req,
4802 struct smb_filename *new_smb_fname)
4804 char *link_target = NULL;
4805 struct smb_filename target_fname;
4806 TALLOC_CTX *ctx = talloc_tos();
4809 struct smb_filename *parent_fname = NULL;
4810 struct smb_filename *base_name = NULL;
4812 /* Set a symbolic link. */
4813 /* Don't allow this if follow links is false. */
4815 if (total_data == 0) {
4816 return NT_STATUS_INVALID_PARAMETER;
4819 if (!lp_follow_symlinks(SNUM(conn))) {
4820 return NT_STATUS_ACCESS_DENIED;
4823 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
4824 total_data, STR_TERMINATE);
4827 return NT_STATUS_INVALID_PARAMETER;
4830 target_fname = (struct smb_filename) {
4831 .base_name = link_target,
4834 /* Removes @GMT tokens if any */
4835 status = canonicalize_snapshot_path(&target_fname, UCF_GMT_PATHNAME, 0);
4836 if (!NT_STATUS_IS_OK(status)) {
4840 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
4841 new_smb_fname->base_name, link_target ));
4843 status = parent_pathref(talloc_tos(),
4848 if (!NT_STATUS_IS_OK(status)) {
4852 ret = SMB_VFS_SYMLINKAT(conn,
4857 TALLOC_FREE(parent_fname);
4858 return map_nt_error_from_unix(errno);
4861 TALLOC_FREE(parent_fname);
4862 return NT_STATUS_OK;
4865 /****************************************************************************
4866 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
4867 ****************************************************************************/
4869 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
4870 struct smb_request *req,
4871 const char *pdata, int total_data,
4872 struct smb_filename *smb_fname_new)
4874 char *oldname = NULL;
4875 struct smb_filename *smb_fname_old = NULL;
4876 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
4877 TALLOC_CTX *ctx = talloc_tos();
4878 NTSTATUS status = NT_STATUS_OK;
4880 /* Set a hard link. */
4881 if (total_data == 0) {
4882 return NT_STATUS_INVALID_PARAMETER;
4885 if (req->posix_pathnames) {
4886 srvstr_get_path_posix(ctx,
4895 srvstr_get_path(ctx,
4904 if (!NT_STATUS_IS_OK(status)) {
4908 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
4909 smb_fname_str_dbg(smb_fname_new), oldname));
4911 status = filename_convert(ctx,
4917 if (!NT_STATUS_IS_OK(status)) {
4921 return hardlink_internals(ctx, conn, req, false,
4922 smb_fname_old, smb_fname_new);
4925 /****************************************************************************
4926 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
4927 ****************************************************************************/
4929 static NTSTATUS smb2_file_rename_information(connection_struct *conn,
4930 struct smb_request *req,
4934 struct smb_filename *smb_fname_src)
4938 char *newname = NULL;
4939 struct smb_filename *smb_fname_dst = NULL;
4940 const char *dst_original_lcomp = NULL;
4941 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
4942 NTSTATUS status = NT_STATUS_OK;
4943 TALLOC_CTX *ctx = talloc_tos();
4946 return NT_STATUS_INVALID_HANDLE;
4949 if (total_data < 20) {
4950 return NT_STATUS_INVALID_PARAMETER;
4953 overwrite = (CVAL(pdata,0) ? True : False);
4954 len = IVAL(pdata,16);
4956 if (len > (total_data - 20) || (len == 0)) {
4957 return NT_STATUS_INVALID_PARAMETER;
4960 if (req->posix_pathnames) {
4961 srvstr_get_path_posix(ctx,
4970 srvstr_get_path(ctx,
4979 if (!NT_STATUS_IS_OK(status)) {
4983 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
4986 status = filename_convert(ctx,
4992 if (!NT_STATUS_IS_OK(status)) {
4996 if (fsp->base_fsp) {
4997 /* newname must be a stream name. */
4998 if (newname[0] != ':') {
4999 return NT_STATUS_NOT_SUPPORTED;
5002 /* Create an smb_fname to call rename_internals_fsp() with. */
5003 smb_fname_dst = synthetic_smb_fname(talloc_tos(),
5004 fsp->base_fsp->fsp_name->base_name,
5007 fsp->base_fsp->fsp_name->twrp,
5008 fsp->base_fsp->fsp_name->flags);
5009 if (smb_fname_dst == NULL) {
5010 status = NT_STATUS_NO_MEMORY;
5016 * Set the original last component, since
5017 * rename_internals_fsp() requires it.
5019 dst_original_lcomp = get_original_lcomp(smb_fname_dst,
5023 if (dst_original_lcomp == NULL) {
5024 status = NT_STATUS_NO_MEMORY;
5028 DEBUG(10,("smb2_file_rename_information: "
5029 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
5030 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
5031 smb_fname_str_dbg(smb_fname_dst)));
5032 status = rename_internals_fsp(conn,
5036 (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM),
5040 TALLOC_FREE(smb_fname_dst);
5044 static NTSTATUS smb_file_link_information(connection_struct *conn,
5045 struct smb_request *req,
5049 struct smb_filename *smb_fname_src)
5053 char *newname = NULL;
5054 struct smb_filename *smb_fname_dst = NULL;
5055 NTSTATUS status = NT_STATUS_OK;
5056 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
5057 TALLOC_CTX *ctx = talloc_tos();
5060 return NT_STATUS_INVALID_HANDLE;
5063 if (total_data < 20) {
5064 return NT_STATUS_INVALID_PARAMETER;
5067 overwrite = (CVAL(pdata,0) ? true : false);
5068 len = IVAL(pdata,16);
5070 if (len > (total_data - 20) || (len == 0)) {
5071 return NT_STATUS_INVALID_PARAMETER;
5074 if (smb_fname_src->flags & SMB_FILENAME_POSIX_PATH) {
5075 srvstr_get_path_posix(ctx,
5083 ucf_flags |= UCF_POSIX_PATHNAMES;
5085 srvstr_get_path(ctx,
5094 if (!NT_STATUS_IS_OK(status)) {
5098 DEBUG(10,("smb_file_link_information: got name |%s|\n",
5101 status = filename_convert(ctx,
5107 if (!NT_STATUS_IS_OK(status)) {
5111 if (fsp->base_fsp) {
5112 /* No stream names. */
5113 return NT_STATUS_NOT_SUPPORTED;
5116 DEBUG(10,("smb_file_link_information: "
5117 "SMB_FILE_LINK_INFORMATION (%s) %s -> %s\n",
5118 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
5119 smb_fname_str_dbg(smb_fname_dst)));
5120 status = hardlink_internals(ctx,
5127 TALLOC_FREE(smb_fname_dst);
5131 /****************************************************************************
5132 Deal with SMB_FILE_RENAME_INFORMATION.
5133 ****************************************************************************/
5135 static NTSTATUS smb_file_rename_information(connection_struct *conn,
5136 struct smb_request *req,
5140 struct smb_filename *smb_fname_src)
5145 char *newname = NULL;
5146 struct smb_filename *smb_fname_dst = NULL;
5147 const char *dst_original_lcomp = NULL;
5148 NTSTATUS status = NT_STATUS_OK;
5150 TALLOC_CTX *ctx = talloc_tos();
5152 if (total_data < 13) {
5153 return NT_STATUS_INVALID_PARAMETER;
5156 overwrite = (CVAL(pdata,0) ? True : False);
5157 root_fid = IVAL(pdata,4);
5158 len = IVAL(pdata,8);
5160 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
5161 return NT_STATUS_INVALID_PARAMETER;
5164 if (req->posix_pathnames) {
5165 srvstr_get_path_posix(ctx,
5174 srvstr_get_path(ctx,
5183 if (!NT_STATUS_IS_OK(status)) {
5187 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
5190 /* Check the new name has no '/' characters. */
5191 if (strchr_m(newname, '/')) {
5192 return NT_STATUS_NOT_SUPPORTED;
5195 if (fsp && fsp->base_fsp) {
5196 /* newname must be a stream name. */
5197 if (newname[0] != ':') {
5198 return NT_STATUS_NOT_SUPPORTED;
5201 /* Create an smb_fname to call rename_internals_fsp() with. */
5202 smb_fname_dst = synthetic_smb_fname(talloc_tos(),
5203 fsp->base_fsp->fsp_name->base_name,
5206 fsp->base_fsp->fsp_name->twrp,
5207 fsp->base_fsp->fsp_name->flags);
5208 if (smb_fname_dst == NULL) {
5209 status = NT_STATUS_NO_MEMORY;
5214 * Get the original last component, since
5215 * rename_internals_fsp() requires it.
5217 dst_original_lcomp = get_original_lcomp(smb_fname_dst,
5221 if (dst_original_lcomp == NULL) {
5222 status = NT_STATUS_NO_MEMORY;
5228 * Build up an smb_fname_dst based on the filename passed in.
5229 * We basically just strip off the last component, and put on
5230 * the newname instead.
5232 char *base_name = NULL;
5233 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
5235 /* newname must *not* be a stream name. */
5236 if (newname[0] == ':') {
5237 return NT_STATUS_NOT_SUPPORTED;
5241 * Strip off the last component (filename) of the path passed
5244 base_name = talloc_strdup(ctx, smb_fname_src->base_name);
5246 return NT_STATUS_NO_MEMORY;
5248 p = strrchr_m(base_name, '/');
5252 base_name = talloc_strdup(ctx, "");
5254 return NT_STATUS_NO_MEMORY;
5257 /* Append the new name. */
5258 base_name = talloc_asprintf_append(base_name,
5262 return NT_STATUS_NO_MEMORY;
5265 status = filename_convert(ctx,
5272 if (!NT_STATUS_IS_OK(status)) {
5275 dst_original_lcomp = get_original_lcomp(smb_fname_dst,
5279 if (dst_original_lcomp == NULL) {
5280 status = NT_STATUS_NO_MEMORY;
5285 if (fsp != NULL && fsp->fsp_flags.is_fsa) {
5286 DEBUG(10,("smb_file_rename_information: "
5287 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
5288 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
5289 smb_fname_str_dbg(smb_fname_dst)));
5290 status = rename_internals_fsp(conn,
5297 DEBUG(10,("smb_file_rename_information: "
5298 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
5299 smb_fname_str_dbg(smb_fname_src),
5300 smb_fname_str_dbg(smb_fname_dst)));
5301 status = rename_internals(ctx,
5309 FILE_WRITE_ATTRIBUTES);
5312 TALLOC_FREE(smb_fname_dst);
5316 /****************************************************************************
5317 Deal with SMB_SET_POSIX_ACL.
5318 ****************************************************************************/
5320 #if defined(HAVE_POSIX_ACLS)
5321 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
5322 struct smb_request *req,
5326 struct smb_filename *smb_fname)
5328 uint16_t posix_acl_version;
5329 uint16_t num_file_acls;
5330 uint16_t num_def_acls;
5331 bool valid_file_acls = true;
5332 bool valid_def_acls = true;
5334 unsigned int size_needed;
5335 unsigned int total_data;
5336 bool close_fsp = false;
5338 if (total_data_in < 0) {
5339 status = NT_STATUS_INVALID_PARAMETER;
5343 total_data = total_data_in;
5345 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
5346 status = NT_STATUS_INVALID_PARAMETER;
5349 posix_acl_version = SVAL(pdata,0);
5350 num_file_acls = SVAL(pdata,2);
5351 num_def_acls = SVAL(pdata,4);
5353 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5354 valid_file_acls = false;
5358 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5359 valid_def_acls = false;
5363 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
5364 status = NT_STATUS_INVALID_PARAMETER;
5369 if (num_file_acls + num_def_acls < num_file_acls) {
5370 status = NT_STATUS_INVALID_PARAMETER;
5374 size_needed = num_file_acls + num_def_acls;
5377 * (size_needed * SMB_POSIX_ACL_ENTRY_SIZE) must be less
5378 * than UINT_MAX, so check by division.
5380 if (size_needed > (UINT_MAX/SMB_POSIX_ACL_ENTRY_SIZE)) {
5381 status = NT_STATUS_INVALID_PARAMETER;
5385 size_needed = size_needed*SMB_POSIX_ACL_ENTRY_SIZE;
5386 if (size_needed + SMB_POSIX_ACL_HEADER_SIZE < size_needed) {
5387 status = NT_STATUS_INVALID_PARAMETER;
5390 size_needed += SMB_POSIX_ACL_HEADER_SIZE;
5392 if (total_data < size_needed) {
5393 status = NT_STATUS_INVALID_PARAMETER;
5398 * Ensure we always operate on a file descriptor, not just
5401 if (fsp == NULL || !fsp->fsp_flags.is_fsa) {
5402 uint32_t access_mask = SEC_STD_WRITE_OWNER|
5404 SEC_STD_READ_CONTROL|
5405 FILE_READ_ATTRIBUTES|
5406 FILE_WRITE_ATTRIBUTES;
5408 status = get_posix_fsp(conn,
5414 if (!NT_STATUS_IS_OK(status)) {
5420 /* Here we know fsp != NULL */
5421 SMB_ASSERT(fsp != NULL);
5423 status = refuse_symlink_fsp(fsp);
5424 if (!NT_STATUS_IS_OK(status)) {
5428 /* If we have a default acl, this *must* be a directory. */
5429 if (valid_def_acls && !fsp->fsp_flags.is_directory) {
5430 DBG_INFO("Can't set default acls on "
5431 "non-directory %s\n",
5433 return NT_STATUS_INVALID_HANDLE;
5436 DBG_DEBUG("file %s num_file_acls = %"PRIu16", "
5437 "num_def_acls = %"PRIu16"\n",
5442 /* Move pdata to the start of the file ACL entries. */
5443 pdata += SMB_POSIX_ACL_HEADER_SIZE;
5445 if (valid_file_acls) {
5446 status = set_unix_posix_acl(conn,
5450 if (!NT_STATUS_IS_OK(status)) {
5455 /* Move pdata to the start of the default ACL entries. */
5456 pdata += (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE);
5458 if (valid_def_acls) {
5459 status = set_unix_posix_default_acl(conn,
5463 if (!NT_STATUS_IS_OK(status)) {
5468 status = NT_STATUS_OK;
5473 (void)close_file_free(req, &fsp, NORMAL_CLOSE);
5479 /****************************************************************************
5480 Deal with SMB_SET_FILE_BASIC_INFO.
5481 ****************************************************************************/
5483 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
5487 struct smb_filename *smb_fname)
5489 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
5490 struct smb_file_time ft;
5491 uint32_t dosmode = 0;
5492 NTSTATUS status = NT_STATUS_OK;
5494 init_smb_file_time(&ft);
5496 if (total_data < 36) {
5497 return NT_STATUS_INVALID_PARAMETER;
5501 return NT_STATUS_INVALID_HANDLE;
5504 status = check_access_fsp(fsp, FILE_WRITE_ATTRIBUTES);
5505 if (!NT_STATUS_IS_OK(status)) {
5509 /* Set the attributes */
5510 dosmode = IVAL(pdata,32);
5511 status = smb_set_file_dosmode(conn, fsp, dosmode);
5512 if (!NT_STATUS_IS_OK(status)) {
5517 ft.create_time = pull_long_date_full_timespec(pdata);
5520 ft.atime = pull_long_date_full_timespec(pdata+8);
5523 ft.mtime = pull_long_date_full_timespec(pdata+16);
5526 ft.ctime = pull_long_date_full_timespec(pdata+24);
5528 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
5529 smb_fname_str_dbg(smb_fname)));
5531 status = smb_set_file_time(conn, fsp, smb_fname, &ft, true);
5532 if (!NT_STATUS_IS_OK(status)) {
5536 if (fsp->fsp_flags.modified) {
5537 trigger_write_time_update_immediate(fsp);
5539 return NT_STATUS_OK;
5542 /****************************************************************************
5543 Deal with SMB_INFO_STANDARD.
5544 ****************************************************************************/
5546 static NTSTATUS smb_set_info_standard(connection_struct *conn,
5550 struct smb_filename *smb_fname)
5553 struct smb_file_time ft;
5555 init_smb_file_time(&ft);
5557 if (total_data < 12) {
5558 return NT_STATUS_INVALID_PARAMETER;
5562 return NT_STATUS_INVALID_HANDLE;
5566 ft.create_time = time_t_to_full_timespec(srv_make_unix_date2(pdata));
5568 ft.atime = time_t_to_full_timespec(srv_make_unix_date2(pdata+4));
5570 ft.mtime = time_t_to_full_timespec(srv_make_unix_date2(pdata+8));
5572 DEBUG(10,("smb_set_info_standard: file %s\n",
5573 smb_fname_str_dbg(smb_fname)));
5575 status = check_access_fsp(fsp, FILE_WRITE_ATTRIBUTES);
5576 if (!NT_STATUS_IS_OK(status)) {
5580 status = smb_set_file_time(conn, fsp, smb_fname, &ft, true);
5581 if (!NT_STATUS_IS_OK(status)) {
5585 if (fsp->fsp_flags.modified) {
5586 trigger_write_time_update_immediate(fsp);
5588 return NT_STATUS_OK;
5591 /****************************************************************************
5592 Deal with SMB_SET_FILE_ALLOCATION_INFO.
5593 ****************************************************************************/
5595 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
5596 struct smb_request *req,
5600 struct smb_filename *smb_fname)
5602 uint64_t allocation_size = 0;
5603 NTSTATUS status = NT_STATUS_OK;
5604 files_struct *new_fsp = NULL;
5606 if (!VALID_STAT(smb_fname->st)) {
5607 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5610 if (total_data < 8) {
5611 return NT_STATUS_INVALID_PARAMETER;
5614 allocation_size = (uint64_t)IVAL(pdata,0);
5615 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
5616 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
5617 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
5618 (double)allocation_size));
5620 if (allocation_size) {
5621 allocation_size = smb_roundup(conn, allocation_size);
5624 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
5625 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
5626 (double)allocation_size));
5629 !fsp->fsp_flags.is_pathref &&
5630 fsp_get_io_fd(fsp) != -1)
5632 /* Open file handle. */
5633 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
5634 return NT_STATUS_ACCESS_DENIED;
5637 /* Only change if needed. */
5638 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
5639 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
5640 return map_nt_error_from_unix(errno);
5643 /* But always update the time. */
5645 * This is equivalent to a write. Ensure it's seen immediately
5646 * if there are no pending writes.
5648 trigger_write_time_update_immediate(fsp);
5649 return NT_STATUS_OK;
5652 /* Pathname or stat or directory file. */
5653 status = SMB_VFS_CREATE_FILE(
5657 smb_fname, /* fname */
5658 FILE_WRITE_DATA, /* access_mask */
5659 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5661 FILE_OPEN, /* create_disposition*/
5662 0, /* create_options */
5663 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5664 0, /* oplock_request */
5666 0, /* allocation_size */
5667 0, /* private_flags */
5670 &new_fsp, /* result */
5672 NULL, NULL); /* create context */
5674 if (!NT_STATUS_IS_OK(status)) {
5675 /* NB. We check for open_was_deferred in the caller. */
5679 /* Only change if needed. */
5680 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
5681 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
5682 status = map_nt_error_from_unix(errno);
5683 close_file_free(req, &new_fsp, NORMAL_CLOSE);
5688 /* Changing the allocation size should set the last mod time. */
5690 * This is equivalent to a write. Ensure it's seen immediately
5691 * if there are no pending writes.
5693 trigger_write_time_update_immediate(new_fsp);
5694 close_file_free(req, &new_fsp, NORMAL_CLOSE);
5695 return NT_STATUS_OK;
5698 /****************************************************************************
5699 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
5700 ****************************************************************************/
5702 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
5703 struct smb_request *req,
5707 struct smb_filename *smb_fname,
5708 bool fail_after_createfile)
5712 if (total_data < 8) {
5713 return NT_STATUS_INVALID_PARAMETER;
5716 size = IVAL(pdata,0);
5717 size |= (((off_t)IVAL(pdata,4)) << 32);
5718 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
5719 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
5722 return smb_set_file_size(conn, req,
5727 fail_after_createfile);
5730 /****************************************************************************
5731 Allow a UNIX info mknod.
5732 ****************************************************************************/
5734 static NTSTATUS smb_unix_mknod(connection_struct *conn,
5737 const struct smb_filename *smb_fname)
5739 uint32_t file_type = IVAL(pdata,56);
5740 #if defined(HAVE_MAKEDEV)
5741 uint32_t dev_major = IVAL(pdata,60);
5742 uint32_t dev_minor = IVAL(pdata,68);
5744 SMB_DEV_T dev = (SMB_DEV_T)0;
5745 uint32_t raw_unixmode = IVAL(pdata,84);
5749 struct smb_filename *parent_fname = NULL;
5750 struct smb_filename *base_name = NULL;
5752 if (total_data < 100) {
5753 return NT_STATUS_INVALID_PARAMETER;
5756 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
5757 PERM_NEW_FILE, &unixmode);
5758 if (!NT_STATUS_IS_OK(status)) {
5762 #if defined(HAVE_MAKEDEV)
5763 dev = makedev(dev_major, dev_minor);
5766 switch (file_type) {
5767 /* We can't create other objects here. */
5768 case UNIX_TYPE_FILE:
5770 case UNIX_TYPE_SYMLINK:
5771 return NT_STATUS_ACCESS_DENIED;
5772 #if defined(S_IFIFO)
5773 case UNIX_TYPE_FIFO:
5774 unixmode |= S_IFIFO;
5777 #if defined(S_IFSOCK)
5778 case UNIX_TYPE_SOCKET:
5779 unixmode |= S_IFSOCK;
5782 #if defined(S_IFCHR)
5783 case UNIX_TYPE_CHARDEV:
5784 /* This is only allowed for root. */
5785 if (get_current_uid(conn) != sec_initial_uid()) {
5786 return NT_STATUS_ACCESS_DENIED;
5788 unixmode |= S_IFCHR;
5791 #if defined(S_IFBLK)
5792 case UNIX_TYPE_BLKDEV:
5793 if (get_current_uid(conn) != sec_initial_uid()) {
5794 return NT_STATUS_ACCESS_DENIED;
5796 unixmode |= S_IFBLK;
5800 return NT_STATUS_INVALID_PARAMETER;
5803 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
5804 "%.0f mode 0%o for file %s\n", (double)dev,
5805 (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
5807 status = parent_pathref(talloc_tos(),
5812 if (!NT_STATUS_IS_OK(status)) {
5816 /* Ok - do the mknod. */
5817 ret = SMB_VFS_MKNODAT(conn,
5824 TALLOC_FREE(parent_fname);
5825 return map_nt_error_from_unix(errno);
5828 /* If any of the other "set" calls fail we
5829 * don't want to end up with a half-constructed mknod.
5832 if (lp_inherit_permissions(SNUM(conn))) {
5833 inherit_access_posix_acl(conn,
5838 TALLOC_FREE(parent_fname);
5840 return NT_STATUS_OK;
5843 /****************************************************************************
5844 Deal with SMB_SET_FILE_UNIX_BASIC.
5845 ****************************************************************************/
5847 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
5848 struct smb_request *req,
5852 struct smb_filename *smb_fname)
5854 struct smb_file_time ft;
5855 uint32_t raw_unixmode;
5858 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
5859 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
5860 NTSTATUS status = NT_STATUS_OK;
5861 enum perm_type ptype;
5862 files_struct *all_fsps = NULL;
5863 bool modify_mtime = true;
5865 SMB_STRUCT_STAT sbuf;
5867 init_smb_file_time(&ft);
5869 if (total_data < 100) {
5870 return NT_STATUS_INVALID_PARAMETER;
5873 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
5874 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
5875 size=IVAL(pdata,0); /* first 8 Bytes are size */
5876 size |= (((off_t)IVAL(pdata,4)) << 32);
5879 ft.atime = pull_long_date_full_timespec(pdata+24); /* access_time */
5880 ft.mtime = pull_long_date_full_timespec(pdata+32); /* modification_time */
5881 set_owner = (uid_t)IVAL(pdata,40);
5882 set_grp = (gid_t)IVAL(pdata,48);
5883 raw_unixmode = IVAL(pdata,84);
5885 if (VALID_STAT(smb_fname->st)) {
5886 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
5887 ptype = PERM_EXISTING_DIR;
5889 ptype = PERM_EXISTING_FILE;
5892 ptype = PERM_NEW_FILE;
5895 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
5897 if (!NT_STATUS_IS_OK(status)) {
5901 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
5902 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
5903 smb_fname_str_dbg(smb_fname), (double)size,
5904 (unsigned int)set_owner, (unsigned int)set_grp,
5905 (int)raw_unixmode));
5907 sbuf = smb_fname->st;
5909 if (!VALID_STAT(sbuf)) {
5911 * The only valid use of this is to create character and block
5912 * devices, and named pipes. This is deprecated (IMHO) and
5913 * a new info level should be used for mknod. JRA.
5916 return smb_unix_mknod(conn,
5923 /* Horrible backwards compatibility hack as an old server bug
5924 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
5928 size = get_file_size_stat(&sbuf);
5933 * Deal with the UNIX specific mode set.
5936 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
5939 if (fsp == NULL || S_ISLNK(smb_fname->st.st_ex_mode)) {
5940 DBG_WARNING("Can't set mode on symlink %s\n",
5941 smb_fname_str_dbg(smb_fname));
5942 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5945 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
5946 "setting mode 0%o for file %s\n",
5947 (unsigned int)unixmode,
5948 smb_fname_str_dbg(smb_fname)));
5949 ret = SMB_VFS_FCHMOD(fsp, unixmode);
5951 return map_nt_error_from_unix(errno);
5956 * Deal with the UNIX specific uid set.
5959 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
5960 (sbuf.st_ex_uid != set_owner)) {
5963 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
5964 "changing owner %u for path %s\n",
5965 (unsigned int)set_owner,
5966 smb_fname_str_dbg(smb_fname)));
5969 !fsp->fsp_flags.is_pathref &&
5970 fsp_get_io_fd(fsp) != -1)
5972 ret = SMB_VFS_FCHOWN(fsp, set_owner, (gid_t)-1);
5975 * UNIX extensions calls must always operate
5978 ret = SMB_VFS_LCHOWN(conn, smb_fname,
5979 set_owner, (gid_t)-1);
5983 status = map_nt_error_from_unix(errno);
5989 * Deal with the UNIX specific gid set.
5992 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
5993 (sbuf.st_ex_gid != set_grp)) {
5996 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
5997 "changing group %u for file %s\n",
5998 (unsigned int)set_grp,
5999 smb_fname_str_dbg(smb_fname)));
6001 !fsp->fsp_flags.is_pathref &&
6002 fsp_get_io_fd(fsp) != -1)
6004 ret = SMB_VFS_FCHOWN(fsp, (uid_t)-1, set_grp);
6007 * UNIX extensions calls must always operate
6010 ret = SMB_VFS_LCHOWN(conn, smb_fname, (uid_t)-1,
6014 status = map_nt_error_from_unix(errno);
6019 /* Deal with any size changes. */
6021 if (S_ISREG(sbuf.st_ex_mode)) {
6022 status = smb_set_file_size(conn, req,
6028 if (!NT_STATUS_IS_OK(status)) {
6033 /* Deal with any time changes. */
6034 if (is_omit_timespec(&ft.mtime) && is_omit_timespec(&ft.atime)) {
6035 /* No change, don't cancel anything. */
6039 id = vfs_file_id_from_sbuf(conn, &sbuf);
6040 for(all_fsps = file_find_di_first(conn->sconn, id, true); all_fsps;
6041 all_fsps = file_find_di_next(all_fsps, true)) {
6043 * We're setting the time explicitly for UNIX.
6044 * Cancel any pending changes over all handles.
6046 all_fsps->fsp_flags.update_write_time_on_close = false;
6047 TALLOC_FREE(all_fsps->update_write_time_event);
6051 * Override the "setting_write_time"
6052 * parameter here as it almost does what
6053 * we need. Just remember if we modified
6054 * mtime and send the notify ourselves.
6056 if (is_omit_timespec(&ft.mtime)) {
6057 modify_mtime = false;
6060 status = smb_set_file_time(conn,
6066 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
6067 FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
6072 /****************************************************************************
6073 Deal with SMB_SET_FILE_UNIX_INFO2.
6074 ****************************************************************************/
6076 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
6077 struct smb_request *req,
6081 struct smb_filename *smb_fname)
6084 uint32_t smb_fflags;
6087 if (total_data < 116) {
6088 return NT_STATUS_INVALID_PARAMETER;
6091 /* Start by setting all the fields that are common between UNIX_BASIC
6094 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
6096 if (!NT_STATUS_IS_OK(status)) {
6100 smb_fflags = IVAL(pdata, 108);
6101 smb_fmask = IVAL(pdata, 112);
6103 /* NB: We should only attempt to alter the file flags if the client
6104 * sends a non-zero mask.
6106 if (smb_fmask != 0) {
6107 int stat_fflags = 0;
6109 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
6110 smb_fmask, &stat_fflags)) {
6111 /* Client asked to alter a flag we don't understand. */
6112 return NT_STATUS_INVALID_PARAMETER;
6115 if (fsp == NULL || S_ISLNK(smb_fname->st.st_ex_mode)) {
6116 DBG_WARNING("Can't change flags on symlink %s\n",
6117 smb_fname_str_dbg(smb_fname));
6118 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6120 if (SMB_VFS_FCHFLAGS(fsp, stat_fflags) != 0) {
6121 return map_nt_error_from_unix(errno);
6125 /* XXX: need to add support for changing the create_time here. You
6126 * can do this for paths on Darwin with setattrlist(2). The right way
6127 * to hook this up is probably by extending the VFS utimes interface.
6130 return NT_STATUS_OK;
6133 /****************************************************************************
6134 Create a directory with POSIX semantics.
6135 ****************************************************************************/
6137 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
6138 struct smb_request *req,
6141 struct smb_filename *smb_fname,
6142 int *pdata_return_size)
6144 NTSTATUS status = NT_STATUS_OK;
6145 uint32_t raw_unixmode = 0;
6146 mode_t unixmode = (mode_t)0;
6147 files_struct *fsp = NULL;
6148 uint16_t info_level_return = 0;
6150 char *pdata = *ppdata;
6151 struct smb2_create_blobs *posx = NULL;
6153 if (total_data < 18) {
6154 return NT_STATUS_INVALID_PARAMETER;
6157 raw_unixmode = IVAL(pdata,8);
6158 /* Next 4 bytes are not yet defined. */
6160 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6161 PERM_NEW_DIR, &unixmode);
6162 if (!NT_STATUS_IS_OK(status)) {
6166 status = make_smb2_posix_create_ctx(talloc_tos(), &posx, unixmode);
6167 if (!NT_STATUS_IS_OK(status)) {
6168 DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
6173 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
6174 smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
6176 status = SMB_VFS_CREATE_FILE(
6180 smb_fname, /* fname */
6181 FILE_READ_ATTRIBUTES, /* access_mask */
6182 FILE_SHARE_NONE, /* share_access */
6183 FILE_CREATE, /* create_disposition*/
6184 FILE_DIRECTORY_FILE, /* create_options */
6185 0, /* file_attributes */
6186 0, /* oplock_request */
6188 0, /* allocation_size */
6189 0, /* private_flags */
6194 posx, /* in_context_blobs */
6195 NULL); /* out_context_blobs */
6199 if (NT_STATUS_IS_OK(status)) {
6200 close_file_free(req, &fsp, NORMAL_CLOSE);
6203 info_level_return = SVAL(pdata,16);
6205 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6206 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6207 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6208 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6210 *pdata_return_size = 12;
6213 /* Realloc the data size */
6214 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6215 if (*ppdata == NULL) {
6216 *pdata_return_size = 0;
6217 return NT_STATUS_NO_MEMORY;
6221 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6222 SSVAL(pdata,2,0); /* No fnum. */
6223 SIVAL(pdata,4,info); /* Was directory created. */
6225 switch (info_level_return) {
6226 case SMB_QUERY_FILE_UNIX_BASIC:
6227 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6228 SSVAL(pdata,10,0); /* Padding. */
6229 store_file_unix_basic(conn, pdata + 12, fsp,
6232 case SMB_QUERY_FILE_UNIX_INFO2:
6233 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6234 SSVAL(pdata,10,0); /* Padding. */
6235 store_file_unix_basic_info2(conn, pdata + 12, fsp,
6239 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6240 SSVAL(pdata,10,0); /* Padding. */
6247 /****************************************************************************
6248 Open/Create a file with POSIX semantics.
6249 ****************************************************************************/
6251 #define SMB_O_RDONLY_MAPPING (FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA)
6252 #define SMB_O_WRONLY_MAPPING (FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA)
6254 static NTSTATUS smb_posix_open(connection_struct *conn,
6255 struct smb_request *req,
6258 struct smb_filename *smb_fname,
6259 int *pdata_return_size)
6261 bool extended_oplock_granted = False;
6262 char *pdata = *ppdata;
6264 uint32_t wire_open_mode = 0;
6265 uint32_t raw_unixmode = 0;
6266 uint32_t attributes = 0;
6267 uint32_t create_disp = 0;
6268 uint32_t access_mask = 0;
6269 uint32_t create_options = FILE_NON_DIRECTORY_FILE;
6270 NTSTATUS status = NT_STATUS_OK;
6271 mode_t unixmode = (mode_t)0;
6272 files_struct *fsp = NULL;
6273 int oplock_request = 0;
6275 uint16_t info_level_return = 0;
6276 struct smb2_create_blobs *posx = NULL;
6278 if (total_data < 18) {
6279 return NT_STATUS_INVALID_PARAMETER;
6282 flags = IVAL(pdata,0);
6283 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
6284 if (oplock_request) {
6285 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
6288 wire_open_mode = IVAL(pdata,4);
6290 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
6291 return smb_posix_mkdir(conn, req,
6298 switch (wire_open_mode & SMB_ACCMODE) {
6300 access_mask = SMB_O_RDONLY_MAPPING;
6303 access_mask = SMB_O_WRONLY_MAPPING;
6306 access_mask = (SMB_O_RDONLY_MAPPING|
6307 SMB_O_WRONLY_MAPPING);
6310 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
6311 (unsigned int)wire_open_mode ));
6312 return NT_STATUS_INVALID_PARAMETER;
6315 wire_open_mode &= ~SMB_ACCMODE;
6317 /* First take care of O_CREAT|O_EXCL interactions. */
6318 switch (wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) {
6319 case (SMB_O_CREAT | SMB_O_EXCL):
6320 /* File exists fail. File not exist create. */
6321 create_disp = FILE_CREATE;
6324 /* File exists open. File not exist create. */
6325 create_disp = FILE_OPEN_IF;
6328 /* O_EXCL on its own without O_CREAT is undefined.
6329 We deliberately ignore it as some versions of
6330 Linux CIFSFS can send a bare O_EXCL on the
6331 wire which other filesystems in the kernel
6332 ignore. See bug 9519 for details. */
6337 /* File exists open. File not exist fail. */
6338 create_disp = FILE_OPEN;
6341 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
6342 (unsigned int)wire_open_mode ));
6343 return NT_STATUS_INVALID_PARAMETER;
6346 /* Next factor in the effects of O_TRUNC. */
6347 wire_open_mode &= ~(SMB_O_CREAT | SMB_O_EXCL);
6349 if (wire_open_mode & SMB_O_TRUNC) {
6350 switch (create_disp) {
6352 /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
6353 /* Leave create_disp alone as
6354 (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
6356 /* File exists fail. File not exist create. */
6359 /* SMB_O_CREAT | SMB_O_TRUNC */
6360 /* File exists overwrite. File not exist create. */
6361 create_disp = FILE_OVERWRITE_IF;
6365 /* File exists overwrite. File not exist fail. */
6366 create_disp = FILE_OVERWRITE;
6369 /* Cannot get here. */
6370 smb_panic("smb_posix_open: logic error");
6371 return NT_STATUS_INVALID_PARAMETER;
6375 raw_unixmode = IVAL(pdata,8);
6376 /* Next 4 bytes are not yet defined. */
6378 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6379 (VALID_STAT(smb_fname->st) ?
6380 PERM_EXISTING_FILE : PERM_NEW_FILE),
6383 if (!NT_STATUS_IS_OK(status)) {
6387 status = make_smb2_posix_create_ctx(talloc_tos(), &posx, unixmode);
6388 if (!NT_STATUS_IS_OK(status)) {
6389 DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
6394 if (wire_open_mode & SMB_O_SYNC) {
6395 create_options |= FILE_WRITE_THROUGH;
6397 if (wire_open_mode & SMB_O_APPEND) {
6398 access_mask |= FILE_APPEND_DATA;
6400 if (wire_open_mode & SMB_O_DIRECT) {
6401 attributes |= FILE_FLAG_NO_BUFFERING;
6404 if ((wire_open_mode & SMB_O_DIRECTORY) ||
6405 VALID_STAT_OF_DIR(smb_fname->st)) {
6406 if (access_mask != SMB_O_RDONLY_MAPPING) {
6407 return NT_STATUS_FILE_IS_A_DIRECTORY;
6409 create_options &= ~FILE_NON_DIRECTORY_FILE;
6410 create_options |= FILE_DIRECTORY_FILE;
6413 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
6414 smb_fname_str_dbg(smb_fname),
6415 (unsigned int)wire_open_mode,
6416 (unsigned int)unixmode ));
6418 status = SMB_VFS_CREATE_FILE(
6422 smb_fname, /* fname */
6423 access_mask, /* access_mask */
6424 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6426 create_disp, /* create_disposition*/
6427 create_options, /* create_options */
6428 attributes, /* file_attributes */
6429 oplock_request, /* oplock_request */
6431 0, /* allocation_size */
6432 0, /* private_flags */
6437 posx, /* in_context_blobs */
6438 NULL); /* out_context_blobs */
6442 if (!NT_STATUS_IS_OK(status)) {
6446 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
6447 extended_oplock_granted = True;
6450 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
6451 extended_oplock_granted = True;
6454 info_level_return = SVAL(pdata,16);
6456 /* Allocate the correct return size. */
6458 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6459 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6460 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6461 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6463 *pdata_return_size = 12;
6466 /* Realloc the data size */
6467 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6468 if (*ppdata == NULL) {
6469 close_file_free(req, &fsp, ERROR_CLOSE);
6470 *pdata_return_size = 0;
6471 return NT_STATUS_NO_MEMORY;
6475 if (extended_oplock_granted) {
6476 if (flags & REQUEST_BATCH_OPLOCK) {
6477 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
6479 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
6481 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
6482 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
6484 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6487 SSVAL(pdata,2,fsp->fnum);
6488 SIVAL(pdata,4,info); /* Was file created etc. */
6490 switch (info_level_return) {
6491 case SMB_QUERY_FILE_UNIX_BASIC:
6492 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6493 SSVAL(pdata,10,0); /* padding. */
6494 store_file_unix_basic(conn, pdata + 12, fsp,
6497 case SMB_QUERY_FILE_UNIX_INFO2:
6498 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6499 SSVAL(pdata,10,0); /* padding. */
6500 store_file_unix_basic_info2(conn, pdata + 12, fsp,
6504 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6505 SSVAL(pdata,10,0); /* padding. */
6508 return NT_STATUS_OK;
6511 /****************************************************************************
6512 Delete a file with POSIX semantics.
6513 ****************************************************************************/
6515 static NTSTATUS smb_posix_unlink(connection_struct *conn,
6516 struct smb_request *req,
6519 struct smb_filename *smb_fname)
6521 NTSTATUS status = NT_STATUS_OK;
6522 files_struct *fsp = NULL;
6526 int create_options = 0;
6527 struct share_mode_lock *lck = NULL;
6528 bool other_nonposix_opens;
6529 struct smb2_create_blobs *posx = NULL;
6531 if (total_data < 2) {
6532 return NT_STATUS_INVALID_PARAMETER;
6535 flags = SVAL(pdata,0);
6537 if (!VALID_STAT(smb_fname->st)) {
6538 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6541 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
6542 !VALID_STAT_OF_DIR(smb_fname->st)) {
6543 return NT_STATUS_NOT_A_DIRECTORY;
6546 DEBUG(10,("smb_posix_unlink: %s %s\n",
6547 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
6548 smb_fname_str_dbg(smb_fname)));
6550 if (VALID_STAT_OF_DIR(smb_fname->st)) {
6551 create_options |= FILE_DIRECTORY_FILE;
6554 status = make_smb2_posix_create_ctx(talloc_tos(), &posx, 0777);
6555 if (!NT_STATUS_IS_OK(status)) {
6556 DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
6561 status = SMB_VFS_CREATE_FILE(
6565 smb_fname, /* fname */
6566 DELETE_ACCESS, /* access_mask */
6567 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6569 FILE_OPEN, /* create_disposition*/
6570 create_options, /* create_options */
6571 0, /* file_attributes */
6572 0, /* oplock_request */
6574 0, /* allocation_size */
6575 0, /* private_flags */
6580 posx, /* in_context_blobs */
6581 NULL); /* out_context_blobs */
6585 if (!NT_STATUS_IS_OK(status)) {
6590 * Don't lie to client. If we can't really delete due to
6591 * non-POSIX opens return SHARING_VIOLATION.
6594 lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
6596 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
6597 "lock for file %s\n", fsp_str_dbg(fsp)));
6598 close_file_free(req, &fsp, NORMAL_CLOSE);
6599 return NT_STATUS_INVALID_PARAMETER;
6602 other_nonposix_opens = has_other_nonposix_opens(lck, fsp);
6603 if (other_nonposix_opens) {
6604 /* Fail with sharing violation. */
6606 close_file_free(req, &fsp, NORMAL_CLOSE);
6607 return NT_STATUS_SHARING_VIOLATION;
6611 * Set the delete on close.
6613 status = smb_set_file_disposition_info(conn,
6621 if (!NT_STATUS_IS_OK(status)) {
6622 close_file_free(req, &fsp, NORMAL_CLOSE);
6625 return close_file_free(req, &fsp, NORMAL_CLOSE);
6628 static NTSTATUS smbd_do_posix_setfilepathinfo(struct connection_struct *conn,
6629 struct smb_request *req,
6630 TALLOC_CTX *mem_ctx,
6631 uint16_t info_level,
6632 struct smb_filename *smb_fname,
6638 char *pdata = *ppdata;
6639 NTSTATUS status = NT_STATUS_OK;
6640 int data_return_size = 0;
6644 if (!CAN_WRITE(conn)) {
6645 /* Allow POSIX opens. The open path will deny
6646 * any non-readonly opens. */
6647 if (info_level != SMB_POSIX_PATH_OPEN) {
6648 return NT_STATUS_DOS(ERRSRV, ERRaccess);
6652 DBG_DEBUG("file=%s (%s) info_level=%d totdata=%d\n",
6653 smb_fname_str_dbg(smb_fname),
6658 switch (info_level) {
6659 case SMB_SET_FILE_UNIX_BASIC:
6661 status = smb_set_file_unix_basic(conn, req,
6669 case SMB_SET_FILE_UNIX_INFO2:
6671 status = smb_set_file_unix_info2(conn, req,
6679 case SMB_SET_FILE_UNIX_LINK:
6681 if (smb_fname == NULL) {
6682 /* We must have a pathname for this. */
6683 return NT_STATUS_INVALID_LEVEL;
6685 status = smb_set_file_unix_link(conn, req, pdata,
6686 total_data, smb_fname);
6690 case SMB_SET_FILE_UNIX_HLINK:
6692 if (smb_fname == NULL) {
6693 /* We must have a pathname for this. */
6694 return NT_STATUS_INVALID_LEVEL;
6696 status = smb_set_file_unix_hlink(conn, req,
6702 #if defined(HAVE_POSIX_ACLS)
6703 case SMB_SET_POSIX_ACL:
6705 status = smb_set_posix_acl(conn,
6715 #if defined(WITH_SMB1SERVER)
6716 case SMB_SET_POSIX_LOCK:
6719 return NT_STATUS_INVALID_LEVEL;
6721 status = smb_set_posix_lock(conn, req,
6722 pdata, total_data, fsp);
6727 case SMB_POSIX_PATH_OPEN:
6729 if (smb_fname == NULL) {
6730 /* We must have a pathname for this. */
6731 return NT_STATUS_INVALID_LEVEL;
6734 status = smb_posix_open(conn, req,
6742 case SMB_POSIX_PATH_UNLINK:
6744 if (smb_fname == NULL) {
6745 /* We must have a pathname for this. */
6746 return NT_STATUS_INVALID_LEVEL;
6749 status = smb_posix_unlink(conn, req,
6757 return NT_STATUS_INVALID_LEVEL;
6760 if (!NT_STATUS_IS_OK(status)) {
6764 *ret_data_size = data_return_size;
6765 return NT_STATUS_OK;
6768 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
6769 struct smb_request *req,
6770 TALLOC_CTX *mem_ctx,
6771 uint16_t info_level,
6773 struct smb_filename *smb_fname,
6774 char **ppdata, int total_data,
6777 char *pdata = *ppdata;
6778 NTSTATUS status = NT_STATUS_OK;
6779 int data_return_size = 0;
6781 if (INFO_LEVEL_IS_UNIX(info_level)) {
6782 if (!lp_smb1_unix_extensions()) {
6783 return NT_STATUS_INVALID_LEVEL;
6785 if (!req->posix_pathnames) {
6786 return NT_STATUS_INVALID_LEVEL;
6788 status = smbd_do_posix_setfilepathinfo(conn,
6797 if (!NT_STATUS_IS_OK(status)) {
6800 *ret_data_size = data_return_size;
6801 return NT_STATUS_OK;
6806 DEBUG(3,("smbd_do_setfilepathinfo: %s (%s) info_level=%d "
6807 "totdata=%d\n", smb_fname_str_dbg(smb_fname),
6809 info_level, total_data));
6811 switch (info_level) {
6813 case SMB_INFO_STANDARD:
6815 status = smb_set_info_standard(conn,
6823 case SMB_INFO_SET_EA:
6825 status = smb_info_set_ea(conn,
6833 case SMB_SET_FILE_BASIC_INFO:
6834 case SMB_FILE_BASIC_INFORMATION:
6836 status = smb_set_file_basic_info(conn,
6844 case SMB_FILE_ALLOCATION_INFORMATION:
6845 case SMB_SET_FILE_ALLOCATION_INFO:
6847 status = smb_set_file_allocation_info(conn, req,
6855 case SMB_FILE_END_OF_FILE_INFORMATION:
6856 case SMB_SET_FILE_END_OF_FILE_INFO:
6859 * XP/Win7 both fail after the createfile with
6860 * SMB_SET_FILE_END_OF_FILE_INFO but not
6861 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
6862 * The level is known here, so pass it down
6866 (info_level == SMB_SET_FILE_END_OF_FILE_INFO);
6868 status = smb_set_file_end_of_file_info(conn, req,
6877 case SMB_FILE_DISPOSITION_INFORMATION:
6878 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
6881 /* JRA - We used to just ignore this on a path ?
6882 * Shouldn't this be invalid level on a pathname
6885 if (tran_call != TRANSACT2_SETFILEINFO) {
6886 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6889 status = smb_set_file_disposition_info(conn,
6897 case SMB_FILE_POSITION_INFORMATION:
6899 status = smb_file_position_information(conn,
6906 case SMB_FILE_FULL_EA_INFORMATION:
6908 status = smb_set_file_full_ea_info(conn,
6915 /* From tridge Samba4 :
6916 * MODE_INFORMATION in setfileinfo (I have no
6917 * idea what "mode information" on a file is - it takes a value of 0,
6918 * 2, 4 or 6. What could it be?).
6921 case SMB_FILE_MODE_INFORMATION:
6923 status = smb_file_mode_information(conn,
6929 /* [MS-SMB2] 3.3.5.21.1 states we MUST fail with STATUS_NOT_SUPPORTED. */
6930 case SMB_FILE_VALID_DATA_LENGTH_INFORMATION:
6931 case SMB_FILE_SHORT_NAME_INFORMATION:
6932 return NT_STATUS_NOT_SUPPORTED;
6934 case SMB_FILE_RENAME_INFORMATION:
6936 status = smb_file_rename_information(conn, req,
6942 case SMB2_FILE_RENAME_INFORMATION_INTERNAL:
6944 /* SMB2 rename information. */
6945 status = smb2_file_rename_information(conn, req,
6951 case SMB_FILE_LINK_INFORMATION:
6953 status = smb_file_link_information(conn, req,
6960 return NT_STATUS_INVALID_LEVEL;
6963 if (!NT_STATUS_IS_OK(status)) {
6967 *ret_data_size = data_return_size;
6968 return NT_STATUS_OK;
6971 static uint32_t generate_volume_serial_number(
6972 const struct loadparm_substitution *lp_sub,
6975 int serial = lp_volume_serial_number(snum);
6976 return serial != -1 ? serial:
6977 str_checksum(lp_servicename(talloc_tos(), lp_sub, snum)) ^
6978 (str_checksum(get_local_machine_name())<<16);