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 "../librpc/gen_ndr/ndr_smb3posix.h"
37 #include "libcli/security/security.h"
40 #include "smbprofile.h"
41 #include "rpc_server/srv_pipe_hnd.h"
43 #include "lib/util_ea.h"
44 #include "lib/readdir_attr.h"
46 #include "libcli/smb/smb2_posix.h"
47 #include "lib/util/string_wrappers.h"
48 #include "source3/lib/substitute.h"
49 #include "source3/lib/adouble.h"
50 #include "source3/smbd/dir.h"
51 #include "source3/modules/util_reparse.h"
53 #define DIR_ENTRY_SAFETY_MARGIN 4096
55 static uint32_t generate_volume_serial_number(
56 const struct loadparm_substitution
*lp_sub
,
59 /****************************************************************************
60 Check if an open file handle is a symlink.
61 ****************************************************************************/
63 NTSTATUS
refuse_symlink_fsp(const files_struct
*fsp
)
66 if (!VALID_STAT(fsp
->fsp_name
->st
)) {
67 return NT_STATUS_ACCESS_DENIED
;
69 if (S_ISLNK(fsp
->fsp_name
->st
.st_ex_mode
)) {
70 return NT_STATUS_ACCESS_DENIED
;
72 if (fsp_get_pathref_fd(fsp
) == -1) {
73 return NT_STATUS_ACCESS_DENIED
;
79 * Check that one or more of the rights in access mask are
80 * allowed. Iow, access_requested can contain more then one right and
81 * it is sufficient having only one of those granted to pass.
83 NTSTATUS
check_any_access_fsp(struct files_struct
*fsp
,
84 uint32_t access_requested
)
86 const uint32_t ro_access
= SEC_RIGHTS_FILE_READ
| SEC_FILE_EXECUTE
;
87 uint32_t ro_access_granted
= 0;
88 uint32_t access_granted
= 0;
91 if (fsp
->fsp_flags
.is_fsa
) {
92 access_granted
= fsp
->access_mask
;
97 if (!(mask
& access_requested
)) {
102 status
= smbd_check_access_rights_fsp(
107 if (NT_STATUS_IS_OK(status
)) {
108 access_granted
|= mask
;
109 if (fsp
->fsp_name
->twrp
== 0) {
111 * We can only optimize
112 * the non-snapshot case
120 if ((access_granted
& access_requested
) == 0) {
121 return NT_STATUS_ACCESS_DENIED
;
124 if (fsp
->fsp_name
->twrp
== 0) {
128 ro_access_granted
= access_granted
& ro_access
;
129 if ((ro_access_granted
& access_requested
) == 0) {
130 return NT_STATUS_MEDIA_WRITE_PROTECTED
;
136 /********************************************************************
137 Roundup a value to the nearest allocation roundup size boundary.
138 Only do this for Windows clients.
139 ********************************************************************/
141 uint64_t smb_roundup(connection_struct
*conn
, uint64_t val
)
143 uint64_t rval
= lp_allocation_roundup_size(SNUM(conn
));
145 /* Only roundup for Windows clients. */
146 enum remote_arch_types ra_type
= get_remote_arch();
147 if (rval
&& (ra_type
!= RA_SAMBA
) && (ra_type
!= RA_CIFSFS
)) {
148 val
= SMB_ROUNDUP(val
,rval
);
153 /****************************************************************************
154 Utility functions for dealing with extended attributes.
155 ****************************************************************************/
157 /****************************************************************************
158 Refuse to allow clients to overwrite our private xattrs.
159 ****************************************************************************/
161 bool samba_private_attr_name(const char *unix_ea_name
)
163 bool prohibited
= false;
165 prohibited
|= strequal(unix_ea_name
, SAMBA_POSIX_INHERITANCE_EA_NAME
);
166 prohibited
|= strequal(unix_ea_name
, SAMBA_XATTR_DOS_ATTRIB
);
167 prohibited
|= strequal(unix_ea_name
, SAMBA_XATTR_MARKER
);
168 prohibited
|= strequal(unix_ea_name
, SAMBA_XATTR_REPARSE_ATTRIB
);
169 prohibited
|= strequal(unix_ea_name
, XATTR_NTACL_NAME
);
170 prohibited
|= strequal(unix_ea_name
, AFPINFO_EA_NETATALK
);
176 if (strncasecmp_m(unix_ea_name
, SAMBA_XATTR_DOSSTREAM_PREFIX
,
177 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX
)) == 0) {
183 /****************************************************************************
184 Get one EA value. Fill in a struct ea_struct.
185 ****************************************************************************/
187 NTSTATUS
get_ea_value_fsp(TALLOC_CTX
*mem_ctx
,
190 struct ea_struct
*pea
)
192 /* Get the value of this xattr. Max size is 64k. */
193 size_t attr_size
= 256;
196 size_t max_xattr_size
= 0;
200 return NT_STATUS_INVALID_HANDLE
;
202 status
= refuse_symlink_fsp(fsp
);
203 if (!NT_STATUS_IS_OK(status
)) {
207 max_xattr_size
= lp_smbd_max_xattr_size(SNUM(fsp
->conn
));
211 val
= talloc_realloc(mem_ctx
, val
, char, attr_size
);
213 return NT_STATUS_NO_MEMORY
;
216 sizeret
= SMB_VFS_FGETXATTR(fsp
, ea_name
, val
, attr_size
);
217 if (sizeret
== -1 && errno
== ERANGE
&& attr_size
< max_xattr_size
) {
218 attr_size
= max_xattr_size
;
223 return map_nt_error_from_unix(errno
);
226 DBG_DEBUG("EA %s is of length %zd\n", ea_name
, sizeret
);
227 dump_data(10, (uint8_t *)val
, sizeret
);
230 if (strnequal(ea_name
, "user.", 5)) {
231 pea
->name
= talloc_strdup(mem_ctx
, &ea_name
[5]);
233 pea
->name
= talloc_strdup(mem_ctx
, ea_name
);
235 if (pea
->name
== NULL
) {
237 return NT_STATUS_NO_MEMORY
;
239 pea
->value
.data
= (unsigned char *)val
;
240 pea
->value
.length
= (size_t)sizeret
;
244 NTSTATUS
get_ea_names_from_fsp(TALLOC_CTX
*mem_ctx
,
250 /* Get a list of all xattrs. Max namesize is 64k. */
251 size_t ea_namelist_size
= 1024;
252 char *ea_namelist
= smallbuf
;
253 char *to_free
= NULL
;
258 ssize_t sizeret
= -1;
266 if ((fsp
== NULL
) || !NT_STATUS_IS_OK(refuse_symlink_fsp(fsp
))) {
268 * Callers may pass fsp == NULL when passing smb_fname->fsp of a
269 * symlink. This is ok, handle it here, by just return no EA's
275 sizeret
= SMB_VFS_FLISTXATTR(fsp
, ea_namelist
,
278 if ((sizeret
== -1) && (errno
== ERANGE
)) {
279 ea_namelist_size
= 65536;
280 ea_namelist
= talloc_array(mem_ctx
, char, ea_namelist_size
);
281 if (ea_namelist
== NULL
) {
282 return NT_STATUS_NO_MEMORY
;
284 to_free
= ea_namelist
;
286 sizeret
= SMB_VFS_FLISTXATTR(fsp
, ea_namelist
,
291 status
= map_nt_error_from_unix(errno
);
292 TALLOC_FREE(to_free
);
296 DBG_DEBUG("ea_namelist size = %zd\n", sizeret
);
299 TALLOC_FREE(to_free
);
304 * Ensure the result is 0-terminated
307 if (ea_namelist
[sizeret
-1] != '\0') {
308 TALLOC_FREE(to_free
);
309 return NT_STATUS_INTERNAL_ERROR
;
317 for (p
= ea_namelist
; p
- ea_namelist
< sizeret
; p
+= strlen(p
)+1) {
321 *pnum_names
= num_names
;
323 if (pnames
== NULL
) {
324 TALLOC_FREE(to_free
);
328 names
= talloc_array(mem_ctx
, char *, num_names
);
330 DEBUG(0, ("talloc failed\n"));
331 TALLOC_FREE(to_free
);
332 return NT_STATUS_NO_MEMORY
;
335 if (ea_namelist
== smallbuf
) {
336 ea_namelist
= talloc_memdup(names
, smallbuf
, sizeret
);
337 if (ea_namelist
== NULL
) {
339 return NT_STATUS_NO_MEMORY
;
342 talloc_steal(names
, ea_namelist
);
344 ea_namelist
= talloc_realloc(names
, ea_namelist
, char,
346 if (ea_namelist
== NULL
) {
348 return NT_STATUS_NO_MEMORY
;
354 for (p
= ea_namelist
; p
- ea_namelist
< sizeret
; p
+= strlen(p
)+1) {
355 names
[num_names
++] = p
;
363 /****************************************************************************
364 Return a linked list of the total EA's. Plus the total size
365 ****************************************************************************/
367 static NTSTATUS
get_ea_list_from_fsp(TALLOC_CTX
*mem_ctx
,
369 size_t *pea_total_len
,
370 struct ea_list
**ea_list
)
372 /* Get a list of all xattrs. Max namesize is 64k. */
375 struct ea_list
*ea_list_head
= NULL
;
376 bool posix_pathnames
= false;
387 if (!lp_ea_support(SNUM(fsp
->conn
))) {
391 if (fsp_is_alternate_stream(fsp
)) {
392 return NT_STATUS_INVALID_PARAMETER
;
395 posix_pathnames
= (fsp
->fsp_name
->flags
& SMB_FILENAME_POSIX_PATH
);
397 status
= get_ea_names_from_fsp(talloc_tos(),
402 if (!NT_STATUS_IS_OK(status
)) {
406 if (num_names
== 0) {
410 for (i
=0; i
<num_names
; i
++) {
411 struct ea_list
*listp
;
415 * POSIX EA names are divided into several namespaces by
416 * means of string prefixes. Usually, the system controls
417 * semantics for each namespace, but the 'user' namespace is
418 * available for arbitrary use, which comes closest to
419 * Windows EA semantics. Hence, we map POSIX EAs from the
420 * 'user' namespace to Windows EAs, and just ignore all the
421 * other namespaces. Also, a few specific names in the 'user'
422 * namespace are used by Samba internally. Filter them out as
423 * well, and only present the EAs that are available for
426 if (!strnequal(names
[i
], "user.", 5)
427 || samba_private_attr_name(names
[i
]))
431 * Filter out any underlying POSIX EA names
432 * that a Windows client can't handle.
434 if (!posix_pathnames
&&
435 is_invalid_windows_ea_name(names
[i
])) {
439 listp
= talloc(mem_ctx
, struct ea_list
);
441 return NT_STATUS_NO_MEMORY
;
444 status
= get_ea_value_fsp(listp
,
449 if (!NT_STATUS_IS_OK(status
)) {
454 if (listp
->ea
.value
.length
== 0) {
456 * We can never return a zero length EA.
457 * Windows reports the EA's as corrupted.
462 if (listp
->ea
.value
.length
> 65536) {
464 * SMB clients may report error with file
465 * if large EA is presented to them.
467 DBG_ERR("EA [%s] on file [%s] exceeds "
468 "maximum permitted EA size of 64KiB: %zu\n.",
469 listp
->ea
.name
, fsp_str_dbg(fsp
),
470 listp
->ea
.value
.length
);
475 push_ascii_fstring(dos_ea_name
, listp
->ea
.name
);
478 4 + strlen(dos_ea_name
) + 1 + listp
->ea
.value
.length
;
480 DBG_DEBUG("total_len = %zu, %s, val len = %zu\n",
483 listp
->ea
.value
.length
);
485 DLIST_ADD_END(ea_list_head
, listp
);
489 /* Add on 4 for total length. */
490 if (*pea_total_len
) {
494 DBG_DEBUG("total_len = %zu\n", *pea_total_len
);
496 *ea_list
= ea_list_head
;
500 /****************************************************************************
501 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
503 ****************************************************************************/
505 static unsigned int fill_ea_buffer(TALLOC_CTX
*mem_ctx
, char *pdata
, unsigned int total_data_size
,
506 connection_struct
*conn
, struct ea_list
*ea_list
)
508 unsigned int ret_data_size
= 4;
511 SMB_ASSERT(total_data_size
>= 4);
513 if (!lp_ea_support(SNUM(conn
))) {
518 for (p
= pdata
+ 4; ea_list
; ea_list
= ea_list
->next
) {
521 push_ascii_fstring(dos_ea_name
, ea_list
->ea
.name
);
522 dos_namelen
= strlen(dos_ea_name
);
523 if (dos_namelen
> 255 || dos_namelen
== 0) {
526 if (ea_list
->ea
.value
.length
> 65535) {
529 if (4 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
> total_data_size
) {
533 /* We know we have room. */
534 SCVAL(p
,0,ea_list
->ea
.flags
);
535 SCVAL(p
,1,dos_namelen
);
536 SSVAL(p
,2,ea_list
->ea
.value
.length
);
537 strlcpy(p
+4, dos_ea_name
, dos_namelen
+1);
538 if (ea_list
->ea
.value
.length
> 0) {
539 memcpy(p
+ 4 + dos_namelen
+ 1,
540 ea_list
->ea
.value
.data
,
541 ea_list
->ea
.value
.length
);
544 total_data_size
-= 4 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
;
545 p
+= 4 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
;
548 ret_data_size
= PTR_DIFF(p
, pdata
);
549 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size
));
550 SIVAL(pdata
,0,ret_data_size
);
551 return ret_data_size
;
554 static NTSTATUS
fill_ea_chained_buffer(TALLOC_CTX
*mem_ctx
,
556 unsigned int total_data_size
,
557 unsigned int *ret_data_size
,
558 connection_struct
*conn
,
559 struct ea_list
*ea_list
)
561 uint8_t *p
= (uint8_t *)pdata
;
562 uint8_t *last_start
= NULL
;
563 bool do_store_data
= (pdata
!= NULL
);
567 if (!lp_ea_support(SNUM(conn
))) {
568 return NT_STATUS_NO_EAS_ON_FILE
;
571 for (; ea_list
; ea_list
= ea_list
->next
) {
577 if (last_start
!= NULL
&& do_store_data
) {
578 SIVAL(last_start
, 0, PTR_DIFF(p
, last_start
));
582 push_ascii_fstring(dos_ea_name
, ea_list
->ea
.name
);
583 dos_namelen
= strlen(dos_ea_name
);
584 if (dos_namelen
> 255 || dos_namelen
== 0) {
585 return NT_STATUS_INTERNAL_ERROR
;
587 if (ea_list
->ea
.value
.length
> 65535) {
588 return NT_STATUS_INTERNAL_ERROR
;
591 this_size
= 0x08 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
;
594 pad
= (4 - (this_size
% 4)) % 4;
599 if (this_size
> total_data_size
) {
600 return NT_STATUS_INFO_LENGTH_MISMATCH
;
603 /* We know we have room. */
604 SIVAL(p
, 0x00, 0); /* next offset */
605 SCVAL(p
, 0x04, ea_list
->ea
.flags
);
606 SCVAL(p
, 0x05, dos_namelen
);
607 SSVAL(p
, 0x06, ea_list
->ea
.value
.length
);
608 strlcpy((char *)(p
+0x08), dos_ea_name
, dos_namelen
+1);
609 memcpy(p
+ 0x08 + dos_namelen
+ 1, ea_list
->ea
.value
.data
, ea_list
->ea
.value
.length
);
611 memset(p
+ 0x08 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
,
615 total_data_size
-= this_size
;
621 *ret_data_size
= PTR_DIFF(p
, pdata
);
622 DEBUG(10,("fill_ea_chained_buffer: data_size = %u\n", *ret_data_size
));
626 unsigned int estimate_ea_size(files_struct
*fsp
)
628 size_t total_ea_len
= 0;
630 struct ea_list
*ea_list
= NULL
;
638 if (!lp_ea_support(SNUM(fsp
->conn
))) {
642 mem_ctx
= talloc_stackframe();
644 /* If this is a stream fsp, then we need to instead find the
645 * estimated ea len from the main file, not the stream
646 * (streams cannot have EAs), but the estimate isn't just 0 in
648 fsp
= metadata_fsp(fsp
);
649 (void)get_ea_list_from_fsp(mem_ctx
,
654 if(conn_using_smb2(fsp
->conn
->sconn
)) {
655 unsigned int ret_data_size
;
657 * We're going to be using fill_ea_chained_buffer() to
658 * marshall EA's - this size is significantly larger
659 * than the SMB1 buffer. Re-calculate the size without
662 status
= fill_ea_chained_buffer(mem_ctx
,
668 if (!NT_STATUS_IS_OK(status
)) {
671 total_ea_len
= ret_data_size
;
673 TALLOC_FREE(mem_ctx
);
677 /****************************************************************************
678 Ensure the EA name is case insensitive by matching any existing EA name.
679 ****************************************************************************/
681 static void canonicalize_ea_name(files_struct
*fsp
,
682 fstring unix_ea_name
)
685 TALLOC_CTX
*mem_ctx
= talloc_tos();
686 struct ea_list
*ea_list
;
687 NTSTATUS status
= get_ea_list_from_fsp(mem_ctx
,
691 if (!NT_STATUS_IS_OK(status
)) {
695 for (; ea_list
; ea_list
= ea_list
->next
) {
696 if (strequal(&unix_ea_name
[5], ea_list
->ea
.name
)) {
697 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
698 &unix_ea_name
[5], ea_list
->ea
.name
));
699 strlcpy(&unix_ea_name
[5], ea_list
->ea
.name
, sizeof(fstring
)-5);
705 /****************************************************************************
706 Set or delete an extended attribute.
707 ****************************************************************************/
709 NTSTATUS
set_ea(connection_struct
*conn
, files_struct
*fsp
,
710 struct ea_list
*ea_list
)
713 bool posix_pathnames
= false;
715 if (!lp_ea_support(SNUM(conn
))) {
716 return NT_STATUS_EAS_NOT_SUPPORTED
;
720 return NT_STATUS_INVALID_HANDLE
;
723 posix_pathnames
= (fsp
->fsp_name
->flags
& SMB_FILENAME_POSIX_PATH
);
725 status
= refuse_symlink_fsp(fsp
);
726 if (!NT_STATUS_IS_OK(status
)) {
730 status
= check_any_access_fsp(fsp
, FILE_WRITE_EA
);
731 if (!NT_STATUS_IS_OK(status
)) {
735 /* Setting EAs on streams isn't supported. */
736 if (fsp_is_alternate_stream(fsp
)) {
737 return NT_STATUS_INVALID_PARAMETER
;
741 * Filter out invalid Windows EA names - before
742 * we set *any* of them.
745 if (!posix_pathnames
&& ea_list_has_invalid_name(ea_list
)) {
746 return STATUS_INVALID_EA_NAME
;
749 for (;ea_list
; ea_list
= ea_list
->next
) {
751 fstring unix_ea_name
;
754 * Complementing the forward mapping from POSIX EAs to
755 * Windows EAs in get_ea_list_from_fsp(), here we map in the
756 * opposite direction from Windows EAs to the 'user' namespace
757 * of POSIX EAs. Hence, all POSIX EA names the we set here must
758 * start with a 'user.' prefix.
760 fstrcpy(unix_ea_name
, "user.");
761 fstrcat(unix_ea_name
, ea_list
->ea
.name
);
763 canonicalize_ea_name(fsp
, unix_ea_name
);
765 DBG_DEBUG("ea_name %s ealen = %zu\n",
767 ea_list
->ea
.value
.length
);
769 if (samba_private_attr_name(unix_ea_name
)) {
770 DBG_DEBUG("ea name %s is a private Samba name.\n",
772 return NT_STATUS_ACCESS_DENIED
;
775 if (ea_list
->ea
.value
.length
== 0) {
776 /* Remove the attribute. */
777 DBG_DEBUG("deleting ea name %s on "
778 "file %s by file descriptor.\n",
779 unix_ea_name
, fsp_str_dbg(fsp
));
780 ret
= SMB_VFS_FREMOVEXATTR(fsp
, unix_ea_name
);
782 /* Removing a non existent attribute always succeeds. */
783 if (ret
== -1 && errno
== ENOATTR
) {
784 DBG_DEBUG("deleting ea name %s didn't exist - "
785 "succeeding by default.\n",
791 DBG_DEBUG("setting ea name %s on file "
792 "%s by file descriptor.\n",
795 ret
= SMB_VFS_FSETXATTR(fsp
, unix_ea_name
,
796 ea_list
->ea
.value
.data
, ea_list
->ea
.value
.length
, 0);
801 if (errno
== ENOTSUP
) {
802 return NT_STATUS_EAS_NOT_SUPPORTED
;
805 return map_nt_error_from_unix(errno
);
812 /****************************************************************************
813 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
814 ****************************************************************************/
816 struct ea_list
*read_ea_list(TALLOC_CTX
*ctx
, const char *pdata
, size_t data_size
)
818 struct ea_list
*ea_list_head
= NULL
;
820 size_t bytes_used
= 0;
822 while (offset
< data_size
) {
823 struct ea_list
*eal
= read_ea_list_entry(ctx
, pdata
+ offset
, data_size
- offset
, &bytes_used
);
829 DLIST_ADD_END(ea_list_head
, eal
);
830 offset
+= bytes_used
;
836 /****************************************************************************
837 Count the total EA size needed.
838 ****************************************************************************/
840 static size_t ea_list_size(struct ea_list
*ealist
)
843 struct ea_list
*listp
;
846 for (listp
= ealist
; listp
; listp
= listp
->next
) {
847 push_ascii_fstring(dos_ea_name
, listp
->ea
.name
);
848 ret
+= 4 + strlen(dos_ea_name
) + 1 + listp
->ea
.value
.length
;
850 /* Add on 4 for total length. */
858 /****************************************************************************
859 Return a union of EA's from a file list and a list of names.
860 The TALLOC context for the two lists *MUST* be identical as we steal
861 memory from one list to add to another. JRA.
862 ****************************************************************************/
864 static struct ea_list
*ea_list_union(struct ea_list
*name_list
, struct ea_list
*file_list
, size_t *total_ea_len
)
866 struct ea_list
*nlistp
, *flistp
;
868 for (nlistp
= name_list
; nlistp
; nlistp
= nlistp
->next
) {
869 for (flistp
= file_list
; flistp
; flistp
= flistp
->next
) {
870 if (strequal(nlistp
->ea
.name
, flistp
->ea
.name
)) {
876 /* Copy the data from this entry. */
877 nlistp
->ea
.flags
= flistp
->ea
.flags
;
878 nlistp
->ea
.value
= flistp
->ea
.value
;
881 nlistp
->ea
.flags
= 0;
882 ZERO_STRUCT(nlistp
->ea
.value
);
886 *total_ea_len
= ea_list_size(name_list
);
890 /****************************************************************************
891 Map wire perms onto standard UNIX permissions. Obey share restrictions.
892 ****************************************************************************/
894 NTSTATUS
unix_perms_from_wire(connection_struct
*conn
,
895 const SMB_STRUCT_STAT
*psbuf
,
901 if (perms
== SMB_MODE_NO_CHANGE
) {
902 if (!VALID_STAT(*psbuf
)) {
903 return NT_STATUS_INVALID_PARAMETER
;
905 *ret_perms
= psbuf
->st_ex_mode
;
909 ret
= wire_perms_to_unix(perms
);
915 /****************************************************************************
916 Get a level dependent lanman2 dir entry.
917 ****************************************************************************/
919 struct smbd_dirptr_lanman2_state
{
920 connection_struct
*conn
;
922 bool check_mangled_names
;
926 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX
*ctx
,
932 struct smbd_dirptr_lanman2_state
*state
=
933 (struct smbd_dirptr_lanman2_state
*)private_data
;
935 char mangled_name
[13]; /* mangled 8.3 name. */
939 /* Mangle fname if it's an illegal name. */
940 if (mangle_must_mangle(dname
, state
->conn
->params
)) {
942 * Slow path - ensure we can push the original name as UCS2. If
943 * not, then just don't return this name.
947 size_t len
= (strlen(dname
) + 2) * 4; /* Allow enough space. */
948 uint8_t *tmp
= talloc_array(talloc_tos(),
952 status
= srvstr_push(NULL
,
953 FLAGS2_UNICODE_STRINGS
,
962 if (!NT_STATUS_IS_OK(status
)) {
966 ok
= name_to_8_3(dname
, mangled_name
,
967 true, state
->conn
->params
);
971 fname
= mangled_name
;
976 got_match
= mask_match(fname
, mask
,
977 state
->case_sensitive
);
979 if(!got_match
&& state
->check_mangled_names
&&
980 !mangle_is_8_3(fname
, false, state
->conn
->params
)) {
982 * It turns out that NT matches wildcards against
983 * both long *and* short names. This may explain some
984 * of the wildcard weirdness from old DOS clients
985 * that some people have been seeing.... JRA.
987 /* Force the mangling into 8.3. */
988 ok
= name_to_8_3(fname
, mangled_name
,
989 false, state
->conn
->params
);
994 got_match
= mask_match(mangled_name
, mask
,
995 state
->case_sensitive
);
1002 *_fname
= talloc_strdup(ctx
, fname
);
1003 if (*_fname
== NULL
) {
1010 static uint32_t get_dirent_ea_size(uint32_t mode
, files_struct
*fsp
)
1012 uint32_t ea_size
= IO_REPARSE_TAG_DFS
;
1014 if (mode
& FILE_ATTRIBUTE_REPARSE_POINT
) {
1015 (void)fsctl_get_reparse_tag(fsp
, &ea_size
);
1017 ea_size
= estimate_ea_size(fsp
);
1023 static NTSTATUS
smbd_marshall_dir_entry(TALLOC_CTX
*ctx
,
1024 connection_struct
*conn
,
1026 uint32_t info_level
,
1027 struct ea_list
*name_list
,
1028 bool check_mangled_names
,
1029 bool requires_resume_key
,
1032 const struct smb_filename
*smb_fname
,
1033 int space_remaining
,
1039 uint64_t *last_entry_off
)
1041 char *p
, *q
, *pdata
= *ppdata
;
1043 uint64_t file_size
= 0;
1044 uint64_t allocation_size
= 0;
1045 uint64_t file_id
= 0;
1047 struct timespec mdate_ts
= {0};
1048 struct timespec adate_ts
= {0};
1049 struct timespec cdate_ts
= {0};
1050 struct timespec create_date_ts
= {0};
1052 char *last_entry_ptr
;
1057 struct readdir_attr_data
*readdir_attr_data
= NULL
;
1060 if (!(mode
& FILE_ATTRIBUTE_DIRECTORY
)) {
1061 file_size
= get_file_size_stat(&smb_fname
->st
);
1063 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
, NULL
, &smb_fname
->st
);
1066 * Skip SMB_VFS_FREADDIR_ATTR if the directory entry is a symlink or
1069 if (smb_fname
->fsp
!= NULL
&&
1070 !(mode
& FILE_ATTRIBUTE_REPARSE_POINT
)) {
1071 status
= SMB_VFS_FREADDIR_ATTR(smb_fname
->fsp
,
1073 &readdir_attr_data
);
1074 if (!NT_STATUS_IS_OK(status
)) {
1075 if (!NT_STATUS_EQUAL(NT_STATUS_NOT_SUPPORTED
,
1082 file_id
= SMB_VFS_FS_FILE_ID(conn
, &smb_fname
->st
);
1084 mdate_ts
= smb_fname
->st
.st_ex_mtime
;
1085 adate_ts
= smb_fname
->st
.st_ex_atime
;
1086 create_date_ts
= get_create_timespec(conn
, NULL
, smb_fname
);
1087 cdate_ts
= get_change_timespec(conn
, NULL
, smb_fname
);
1089 if (lp_dos_filetime_resolution(SNUM(conn
))) {
1090 dos_filetime_timespec(&create_date_ts
);
1091 dos_filetime_timespec(&mdate_ts
);
1092 dos_filetime_timespec(&adate_ts
);
1093 dos_filetime_timespec(&cdate_ts
);
1096 /* align the record */
1097 SMB_ASSERT(align
>= 1);
1099 off
= (int)PTR_DIFF(pdata
, base_data
);
1100 pad
= (off
+ (align
-1)) & ~(align
-1);
1103 if (pad
&& pad
> space_remaining
) {
1104 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1105 "for padding (wanted %u, had %d)\n",
1108 return STATUS_MORE_ENTRIES
; /* Not finished - just out of space */
1112 /* initialize padding to 0 */
1114 memset(pdata
, 0, pad
);
1116 space_remaining
-= pad
;
1118 DBG_DEBUG("space_remaining = %d\n", space_remaining
);
1127 switch (info_level
) {
1128 case SMB_FIND_INFO_STANDARD
:
1129 DBG_DEBUG("SMB_FIND_INFO_STANDARD\n");
1130 if(requires_resume_key
) {
1134 srv_put_dos_date2_ts(p
, 0, create_date_ts
);
1135 srv_put_dos_date2_ts(p
, 4, adate_ts
);
1136 srv_put_dos_date2_ts(p
, 8, mdate_ts
);
1137 SIVAL(p
,12,(uint32_t)file_size
);
1138 SIVAL(p
,16,(uint32_t)allocation_size
);
1142 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1143 p
+= ucs2_align(base_data
, p
, 0);
1145 status
= srvstr_push(base_data
, flags2
, p
,
1146 fname
, PTR_DIFF(end_data
, p
),
1147 STR_TERMINATE
, &len
);
1148 if (!NT_STATUS_IS_OK(status
)) {
1151 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1153 SCVAL(nameptr
, -1, len
- 2);
1155 SCVAL(nameptr
, -1, 0);
1159 SCVAL(nameptr
, -1, len
- 1);
1161 SCVAL(nameptr
, -1, 0);
1167 case SMB_FIND_EA_SIZE
:
1168 DBG_DEBUG("SMB_FIND_EA_SIZE\n");
1169 if (requires_resume_key
) {
1173 srv_put_dos_date2_ts(p
, 0, create_date_ts
);
1174 srv_put_dos_date2_ts(p
, 4, adate_ts
);
1175 srv_put_dos_date2_ts(p
, 8, mdate_ts
);
1176 SIVAL(p
,12,(uint32_t)file_size
);
1177 SIVAL(p
,16,(uint32_t)allocation_size
);
1180 ea_size
= estimate_ea_size(smb_fname
->fsp
);
1181 SIVAL(p
,22,ea_size
); /* Extended attributes */
1185 status
= srvstr_push(base_data
, flags2
,
1186 p
, fname
, PTR_DIFF(end_data
, p
),
1187 STR_TERMINATE
| STR_NOALIGN
, &len
);
1188 if (!NT_STATUS_IS_OK(status
)) {
1191 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1204 SCVAL(nameptr
,0,len
);
1206 SCVAL(p
,0,0); p
+= 1; /* Extra zero byte ? - why.. */
1209 case SMB_FIND_EA_LIST
:
1211 struct ea_list
*file_list
= NULL
;
1214 DBG_DEBUG("SMB_FIND_EA_LIST\n");
1216 return NT_STATUS_INVALID_PARAMETER
;
1218 if (requires_resume_key
) {
1222 srv_put_dos_date2_ts(p
, 0, create_date_ts
);
1223 srv_put_dos_date2_ts(p
, 4, adate_ts
);
1224 srv_put_dos_date2_ts(p
, 8, mdate_ts
);
1225 SIVAL(p
,12,(uint32_t)file_size
);
1226 SIVAL(p
,16,(uint32_t)allocation_size
);
1228 p
+= 22; /* p now points to the EA area. */
1230 status
= get_ea_list_from_fsp(ctx
,
1232 &ea_len
, &file_list
);
1233 if (!NT_STATUS_IS_OK(status
)) {
1236 name_list
= ea_list_union(name_list
, file_list
, &ea_len
);
1238 /* We need to determine if this entry will fit in the space available. */
1239 /* Max string size is 255 bytes. */
1240 if (PTR_DIFF(p
+ 255 + ea_len
,pdata
) > space_remaining
) {
1241 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1242 "(wanted %u, had %d)\n",
1243 (unsigned int)PTR_DIFF(p
+ 255 + ea_len
,pdata
),
1245 return STATUS_MORE_ENTRIES
; /* Not finished - just out of space */
1248 /* Push the ea_data followed by the name. */
1249 p
+= fill_ea_buffer(ctx
, p
, space_remaining
, conn
, name_list
);
1251 status
= srvstr_push(base_data
, flags2
,
1252 p
+ 1, fname
, PTR_DIFF(end_data
, p
+1),
1253 STR_TERMINATE
| STR_NOALIGN
, &len
);
1254 if (!NT_STATUS_IS_OK(status
)) {
1257 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1270 SCVAL(nameptr
,0,len
);
1272 SCVAL(p
,0,0); p
+= 1; /* Extra zero byte ? - why.. */
1276 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
1277 DBG_DEBUG("SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n");
1278 was_8_3
= mangle_is_8_3(fname
, True
, conn
->params
);
1280 SIVAL(p
,0,reskey
); p
+= 4;
1281 put_long_date_full_timespec(conn
->ts_res
,p
,&create_date_ts
); p
+= 8;
1282 put_long_date_full_timespec(conn
->ts_res
,p
,&adate_ts
); p
+= 8;
1283 put_long_date_full_timespec(conn
->ts_res
,p
,&mdate_ts
); p
+= 8;
1284 put_long_date_full_timespec(conn
->ts_res
,p
,&cdate_ts
); p
+= 8;
1285 SOFF_T(p
,0,file_size
); p
+= 8;
1286 SOFF_T(p
,0,allocation_size
); p
+= 8;
1287 SIVAL(p
,0,mode
); p
+= 4;
1288 q
= p
; p
+= 4; /* q is placeholder for name length. */
1289 ea_size
= get_dirent_ea_size(mode
, smb_fname
->fsp
);
1290 SIVAL(p
, 0, ea_size
);
1292 /* Clear the short name buffer. This is
1293 * IMPORTANT as not doing so will trigger
1294 * a Win2k client bug. JRA.
1296 if (!was_8_3
&& check_mangled_names
) {
1297 char mangled_name
[13]; /* mangled 8.3 name. */
1298 if (!name_to_8_3(fname
,mangled_name
,True
,
1300 /* Error - mangle failed ! */
1301 memset(mangled_name
,'\0',12);
1303 mangled_name
[12] = 0;
1304 status
= srvstr_push(base_data
, flags2
,
1305 p
+2, mangled_name
, 24,
1306 STR_UPPER
|STR_UNICODE
, &len
);
1307 if (!NT_STATUS_IS_OK(status
)) {
1311 memset(p
+ 2 + len
,'\0',24 - len
);
1318 status
= srvstr_push(base_data
, flags2
, p
,
1319 fname
, PTR_DIFF(end_data
, p
),
1320 STR_TERMINATE_ASCII
, &len
);
1321 if (!NT_STATUS_IS_OK(status
)) {
1327 len
= PTR_DIFF(p
, pdata
);
1328 pad
= (len
+ (align
-1)) & ~(align
-1);
1330 * offset to the next entry, the caller
1331 * will overwrite it for the last entry
1332 * that's why we always include the padding
1336 * set padding to zero
1339 memset(p
, 0, pad
- len
);
1346 case SMB_FIND_FILE_DIRECTORY_INFO
:
1347 DBG_DEBUG("SMB_FIND_FILE_DIRECTORY_INFO\n");
1349 SIVAL(p
,0,reskey
); p
+= 4;
1350 put_long_date_full_timespec(conn
->ts_res
,p
,&create_date_ts
); p
+= 8;
1351 put_long_date_full_timespec(conn
->ts_res
,p
,&adate_ts
); p
+= 8;
1352 put_long_date_full_timespec(conn
->ts_res
,p
,&mdate_ts
); p
+= 8;
1353 put_long_date_full_timespec(conn
->ts_res
,p
,&cdate_ts
); p
+= 8;
1354 SOFF_T(p
,0,file_size
); p
+= 8;
1355 SOFF_T(p
,0,allocation_size
); p
+= 8;
1356 SIVAL(p
,0,mode
); p
+= 4;
1357 status
= srvstr_push(base_data
, flags2
,
1358 p
+ 4, fname
, PTR_DIFF(end_data
, p
+4),
1359 STR_TERMINATE_ASCII
, &len
);
1360 if (!NT_STATUS_IS_OK(status
)) {
1366 len
= PTR_DIFF(p
, pdata
);
1367 pad
= (len
+ (align
-1)) & ~(align
-1);
1369 * offset to the next entry, the caller
1370 * will overwrite it for the last entry
1371 * that's why we always include the padding
1375 * set padding to zero
1378 memset(p
, 0, pad
- len
);
1385 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
1386 DBG_DEBUG("SMB_FIND_FILE_FULL_DIRECTORY_INFO\n");
1388 SIVAL(p
,0,reskey
); p
+= 4;
1389 put_long_date_full_timespec(conn
->ts_res
,p
,&create_date_ts
); p
+= 8;
1390 put_long_date_full_timespec(conn
->ts_res
,p
,&adate_ts
); p
+= 8;
1391 put_long_date_full_timespec(conn
->ts_res
,p
,&mdate_ts
); p
+= 8;
1392 put_long_date_full_timespec(conn
->ts_res
,p
,&cdate_ts
); p
+= 8;
1393 SOFF_T(p
,0,file_size
); p
+= 8;
1394 SOFF_T(p
,0,allocation_size
); p
+= 8;
1395 SIVAL(p
,0,mode
); p
+= 4;
1396 q
= p
; p
+= 4; /* q is placeholder for name length. */
1397 ea_size
= get_dirent_ea_size(mode
, smb_fname
->fsp
);
1398 SIVAL(p
, 0, ea_size
);
1400 status
= srvstr_push(base_data
, flags2
, p
,
1401 fname
, PTR_DIFF(end_data
, p
),
1402 STR_TERMINATE_ASCII
, &len
);
1403 if (!NT_STATUS_IS_OK(status
)) {
1409 len
= PTR_DIFF(p
, pdata
);
1410 pad
= (len
+ (align
-1)) & ~(align
-1);
1412 * offset to the next entry, the caller
1413 * will overwrite it for the last entry
1414 * that's why we always include the padding
1418 * set padding to zero
1421 memset(p
, 0, pad
- len
);
1428 case SMB_FIND_FILE_NAMES_INFO
:
1429 DBG_DEBUG("SMB_FIND_FILE_NAMES_INFO\n");
1431 SIVAL(p
,0,reskey
); p
+= 4;
1433 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1434 acl on a dir (tridge) */
1435 status
= srvstr_push(base_data
, flags2
, p
,
1436 fname
, PTR_DIFF(end_data
, p
),
1437 STR_TERMINATE_ASCII
, &len
);
1438 if (!NT_STATUS_IS_OK(status
)) {
1444 len
= PTR_DIFF(p
, pdata
);
1445 pad
= (len
+ (align
-1)) & ~(align
-1);
1447 * offset to the next entry, the caller
1448 * will overwrite it for the last entry
1449 * that's why we always include the padding
1453 * set padding to zero
1456 memset(p
, 0, pad
- len
);
1463 case SMB_FIND_ID_FULL_DIRECTORY_INFO
:
1464 DBG_DEBUG("SMB_FIND_ID_FULL_DIRECTORY_INFO\n");
1466 SIVAL(p
,0,reskey
); p
+= 4;
1467 put_long_date_full_timespec(conn
->ts_res
,p
,&create_date_ts
); p
+= 8;
1468 put_long_date_full_timespec(conn
->ts_res
,p
,&adate_ts
); p
+= 8;
1469 put_long_date_full_timespec(conn
->ts_res
,p
,&mdate_ts
); p
+= 8;
1470 put_long_date_full_timespec(conn
->ts_res
,p
,&cdate_ts
); p
+= 8;
1471 SOFF_T(p
,0,file_size
); p
+= 8;
1472 SOFF_T(p
,0,allocation_size
); p
+= 8;
1473 SIVAL(p
,0,mode
); p
+= 4;
1474 q
= p
; p
+= 4; /* q is placeholder for name length. */
1475 ea_size
= get_dirent_ea_size(mode
, smb_fname
->fsp
);
1476 SIVAL(p
, 0, ea_size
);
1478 SIVAL(p
,0,0); p
+= 4; /* Unknown - reserved ? */
1479 SBVAL(p
,0,file_id
); p
+= 8;
1480 status
= srvstr_push(base_data
, flags2
, p
,
1481 fname
, PTR_DIFF(end_data
, p
),
1482 STR_TERMINATE_ASCII
, &len
);
1483 if (!NT_STATUS_IS_OK(status
)) {
1489 len
= PTR_DIFF(p
, pdata
);
1490 pad
= (len
+ (align
-1)) & ~(align
-1);
1492 * offset to the next entry, the caller
1493 * will overwrite it for the last entry
1494 * that's why we always include the padding
1498 * set padding to zero
1501 memset(p
, 0, pad
- len
);
1508 case SMB_FIND_ID_BOTH_DIRECTORY_INFO
:
1509 DBG_DEBUG("SMB_FIND_ID_BOTH_DIRECTORY_INFO\n");
1510 was_8_3
= mangle_is_8_3(fname
, True
, conn
->params
);
1512 SIVAL(p
,0,reskey
); p
+= 4;
1513 put_long_date_full_timespec(conn
->ts_res
,p
,&create_date_ts
); p
+= 8;
1514 put_long_date_full_timespec(conn
->ts_res
,p
,&adate_ts
); p
+= 8;
1515 put_long_date_full_timespec(conn
->ts_res
,p
,&mdate_ts
); p
+= 8;
1516 put_long_date_full_timespec(conn
->ts_res
,p
,&cdate_ts
); p
+= 8;
1517 SOFF_T(p
,0,file_size
); p
+= 8;
1518 SOFF_T(p
,0,allocation_size
); p
+= 8;
1519 SIVAL(p
,0,mode
); p
+= 4;
1520 q
= p
; p
+= 4; /* q is placeholder for name length */
1521 if (readdir_attr_data
&&
1522 readdir_attr_data
->type
== RDATTR_AAPL
) {
1524 * OS X specific SMB2 extension negotiated via
1525 * AAPL create context: return max_access in
1528 ea_size
= readdir_attr_data
->attr_data
.aapl
.max_access
;
1530 ea_size
= get_dirent_ea_size(mode
, smb_fname
->fsp
);
1532 SIVAL(p
,0,ea_size
); /* Extended attributes */
1535 if (readdir_attr_data
&&
1536 readdir_attr_data
->type
== RDATTR_AAPL
) {
1538 * OS X specific SMB2 extension negotiated via
1539 * AAPL create context: return resource fork
1540 * length and compressed FinderInfo in
1543 * According to documentation short_name_len
1544 * should be 0, but on the wire behaviour
1545 * shows its set to 24 by clients.
1549 /* Resourefork length */
1550 SBVAL(p
, 2, readdir_attr_data
->attr_data
.aapl
.rfork_size
);
1552 /* Compressed FinderInfo */
1553 memcpy(p
+ 10, &readdir_attr_data
->attr_data
.aapl
.finder_info
, 16);
1554 } else if (!was_8_3
&& check_mangled_names
) {
1555 char mangled_name
[13]; /* mangled 8.3 name. */
1556 if (!name_to_8_3(fname
,mangled_name
,True
,
1558 /* Error - mangle failed ! */
1559 memset(mangled_name
,'\0',12);
1561 mangled_name
[12] = 0;
1562 status
= srvstr_push(base_data
, flags2
,
1563 p
+2, mangled_name
, 24,
1564 STR_UPPER
|STR_UNICODE
, &len
);
1565 if (!NT_STATUS_IS_OK(status
)) {
1570 memset(p
+ 2 + len
,'\0',24 - len
);
1574 /* Clear the short name buffer. This is
1575 * IMPORTANT as not doing so will trigger
1576 * a Win2k client bug. JRA.
1583 if (readdir_attr_data
&&
1584 readdir_attr_data
->type
== RDATTR_AAPL
) {
1586 * OS X specific SMB2 extension negotiated via
1587 * AAPL create context: return UNIX mode in
1590 uint16_t aapl_mode
= (uint16_t)readdir_attr_data
->attr_data
.aapl
.unix_mode
;
1591 SSVAL(p
, 0, aapl_mode
);
1597 SBVAL(p
,0,file_id
); p
+= 8;
1598 status
= srvstr_push(base_data
, flags2
, p
,
1599 fname
, PTR_DIFF(end_data
, p
),
1600 STR_TERMINATE_ASCII
, &len
);
1601 if (!NT_STATUS_IS_OK(status
)) {
1607 len
= PTR_DIFF(p
, pdata
);
1608 pad
= (len
+ (align
-1)) & ~(align
-1);
1610 * offset to the next entry, the caller
1611 * will overwrite it for the last entry
1612 * that's why we always include the padding
1616 * set padding to zero
1619 memset(p
, 0, pad
- len
);
1626 /* CIFS UNIX Extension. */
1628 case SMB_FIND_FILE_UNIX
:
1629 case SMB_FIND_FILE_UNIX_INFO2
:
1631 SIVAL(p
,0,reskey
); p
+= 4; /* Used for continuing search. */
1633 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1635 if (info_level
== SMB_FIND_FILE_UNIX
) {
1636 DBG_DEBUG("SMB_FIND_FILE_UNIX\n");
1637 p
= store_file_unix_basic(conn
, p
,
1638 NULL
, &smb_fname
->st
);
1639 status
= srvstr_push(base_data
, flags2
, p
,
1640 fname
, PTR_DIFF(end_data
, p
),
1641 STR_TERMINATE
, &len
);
1642 if (!NT_STATUS_IS_OK(status
)) {
1646 DBG_DEBUG("SMB_FIND_FILE_UNIX_INFO2\n");
1647 p
= store_file_unix_basic_info2(conn
, p
,
1648 NULL
, &smb_fname
->st
);
1651 status
= srvstr_push(base_data
, flags2
, p
, fname
,
1652 PTR_DIFF(end_data
, p
), 0, &len
);
1653 if (!NT_STATUS_IS_OK(status
)) {
1656 SIVAL(nameptr
, 0, len
);
1661 len
= PTR_DIFF(p
, pdata
);
1662 pad
= (len
+ (align
-1)) & ~(align
-1);
1664 * offset to the next entry, the caller
1665 * will overwrite it for the last entry
1666 * that's why we always include the padding
1670 * set padding to zero
1673 memset(p
, 0, pad
- len
);
1678 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1682 /* SMB2 UNIX Extension. */
1684 case SMB2_FILE_POSIX_INFORMATION
:
1686 struct smb3_file_posix_information info
= {};
1687 uint8_t buf
[sizeof(info
)];
1688 struct ndr_push ndr
= {
1690 .alloc_size
= sizeof(buf
),
1691 .fixed_buf_size
= true,
1693 enum ndr_err_code ndr_err
;
1696 DBG_DEBUG("SMB2_FILE_POSIX_INFORMATION\n");
1699 SIVAL(p
,0,reskey
); p
+= 4;
1701 if (!conn_using_smb2(conn
->sconn
)) {
1702 return NT_STATUS_INVALID_LEVEL
;
1705 if (mode
& FILE_ATTRIBUTE_REPARSE_POINT
) {
1706 status
= fsctl_get_reparse_tag(smb_fname
->fsp
,
1708 if (!NT_STATUS_IS_OK(status
)) {
1709 DBG_DEBUG("Could not get reparse "
1711 smb_fname_str_dbg(smb_fname
),
1717 smb3_file_posix_information_init(
1718 conn
, &smb_fname
->st
, tag
, mode
, &info
);
1720 ndr_err
= ndr_push_smb3_file_posix_information(
1721 &ndr
, NDR_SCALARS
|NDR_BUFFERS
, &info
);
1722 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
1723 return NT_STATUS_INSUFFICIENT_RESOURCES
;
1726 memcpy(p
, buf
, ndr
.offset
);
1731 status
= srvstr_push(base_data
, flags2
, p
, fname
,
1732 PTR_DIFF(end_data
, p
), 0, &len
);
1733 if (!NT_STATUS_IS_OK(status
)) {
1736 SIVAL(nameptr
, 0, len
);
1740 len
= PTR_DIFF(p
, pdata
);
1741 pad
= (len
+ (align
-1)) & ~(align
-1);
1743 * offset to the next entry, the caller
1744 * will overwrite it for the last entry
1745 * that's why we always include the padding
1752 return NT_STATUS_INVALID_LEVEL
;
1755 if (PTR_DIFF(p
,pdata
) > space_remaining
) {
1756 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1757 "(wanted %u, had %d)\n",
1758 (unsigned int)PTR_DIFF(p
,pdata
),
1760 return STATUS_MORE_ENTRIES
; /* Not finished - just out of space */
1763 /* Setup the last entry pointer, as an offset from base_data */
1764 *last_entry_off
= PTR_DIFF(last_entry_ptr
,base_data
);
1765 /* Advance the data pointer to the next slot */
1768 return NT_STATUS_OK
;
1771 NTSTATUS
smbd_dirptr_lanman2_entry(TALLOC_CTX
*ctx
,
1772 connection_struct
*conn
,
1773 struct dptr_struct
*dirptr
,
1775 const char *path_mask
,
1778 int requires_resume_key
,
1787 int space_remaining
,
1788 struct smb_filename
**_smb_fname
,
1789 int *_last_entry_off
,
1790 struct ea_list
*name_list
,
1791 struct file_id
*file_id
)
1794 const char *mask
= NULL
;
1797 struct smb_filename
*smb_fname
= NULL
;
1798 struct smbd_dirptr_lanman2_state state
;
1800 uint64_t last_entry_off
= 0;
1802 enum mangled_names_options mangled_names
;
1803 bool marshall_with_83_names
;
1805 mangled_names
= lp_mangled_names(conn
->params
);
1809 state
.info_level
= info_level
;
1810 if (mangled_names
!= MANGLED_NAMES_NO
) {
1811 state
.check_mangled_names
= true;
1813 state
.case_sensitive
= dptr_case_sensitive(dirptr
);
1815 p
= strrchr_m(path_mask
,'/');
1826 ok
= smbd_dirptr_get_entry(ctx
,
1833 smbd_dirptr_lanman2_match_fn
,
1839 return NT_STATUS_END_OF_FILE
;
1842 marshall_with_83_names
= (mangled_names
== MANGLED_NAMES_YES
);
1844 status
= smbd_marshall_dir_entry(ctx
,
1849 marshall_with_83_names
,
1850 requires_resume_key
,
1861 if (NT_STATUS_EQUAL(status
, NT_STATUS_ILLEGAL_CHARACTER
)) {
1862 DEBUG(1,("Conversion error: illegal character: %s\n",
1863 smb_fname_str_dbg(smb_fname
)));
1866 if (file_id
!= NULL
) {
1867 *file_id
= vfs_file_id_from_sbuf(conn
, &smb_fname
->st
);
1870 if (NT_STATUS_EQUAL(status
, STATUS_MORE_ENTRIES
)) {
1871 smbd_dirptr_push_overflow(dirptr
, &fname
, &smb_fname
, mode
);
1874 if (!NT_STATUS_IS_OK(status
)) {
1875 TALLOC_FREE(smb_fname
);
1880 smbd_dirptr_set_last_name_sent(dirptr
, &smb_fname
->base_name
);
1882 if (_smb_fname
!= NULL
) {
1884 * smb_fname is already talloc'ed off ctx.
1885 * We just need to make sure we don't return
1886 * any stream_name, and replace base_name
1887 * with fname in case base_name got mangled.
1888 * This allows us to preserve any smb_fname->fsp
1889 * for asynchronous handle lookups.
1891 TALLOC_FREE(smb_fname
->stream_name
);
1894 * smbd_dirptr_set_last_name_sent() above consumed
1897 smb_fname
->base_name
= talloc_strdup(smb_fname
, fname
);
1899 if (smb_fname
->base_name
== NULL
) {
1900 TALLOC_FREE(smb_fname
);
1902 return NT_STATUS_NO_MEMORY
;
1904 *_smb_fname
= smb_fname
;
1906 TALLOC_FREE(smb_fname
);
1910 *_last_entry_off
= last_entry_off
;
1911 return NT_STATUS_OK
;
1914 unsigned char *create_volume_objectid(connection_struct
*conn
, unsigned char objid
[16])
1916 const struct loadparm_substitution
*lp_sub
=
1917 loadparm_s3_global_substitution();
1919 E_md4hash(lp_servicename(talloc_tos(), lp_sub
, SNUM(conn
)),objid
);
1923 static void samba_extended_info_version(struct smb_extended_info
*extended_info
)
1925 SMB_ASSERT(extended_info
!= NULL
);
1927 extended_info
->samba_magic
= SAMBA_EXTENDED_INFO_MAGIC
;
1928 extended_info
->samba_version
= ((SAMBA_VERSION_MAJOR
& 0xff) << 24)
1929 | ((SAMBA_VERSION_MINOR
& 0xff) << 16)
1930 | ((SAMBA_VERSION_RELEASE
& 0xff) << 8);
1931 #ifdef SAMBA_VERSION_REVISION
1932 extended_info
->samba_version
|= (tolower(*SAMBA_VERSION_REVISION
) - 'a' + 1) & 0xff;
1934 extended_info
->samba_subversion
= 0;
1935 #ifdef SAMBA_VERSION_RC_RELEASE
1936 extended_info
->samba_subversion
|= (SAMBA_VERSION_RC_RELEASE
& 0xff) << 24;
1938 #ifdef SAMBA_VERSION_PRE_RELEASE
1939 extended_info
->samba_subversion
|= (SAMBA_VERSION_PRE_RELEASE
& 0xff) << 16;
1942 #ifdef SAMBA_VERSION_VENDOR_PATCH
1943 extended_info
->samba_subversion
|= (SAMBA_VERSION_VENDOR_PATCH
& 0xffff);
1945 extended_info
->samba_gitcommitdate
= 0;
1946 #ifdef SAMBA_VERSION_COMMIT_TIME
1947 unix_to_nt_time(&extended_info
->samba_gitcommitdate
, SAMBA_VERSION_COMMIT_TIME
);
1950 memset(extended_info
->samba_version_string
, 0,
1951 sizeof(extended_info
->samba_version_string
));
1953 snprintf (extended_info
->samba_version_string
,
1954 sizeof(extended_info
->samba_version_string
),
1955 "%s", samba_version_string());
1958 static bool fsinfo_unix_valid_level(connection_struct
*conn
,
1959 struct files_struct
*fsp
,
1960 uint16_t info_level
)
1962 if (conn_using_smb2(conn
->sconn
) &&
1963 fsp
->fsp_flags
.posix_open
&&
1964 info_level
== SMB2_FS_POSIX_INFORMATION_INTERNAL
)
1968 #if defined(SMB1SERVER)
1969 if (lp_smb1_unix_extensions() &&
1970 info_level
== SMB_QUERY_POSIX_FS_INFO
) {
1978 * fsp is only valid for SMB2.
1980 NTSTATUS
smbd_do_qfsinfo(struct smbXsrv_connection
*xconn
,
1981 connection_struct
*conn
,
1982 TALLOC_CTX
*mem_ctx
,
1983 uint16_t info_level
,
1985 unsigned int max_data_bytes
,
1986 size_t *fixed_portion
,
1987 struct files_struct
*fsp
,
1988 struct smb_filename
*fname
,
1992 const struct loadparm_substitution
*lp_sub
=
1993 loadparm_s3_global_substitution();
1994 char *pdata
, *end_data
;
1997 const char *vname
= volume_label(talloc_tos(), SNUM(conn
));
1998 int snum
= SNUM(conn
);
1999 const char *fstype
= lp_fstype(SNUM(conn
));
2000 const char *filename
= NULL
;
2001 uint64_t bytes_per_sector
= 512;
2002 struct smb_filename smb_fname
;
2004 NTSTATUS status
= NT_STATUS_OK
;
2008 if (fname
== NULL
|| fname
->base_name
== NULL
) {
2011 filename
= fname
->base_name
;
2015 if (info_level
!= SMB_QUERY_CIFS_UNIX_INFO
) {
2016 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
2017 "info level (0x%x) on IPC$.\n",
2018 (unsigned int)info_level
));
2019 return NT_STATUS_ACCESS_DENIED
;
2023 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level
));
2025 smb_fname
= (struct smb_filename
) {
2026 .base_name
= discard_const_p(char, filename
),
2027 .flags
= fname
? fname
->flags
: 0,
2028 .twrp
= fname
? fname
->twrp
: 0,
2031 if(info_level
!= SMB_FS_QUOTA_INFORMATION
2032 && SMB_VFS_STAT(conn
, &smb_fname
) != 0) {
2033 DEBUG(2,("stat of . failed (%s)\n", strerror(errno
)));
2034 return map_nt_error_from_unix(errno
);
2039 if (max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
< max_data_bytes
) {
2040 return NT_STATUS_INVALID_PARAMETER
;
2043 *ppdata
= (char *)SMB_REALLOC(
2044 *ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
2045 if (*ppdata
== NULL
) {
2046 return NT_STATUS_NO_MEMORY
;
2050 memset((char *)pdata
,'\0',max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
2051 end_data
= pdata
+ max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
- 1;
2055 switch (info_level
) {
2056 case SMB_INFO_ALLOCATION
:
2058 uint64_t dfree
,dsize
,bsize
,block_size
,sectors_per_unit
;
2060 df_ret
= get_dfree_info(conn
, &smb_fname
, &bsize
,
2062 if (df_ret
== (uint64_t)-1) {
2063 return map_nt_error_from_unix(errno
);
2066 block_size
= lp_block_size(snum
);
2067 if (bsize
< block_size
) {
2068 uint64_t factor
= block_size
/bsize
;
2073 if (bsize
> block_size
) {
2074 uint64_t factor
= bsize
/block_size
;
2079 sectors_per_unit
= bsize
/bytes_per_sector
;
2081 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2082 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st
.st_ex_dev
, (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
2083 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
2086 * For large drives, return max values and not modulo.
2088 dsize
= MIN(dsize
, UINT32_MAX
);
2089 dfree
= MIN(dfree
, UINT32_MAX
);
2091 SIVAL(pdata
,l1_idFileSystem
,st
.st_ex_dev
);
2092 SIVAL(pdata
,l1_cSectorUnit
,sectors_per_unit
);
2093 SIVAL(pdata
,l1_cUnit
,dsize
);
2094 SIVAL(pdata
,l1_cUnitAvail
,dfree
);
2095 SSVAL(pdata
,l1_cbSector
,bytes_per_sector
);
2099 case SMB_INFO_VOLUME
:
2100 /* Return volume name */
2102 * Add volume serial number - hash of a combination of
2103 * the called hostname and the service name.
2105 serial
= generate_volume_serial_number(lp_sub
, snum
);
2106 SIVAL(pdata
,0,serial
);
2108 * Win2k3 and previous mess this up by sending a name length
2109 * one byte short. I believe only older clients (OS/2 Win9x) use
2110 * this call so try fixing this by adding a terminating null to
2111 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2113 status
= srvstr_push(
2115 pdata
+l2_vol_szVolLabel
, vname
,
2116 PTR_DIFF(end_data
, pdata
+l2_vol_szVolLabel
),
2117 STR_NOALIGN
|STR_TERMINATE
, &len
);
2118 if (!NT_STATUS_IS_OK(status
)) {
2121 SCVAL(pdata
,l2_vol_cch
,len
);
2122 data_len
= l2_vol_szVolLabel
+ len
;
2123 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %u, "
2124 "name = %s serial = 0x%04"PRIx32
"\n",
2125 (unsigned)convert_timespec_to_time_t(st
.st_ex_ctime
),
2126 (unsigned)len
, vname
, serial
));
2129 case SMB_QUERY_FS_ATTRIBUTE_INFO
:
2130 case SMB_FS_ATTRIBUTE_INFORMATION
:
2132 SIVAL(pdata
,0,FILE_CASE_PRESERVED_NAMES
|FILE_CASE_SENSITIVE_SEARCH
|
2133 FILE_SUPPORTS_OBJECT_IDS
|FILE_UNICODE_ON_DISK
|
2134 conn
->fs_capabilities
); /* FS ATTRIBUTES */
2136 SIVAL(pdata
,4,255); /* Max filename component length */
2137 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2138 and will think we can't do long filenames */
2139 status
= srvstr_push(pdata
, flags2
, pdata
+12, fstype
,
2140 PTR_DIFF(end_data
, pdata
+12),
2142 if (!NT_STATUS_IS_OK(status
)) {
2146 data_len
= 12 + len
;
2147 if (max_data_bytes
>= 16 && data_len
> max_data_bytes
) {
2148 /* the client only requested a portion of the
2150 data_len
= max_data_bytes
;
2151 status
= STATUS_BUFFER_OVERFLOW
;
2153 *fixed_portion
= 16;
2156 case SMB_QUERY_FS_LABEL_INFO
:
2157 case SMB_FS_LABEL_INFORMATION
:
2158 status
= srvstr_push(pdata
, flags2
, pdata
+4, vname
,
2159 PTR_DIFF(end_data
, pdata
+4), 0, &len
);
2160 if (!NT_STATUS_IS_OK(status
)) {
2167 case SMB_QUERY_FS_VOLUME_INFO
:
2168 case SMB_FS_VOLUME_INFORMATION
:
2169 put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER
,
2170 pdata
, &st
.st_ex_btime
);
2172 * Add volume serial number - hash of a combination of
2173 * the called hostname and the service name.
2175 serial
= generate_volume_serial_number(lp_sub
, snum
);
2176 SIVAL(pdata
,8,serial
);
2178 /* Max label len is 32 characters. */
2179 status
= srvstr_push(pdata
, flags2
, pdata
+18, vname
,
2180 PTR_DIFF(end_data
, pdata
+18),
2182 if (!NT_STATUS_IS_OK(status
)) {
2185 SIVAL(pdata
,12,len
);
2188 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO "
2189 "namelen = %d, vol=%s serv=%s "
2190 "serial=0x%04"PRIx32
"\n",
2191 (int)strlen(vname
),vname
,
2192 lp_servicename(talloc_tos(), lp_sub
, snum
),
2194 if (max_data_bytes
>= 24 && data_len
> max_data_bytes
) {
2195 /* the client only requested a portion of the
2197 data_len
= max_data_bytes
;
2198 status
= STATUS_BUFFER_OVERFLOW
;
2200 *fixed_portion
= 24;
2203 case SMB_QUERY_FS_SIZE_INFO
:
2204 case SMB_FS_SIZE_INFORMATION
:
2206 uint64_t dfree
,dsize
,bsize
,block_size
,sectors_per_unit
;
2208 df_ret
= get_dfree_info(conn
, &smb_fname
, &bsize
,
2210 if (df_ret
== (uint64_t)-1) {
2211 return map_nt_error_from_unix(errno
);
2213 block_size
= lp_block_size(snum
);
2214 if (bsize
< block_size
) {
2215 uint64_t factor
= block_size
/bsize
;
2220 if (bsize
> block_size
) {
2221 uint64_t factor
= bsize
/block_size
;
2226 sectors_per_unit
= bsize
/bytes_per_sector
;
2227 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2228 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
2229 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
2230 SBIG_UINT(pdata
,0,dsize
);
2231 SBIG_UINT(pdata
,8,dfree
);
2232 SIVAL(pdata
,16,sectors_per_unit
);
2233 SIVAL(pdata
,20,bytes_per_sector
);
2234 *fixed_portion
= 24;
2238 case SMB_FS_FULL_SIZE_INFORMATION
:
2240 uint64_t dfree
,dsize
,bsize
,block_size
,sectors_per_unit
;
2242 df_ret
= get_dfree_info(conn
, &smb_fname
, &bsize
,
2244 if (df_ret
== (uint64_t)-1) {
2245 return map_nt_error_from_unix(errno
);
2247 block_size
= lp_block_size(snum
);
2248 if (bsize
< block_size
) {
2249 uint64_t factor
= block_size
/bsize
;
2254 if (bsize
> block_size
) {
2255 uint64_t factor
= bsize
/block_size
;
2260 sectors_per_unit
= bsize
/bytes_per_sector
;
2261 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2262 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
2263 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
2264 SBIG_UINT(pdata
,0,dsize
); /* Total Allocation units. */
2265 SBIG_UINT(pdata
,8,dfree
); /* Caller available allocation units. */
2266 SBIG_UINT(pdata
,16,dfree
); /* Actual available allocation units. */
2267 SIVAL(pdata
,24,sectors_per_unit
); /* Sectors per allocation unit. */
2268 SIVAL(pdata
,28,bytes_per_sector
); /* Bytes per sector. */
2269 *fixed_portion
= 32;
2273 case SMB_QUERY_FS_DEVICE_INFO
:
2274 case SMB_FS_DEVICE_INFORMATION
:
2276 uint32_t characteristics
= FILE_DEVICE_IS_MOUNTED
;
2278 if (!CAN_WRITE(conn
)) {
2279 characteristics
|= FILE_READ_ONLY_DEVICE
;
2282 SIVAL(pdata
,0,FILE_DEVICE_DISK
); /* dev type */
2283 SIVAL(pdata
,4,characteristics
);
2288 #ifdef HAVE_SYS_QUOTAS
2289 case SMB_FS_QUOTA_INFORMATION
:
2291 * what we have to send --metze:
2293 * Unknown1: 24 NULL bytes
2294 * Soft Quota Threshold: 8 bytes seems like uint64_t or so
2295 * Hard Quota Limit: 8 bytes seems like uint64_t or so
2296 * Quota Flags: 2 byte :
2297 * Unknown3: 6 NULL bytes
2301 * details for Quota Flags:
2303 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2304 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2305 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2306 * 0x0001 Enable Quotas: enable quota for this fs
2310 /* we need to fake up a fsp here,
2311 * because its not send in this call
2313 files_struct tmpfsp
= {
2315 .fnum
= FNUM_FIELD_INVALID
,
2317 SMB_NTQUOTA_STRUCT quotas
= {};
2320 if (get_current_uid(conn
) != 0) {
2321 DEBUG(0,("get_user_quota: access_denied "
2322 "service [%s] user [%s]\n",
2323 lp_servicename(talloc_tos(), lp_sub
, SNUM(conn
)),
2324 conn
->session_info
->unix_info
->unix_name
));
2325 return NT_STATUS_ACCESS_DENIED
;
2328 status
= vfs_get_ntquota(&tmpfsp
, SMB_USER_FS_QUOTA_TYPE
,
2330 if (!NT_STATUS_IS_OK(status
)) {
2331 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), lp_sub
, SNUM(conn
))));
2337 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
2338 lp_servicename(talloc_tos(), lp_sub
, SNUM(conn
))));
2340 /* Unknown1 24 NULL bytes*/
2341 SBIG_UINT(pdata
,0,(uint64_t)0);
2342 SBIG_UINT(pdata
,8,(uint64_t)0);
2343 SBIG_UINT(pdata
,16,(uint64_t)0);
2345 /* Default Soft Quota 8 bytes */
2346 SBIG_UINT(pdata
,24,quotas
.softlim
);
2348 /* Default Hard Quota 8 bytes */
2349 SBIG_UINT(pdata
,32,quotas
.hardlim
);
2351 /* Quota flag 2 bytes */
2352 SSVAL(pdata
,40,quotas
.qflags
);
2354 /* Unknown3 6 NULL bytes */
2360 #endif /* HAVE_SYS_QUOTAS */
2361 case SMB_FS_OBJECTID_INFORMATION
:
2363 unsigned char objid
[16];
2364 struct smb_extended_info extended_info
;
2365 memcpy(pdata
,create_volume_objectid(conn
, objid
),16);
2366 samba_extended_info_version (&extended_info
);
2367 SIVAL(pdata
,16,extended_info
.samba_magic
);
2368 SIVAL(pdata
,20,extended_info
.samba_version
);
2369 SIVAL(pdata
,24,extended_info
.samba_subversion
);
2370 SBIG_UINT(pdata
,28,extended_info
.samba_gitcommitdate
);
2371 memcpy(pdata
+36,extended_info
.samba_version_string
,28);
2376 case SMB_FS_SECTOR_SIZE_INFORMATION
:
2378 uint32_t bps_logical
= lp_parm_ulong(
2380 "fs", "logical bytes per sector",
2382 uint32_t bps_aligned
= lp_parm_ulong(
2384 "fs", "aligned bytes per sector",
2386 uint32_t bps_performance
= lp_parm_ulong(
2388 "fs", "performance bytes per sector",
2390 uint32_t bps_effective
= lp_parm_ulong(
2392 "fs", "effective aligned bytes per sector",
2397 * These values match a physical Windows Server 2012
2398 * share backed by NTFS atop spinning rust.
2400 DEBUG(5, ("SMB_FS_SECTOR_SIZE_INFORMATION:"));
2401 /* logical_bytes_per_sector */
2402 SIVAL(pdata
, 0, bps_logical
);
2403 /* phys_bytes_per_sector_atomic */
2404 SIVAL(pdata
, 4, bps_aligned
);
2405 /* phys_bytes_per_sector_perf */
2406 SIVAL(pdata
, 8, bps_performance
);
2407 /* fs_effective_phys_bytes_per_sector_atomic */
2408 SIVAL(pdata
, 12, bps_effective
);
2410 SIVAL(pdata
, 16, SSINFO_FLAGS_ALIGNED_DEVICE
2411 | SSINFO_FLAGS_PARTITION_ALIGNED_ON_DEVICE
);
2412 /* byte_off_sector_align */
2413 SIVAL(pdata
, 20, 0);
2414 /* byte_off_partition_align */
2415 SIVAL(pdata
, 24, 0);
2416 *fixed_portion
= 28;
2421 #if defined(WITH_SMB1SERVER)
2423 * Query the version and capabilities of the CIFS UNIX extensions
2427 case SMB_QUERY_CIFS_UNIX_INFO
:
2429 bool large_write
= lp_min_receive_file_size() &&
2430 !smb1_srv_is_signing_active(xconn
);
2431 bool large_read
= !smb1_srv_is_signing_active(xconn
);
2432 int encrypt_caps
= 0;
2434 if (!lp_smb1_unix_extensions()) {
2435 return NT_STATUS_INVALID_LEVEL
;
2438 switch (conn
->encrypt_level
) {
2439 case SMB_SIGNING_OFF
:
2442 case SMB_SIGNING_DESIRED
:
2443 case SMB_SIGNING_IF_REQUIRED
:
2444 case SMB_SIGNING_DEFAULT
:
2445 encrypt_caps
= CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP
;
2447 case SMB_SIGNING_REQUIRED
:
2448 encrypt_caps
= CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP
|
2449 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP
;
2450 large_write
= false;
2456 SSVAL(pdata
,0,CIFS_UNIX_MAJOR_VERSION
);
2457 SSVAL(pdata
,2,CIFS_UNIX_MINOR_VERSION
);
2459 /* We have POSIX ACLs, pathname, encryption,
2460 * large read/write, and locking capability. */
2462 SBIG_UINT(pdata
,4,((uint64_t)(
2463 CIFS_UNIX_POSIX_ACLS_CAP
|
2464 CIFS_UNIX_POSIX_PATHNAMES_CAP
|
2465 CIFS_UNIX_FCNTL_LOCKS_CAP
|
2466 CIFS_UNIX_EXTATTR_CAP
|
2467 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP
|
2469 (large_read
? CIFS_UNIX_LARGE_READ_CAP
: 0) |
2471 CIFS_UNIX_LARGE_WRITE_CAP
: 0))));
2476 case SMB_QUERY_POSIX_FS_INFO
:
2477 case SMB2_FS_POSIX_INFORMATION_INTERNAL
:
2480 struct vfs_statvfs_struct svfs
;
2482 if (!fsinfo_unix_valid_level(conn
, fsp
, info_level
)) {
2483 return NT_STATUS_INVALID_LEVEL
;
2486 rc
= SMB_VFS_STATVFS(conn
, &smb_fname
, &svfs
);
2490 SIVAL(pdata
,0,svfs
.OptimalTransferSize
);
2491 SIVAL(pdata
,4,svfs
.BlockSize
);
2492 SBIG_UINT(pdata
,8,svfs
.TotalBlocks
);
2493 SBIG_UINT(pdata
,16,svfs
.BlocksAvail
);
2494 SBIG_UINT(pdata
,24,svfs
.UserBlocksAvail
);
2495 SBIG_UINT(pdata
,32,svfs
.TotalFileNodes
);
2496 SBIG_UINT(pdata
,40,svfs
.FreeFileNodes
);
2497 SBIG_UINT(pdata
,48,svfs
.FsIdentifier
);
2498 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO successful\n"));
2500 } else if (rc
== EOPNOTSUPP
) {
2501 return NT_STATUS_INVALID_LEVEL
;
2502 #endif /* EOPNOTSUPP */
2504 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(talloc_tos(), lp_sub
, SNUM(conn
))));
2505 return NT_STATUS_DOS(ERRSRV
, ERRerror
);
2510 case SMB_QUERY_POSIX_WHOAMI
:
2516 if (!lp_smb1_unix_extensions()) {
2517 return NT_STATUS_INVALID_LEVEL
;
2520 if (max_data_bytes
< 40) {
2521 return NT_STATUS_BUFFER_TOO_SMALL
;
2524 if (security_session_user_level(conn
->session_info
, NULL
) < SECURITY_USER
) {
2525 flags
|= SMB_WHOAMI_GUEST
;
2528 /* NOTE: 8 bytes for UID/GID, irrespective of native
2529 * platform size. This matches
2530 * SMB_QUERY_FILE_UNIX_BASIC and friends.
2532 data_len
= 4 /* flags */
2539 + 4 /* pad/reserved */
2540 + (conn
->session_info
->unix_token
->ngroups
* 8)
2542 + (conn
->session_info
->security_token
->num_sids
*
2546 SIVAL(pdata
, 0, flags
);
2547 SIVAL(pdata
, 4, SMB_WHOAMI_MASK
);
2549 (uint64_t)conn
->session_info
->unix_token
->uid
);
2550 SBIG_UINT(pdata
, 16,
2551 (uint64_t)conn
->session_info
->unix_token
->gid
);
2554 if (data_len
>= max_data_bytes
) {
2555 /* Potential overflow, skip the GIDs and SIDs. */
2557 SIVAL(pdata
, 24, 0); /* num_groups */
2558 SIVAL(pdata
, 28, 0); /* num_sids */
2559 SIVAL(pdata
, 32, 0); /* num_sid_bytes */
2560 SIVAL(pdata
, 36, 0); /* reserved */
2566 SIVAL(pdata
, 24, conn
->session_info
->unix_token
->ngroups
);
2567 SIVAL(pdata
, 28, conn
->session_info
->security_token
->num_sids
);
2569 /* We walk the SID list twice, but this call is fairly
2570 * infrequent, and I don't expect that it's performance
2571 * sensitive -- jpeach
2573 for (i
= 0, sid_bytes
= 0;
2574 i
< conn
->session_info
->security_token
->num_sids
; ++i
) {
2575 sid_bytes
+= ndr_size_dom_sid(
2576 &conn
->session_info
->security_token
->sids
[i
],
2580 /* SID list byte count */
2581 SIVAL(pdata
, 32, sid_bytes
);
2583 /* 4 bytes pad/reserved - must be zero */
2584 SIVAL(pdata
, 36, 0);
2588 for (i
= 0; i
< conn
->session_info
->unix_token
->ngroups
; ++i
) {
2589 SBIG_UINT(pdata
, data_len
,
2590 (uint64_t)conn
->session_info
->unix_token
->groups
[i
]);
2596 i
< conn
->session_info
->security_token
->num_sids
; ++i
) {
2597 int sid_len
= ndr_size_dom_sid(
2598 &conn
->session_info
->security_token
->sids
[i
],
2601 sid_linearize((uint8_t *)(pdata
+ data_len
),
2603 &conn
->session_info
->security_token
->sids
[i
]);
2604 data_len
+= sid_len
;
2610 case SMB_MAC_QUERY_FS_INFO
:
2612 * Thursby MAC extension... ONLY on NTFS filesystems
2613 * once we do streams then we don't need this
2615 if (strequal(lp_fstype(SNUM(conn
)),"NTFS")) {
2617 SIVAL(pdata
,84,0x100); /* Don't support mac... */
2623 return NT_STATUS_INVALID_LEVEL
;
2626 *ret_data_len
= data_len
;
2630 NTSTATUS
smb_set_fsquota(connection_struct
*conn
,
2631 struct smb_request
*req
,
2633 const DATA_BLOB
*qdata
)
2635 const struct loadparm_substitution
*lp_sub
=
2636 loadparm_s3_global_substitution();
2638 SMB_NTQUOTA_STRUCT quotas
;
2640 ZERO_STRUCT(quotas
);
2643 if ((get_current_uid(conn
) != 0) || !CAN_WRITE(conn
)) {
2644 DBG_NOTICE("access_denied service [%s] user [%s]\n",
2645 lp_servicename(talloc_tos(), lp_sub
, SNUM(conn
)),
2646 conn
->session_info
->unix_info
->unix_name
);
2647 return NT_STATUS_ACCESS_DENIED
;
2650 if (!check_fsp_ntquota_handle(conn
, req
,
2652 DBG_WARNING("no valid QUOTA HANDLE\n");
2653 return NT_STATUS_INVALID_HANDLE
;
2656 /* note: normally there're 48 bytes,
2657 * but we didn't use the last 6 bytes for now
2660 if (qdata
->length
< 42) {
2661 DBG_ERR("requires total_data(%zu) >= 42 bytes!\n",
2663 return NT_STATUS_INVALID_PARAMETER
;
2666 /* unknown_1 24 NULL bytes in pdata*/
2668 /* the soft quotas 8 bytes (uint64_t)*/
2669 quotas
.softlim
= BVAL(qdata
->data
,24);
2671 /* the hard quotas 8 bytes (uint64_t)*/
2672 quotas
.hardlim
= BVAL(qdata
->data
,32);
2674 /* quota_flags 2 bytes **/
2675 quotas
.qflags
= SVAL(qdata
->data
,40);
2677 /* unknown_2 6 NULL bytes follow*/
2679 /* now set the quotas */
2680 if (vfs_set_ntquota(fsp
, SMB_USER_FS_QUOTA_TYPE
, NULL
, "as
)!=0) {
2681 DBG_WARNING("vfs_set_ntquota() failed for service [%s]\n",
2682 lp_servicename(talloc_tos(), lp_sub
, SNUM(conn
)));
2683 status
= map_nt_error_from_unix(errno
);
2685 status
= NT_STATUS_OK
;
2690 NTSTATUS
smbd_do_setfsinfo(connection_struct
*conn
,
2691 struct smb_request
*req
,
2692 TALLOC_CTX
*mem_ctx
,
2693 uint16_t info_level
,
2695 const DATA_BLOB
*pdata
)
2697 switch (info_level
) {
2698 case SMB_FS_QUOTA_INFORMATION
:
2700 return smb_set_fsquota(conn
,
2709 return NT_STATUS_INVALID_LEVEL
;
2712 /****************************************************************************
2713 Store the FILE_UNIX_BASIC info.
2714 ****************************************************************************/
2716 char *store_file_unix_basic(connection_struct
*conn
,
2719 const SMB_STRUCT_STAT
*psbuf
)
2723 DBG_DEBUG("SMB_QUERY_FILE_UNIX_BASIC\n");
2724 DBG_NOTICE("st_mode=%o\n", (int)psbuf
->st_ex_mode
);
2726 SOFF_T(pdata
,0,get_file_size_stat(psbuf
)); /* File size 64 Bit */
2729 SOFF_T(pdata
,0,SMB_VFS_GET_ALLOC_SIZE(conn
,fsp
,psbuf
)); /* Number of bytes used on disk - 64 Bit */
2732 put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER
, pdata
, &psbuf
->st_ex_ctime
); /* Change Time 64 Bit */
2733 put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER
,pdata
+8, &psbuf
->st_ex_atime
); /* Last access time 64 Bit */
2734 put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER
, pdata
+16, &psbuf
->st_ex_mtime
); /* Last modification time 64 Bit */
2737 SIVAL(pdata
,0,psbuf
->st_ex_uid
); /* user id for the owner */
2741 SIVAL(pdata
,0,psbuf
->st_ex_gid
); /* group id of owner */
2745 SIVAL(pdata
, 0, unix_filetype_to_wire(psbuf
->st_ex_mode
));
2748 if (S_ISBLK(psbuf
->st_ex_mode
) || S_ISCHR(psbuf
->st_ex_mode
)) {
2749 devno
= psbuf
->st_ex_rdev
;
2751 devno
= psbuf
->st_ex_dev
;
2754 SIVAL(pdata
,0,unix_dev_major(devno
)); /* Major device number if type is device */
2758 SIVAL(pdata
,0,unix_dev_minor(devno
)); /* Minor device number if type is device */
2762 SINO_T_VAL(pdata
, 0, psbuf
->st_ex_ino
); /* inode number */
2765 SIVAL(pdata
,0, unix_perms_to_wire(psbuf
->st_ex_mode
)); /* Standard UNIX file permissions */
2769 SIVAL(pdata
,0,psbuf
->st_ex_nlink
); /* number of hard links */
2776 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
2777 * the chflags(2) (or equivalent) flags.
2779 * XXX: this really should be behind the VFS interface. To do this, we would
2780 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
2781 * Each VFS module could then implement its own mapping as appropriate for the
2782 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
2784 static const struct {unsigned stat_fflag
; unsigned smb_fflag
;}
2788 { UF_NODUMP
, EXT_DO_NOT_BACKUP
},
2792 { UF_IMMUTABLE
, EXT_IMMUTABLE
},
2796 { UF_APPEND
, EXT_OPEN_APPEND_ONLY
},
2800 { UF_HIDDEN
, EXT_HIDDEN
},
2803 /* Do not remove. We need to guarantee that this array has at least one
2804 * entry to build on HP-UX.
2810 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT
*psbuf
,
2811 uint32_t *smb_fflags
, uint32_t *smb_fmask
)
2815 for (i
= 0; i
< ARRAY_SIZE(info2_flags_map
); ++i
) {
2816 *smb_fmask
|= info2_flags_map
[i
].smb_fflag
;
2817 if (psbuf
->st_ex_flags
& info2_flags_map
[i
].stat_fflag
) {
2818 *smb_fflags
|= info2_flags_map
[i
].smb_fflag
;
2823 bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT
*psbuf
,
2824 const uint32_t smb_fflags
,
2825 const uint32_t smb_fmask
,
2828 uint32_t max_fmask
= 0;
2831 *stat_fflags
= psbuf
->st_ex_flags
;
2833 /* For each flags requested in smb_fmask, check the state of the
2834 * corresponding flag in smb_fflags and set or clear the matching
2838 for (i
= 0; i
< ARRAY_SIZE(info2_flags_map
); ++i
) {
2839 max_fmask
|= info2_flags_map
[i
].smb_fflag
;
2840 if (smb_fmask
& info2_flags_map
[i
].smb_fflag
) {
2841 if (smb_fflags
& info2_flags_map
[i
].smb_fflag
) {
2842 *stat_fflags
|= info2_flags_map
[i
].stat_fflag
;
2844 *stat_fflags
&= ~info2_flags_map
[i
].stat_fflag
;
2849 /* If smb_fmask is asking to set any bits that are not supported by
2850 * our flag mappings, we should fail.
2852 if ((smb_fmask
& max_fmask
) != smb_fmask
) {
2860 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
2861 * of file flags and birth (create) time.
2863 char *store_file_unix_basic_info2(connection_struct
*conn
,
2866 const SMB_STRUCT_STAT
*psbuf
)
2868 uint32_t file_flags
= 0;
2869 uint32_t flags_mask
= 0;
2871 pdata
= store_file_unix_basic(conn
, pdata
, fsp
, psbuf
);
2873 /* Create (birth) time 64 bit */
2874 put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER
,pdata
, &psbuf
->st_ex_btime
);
2877 map_info2_flags_from_sbuf(psbuf
, &file_flags
, &flags_mask
);
2878 SIVAL(pdata
, 0, file_flags
); /* flags */
2879 SIVAL(pdata
, 4, flags_mask
); /* mask */
2885 static NTSTATUS
marshall_stream_info(unsigned int num_streams
,
2886 const struct stream_struct
*streams
,
2888 unsigned int max_data_bytes
,
2889 unsigned int *data_size
)
2892 unsigned int ofs
= 0;
2894 if (max_data_bytes
< 32) {
2895 return NT_STATUS_INFO_LENGTH_MISMATCH
;
2898 for (i
= 0; i
< num_streams
; i
++) {
2899 unsigned int next_offset
;
2901 smb_ucs2_t
*namebuf
;
2903 if (!push_ucs2_talloc(talloc_tos(), &namebuf
,
2904 streams
[i
].name
, &namelen
) ||
2907 return NT_STATUS_INVALID_PARAMETER
;
2911 * name_buf is now null-terminated, we need to marshall as not
2918 * We cannot overflow ...
2920 if ((ofs
+ 24 + namelen
) > max_data_bytes
) {
2921 DEBUG(10, ("refusing to overflow reply at stream %u\n",
2923 TALLOC_FREE(namebuf
);
2924 return STATUS_BUFFER_OVERFLOW
;
2927 SIVAL(data
, ofs
+4, namelen
);
2928 SOFF_T(data
, ofs
+8, streams
[i
].size
);
2929 SOFF_T(data
, ofs
+16, streams
[i
].alloc_size
);
2930 memcpy(data
+ofs
+24, namebuf
, namelen
);
2931 TALLOC_FREE(namebuf
);
2933 next_offset
= ofs
+ 24 + namelen
;
2935 if (i
== num_streams
-1) {
2936 SIVAL(data
, ofs
, 0);
2939 unsigned int align
= ndr_align_size(next_offset
, 8);
2941 if ((next_offset
+ align
) > max_data_bytes
) {
2942 DEBUG(10, ("refusing to overflow align "
2943 "reply at stream %u\n",
2945 TALLOC_FREE(namebuf
);
2946 return STATUS_BUFFER_OVERFLOW
;
2949 memset(data
+next_offset
, 0, align
);
2950 next_offset
+= align
;
2952 SIVAL(data
, ofs
, next_offset
- ofs
);
2959 DEBUG(10, ("max_data: %u, data_size: %u\n", max_data_bytes
, ofs
));
2963 return NT_STATUS_OK
;
2966 NTSTATUS
smbd_do_qfilepathinfo(connection_struct
*conn
,
2967 TALLOC_CTX
*mem_ctx
,
2968 struct smb_request
*req
,
2969 uint16_t info_level
,
2971 struct smb_filename
*smb_fname
,
2972 bool delete_pending
,
2973 struct timespec write_time_ts
,
2974 struct ea_list
*ea_list
,
2976 unsigned int max_data_bytes
,
2977 size_t *fixed_portion
,
2979 unsigned int *pdata_size
)
2981 char *pdata
= *ppdata
;
2982 char *dstart
, *dend
;
2983 unsigned int data_size
;
2984 struct timespec create_time_ts
, mtime_ts
, atime_ts
, ctime_ts
;
2985 SMB_STRUCT_STAT
*psbuf
= NULL
;
2986 SMB_STRUCT_STAT
*base_sp
= NULL
;
2993 uint64_t file_size
= 0;
2995 uint64_t allocation_size
= 0;
2996 uint64_t file_id
= 0;
2997 uint32_t access_mask
= 0;
3000 if (INFO_LEVEL_IS_UNIX(info_level
)) {
3003 if (lp_smb1_unix_extensions() && req
->posix_pathnames
) {
3004 DBG_DEBUG("SMB1 unix extensions activated\n");
3008 if (conn_using_smb2(conn
->sconn
) &&
3009 fsp
->fsp_flags
.posix_open
)
3011 DBG_DEBUG("SMB2 posix open\n");
3016 return NT_STATUS_INVALID_LEVEL
;
3020 DBG_INFO("%s (%s) level=%d max_data=%u\n",
3021 smb_fname_str_dbg(smb_fname
),
3023 info_level
, max_data_bytes
);
3026 * In case of querying a symlink in POSIX context,
3027 * fsp will be NULL. fdos_mode() deals with it.
3030 smb_fname
= fsp
->fsp_name
;
3032 mode
= fdos_mode(fsp
);
3033 psbuf
= &smb_fname
->st
;
3036 base_sp
= fsp
->base_fsp
?
3037 &fsp
->base_fsp
->fsp_name
->st
:
3040 base_sp
= &smb_fname
->st
;
3043 nlink
= psbuf
->st_ex_nlink
;
3045 if (nlink
&& (mode
&FILE_ATTRIBUTE_DIRECTORY
)) {
3049 if ((nlink
> 0) && delete_pending
) {
3053 if (max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
< max_data_bytes
) {
3054 return NT_STATUS_INVALID_PARAMETER
;
3057 data_size
= max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
;
3058 *ppdata
= (char *)SMB_REALLOC(*ppdata
, data_size
);
3059 if (*ppdata
== NULL
) {
3060 return NT_STATUS_NO_MEMORY
;
3064 dend
= dstart
+ data_size
- 1;
3066 if (!is_omit_timespec(&write_time_ts
) &&
3067 !INFO_LEVEL_IS_UNIX(info_level
))
3069 update_stat_ex_mtime(psbuf
, write_time_ts
);
3072 create_time_ts
= get_create_timespec(conn
, fsp
, smb_fname
);
3073 mtime_ts
= psbuf
->st_ex_mtime
;
3074 atime_ts
= psbuf
->st_ex_atime
;
3075 ctime_ts
= get_change_timespec(conn
, fsp
, smb_fname
);
3077 if (lp_dos_filetime_resolution(SNUM(conn
))) {
3078 dos_filetime_timespec(&create_time_ts
);
3079 dos_filetime_timespec(&mtime_ts
);
3080 dos_filetime_timespec(&atime_ts
);
3081 dos_filetime_timespec(&ctime_ts
);
3084 p
= strrchr_m(smb_fname
->base_name
,'/');
3086 base_name
= smb_fname
->base_name
;
3091 /* NT expects the name to be in an exact form of the *full*
3092 filename. See the trans2 torture test */
3093 if (ISDOT(base_name
)) {
3094 dos_fname
= talloc_strdup(mem_ctx
, "\\");
3096 return NT_STATUS_NO_MEMORY
;
3099 dos_fname
= talloc_asprintf(mem_ctx
,
3101 smb_fname
->base_name
);
3103 return NT_STATUS_NO_MEMORY
;
3105 if (is_named_stream(smb_fname
)) {
3106 dos_fname
= talloc_asprintf(dos_fname
, "%s",
3107 smb_fname
->stream_name
);
3109 return NT_STATUS_NO_MEMORY
;
3113 string_replace(dos_fname
, '/', '\\');
3116 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
, fsp
, psbuf
);
3118 if (fsp
== NULL
|| !fsp
->fsp_flags
.is_fsa
) {
3119 /* Do we have this path open ? */
3120 struct file_id fileid
= vfs_file_id_from_sbuf(conn
, psbuf
);
3121 files_struct
*fsp1
= file_find_di_first(
3122 conn
->sconn
, fileid
, true);
3123 if (fsp1
&& fsp1
->initial_allocation_size
) {
3124 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
, fsp1
, psbuf
);
3128 if (!(mode
& FILE_ATTRIBUTE_DIRECTORY
)) {
3129 file_size
= get_file_size_stat(psbuf
);
3133 pos
= fh_get_position_information(fsp
->fh
);
3137 access_mask
= fsp
->access_mask
;
3139 /* GENERIC_EXECUTE mapping from Windows */
3140 access_mask
= 0x12019F;
3143 /* This should be an index number - looks like
3146 I think this causes us to fail the IFSKIT
3147 BasicFileInformationTest. -tpot */
3148 file_id
= SMB_VFS_FS_FILE_ID(conn
, base_sp
);
3152 switch (info_level
) {
3153 case SMB_INFO_STANDARD
:
3154 DBG_DEBUG("SMB_INFO_STANDARD\n");
3156 srv_put_dos_date2_ts(pdata
,
3159 srv_put_dos_date2_ts(pdata
,
3162 srv_put_dos_date2_ts(pdata
,
3164 mtime_ts
); /* write time */
3165 SIVAL(pdata
,l1_cbFile
,(uint32_t)file_size
);
3166 SIVAL(pdata
,l1_cbFileAlloc
,(uint32_t)allocation_size
);
3167 SSVAL(pdata
,l1_attrFile
,mode
);
3170 case SMB_INFO_QUERY_EA_SIZE
:
3172 unsigned int ea_size
=
3173 estimate_ea_size(smb_fname
->fsp
);
3174 DBG_DEBUG("SMB_INFO_QUERY_EA_SIZE\n");
3176 srv_put_dos_date2_ts(pdata
, 0, create_time_ts
);
3177 srv_put_dos_date2_ts(pdata
, 4, atime_ts
);
3178 srv_put_dos_date2_ts(pdata
,
3180 mtime_ts
); /* write time */
3181 SIVAL(pdata
,12,(uint32_t)file_size
);
3182 SIVAL(pdata
,16,(uint32_t)allocation_size
);
3183 SSVAL(pdata
,20,mode
);
3184 SIVAL(pdata
,22,ea_size
);
3188 case SMB_INFO_IS_NAME_VALID
:
3189 DBG_DEBUG("SMB_INFO_IS_NAME_VALID\n");
3191 /* os/2 needs this ? really ?*/
3192 return NT_STATUS_DOS(ERRDOS
, ERRbadfunc
);
3194 /* This is only reached for qpathinfo */
3198 case SMB_INFO_QUERY_EAS_FROM_LIST
:
3200 size_t total_ea_len
= 0;
3201 struct ea_list
*ea_file_list
= NULL
;
3202 DBG_DEBUG("SMB_INFO_QUERY_EAS_FROM_LIST\n");
3205 get_ea_list_from_fsp(mem_ctx
,
3207 &total_ea_len
, &ea_file_list
);
3208 if (!NT_STATUS_IS_OK(status
)) {
3212 ea_list
= ea_list_union(ea_list
, ea_file_list
, &total_ea_len
);
3214 if (!ea_list
|| (total_ea_len
> data_size
)) {
3216 SIVAL(pdata
,0,4); /* EA List Length must be set to 4 if no EA's. */
3220 data_size
= fill_ea_buffer(mem_ctx
, pdata
, data_size
, conn
, ea_list
);
3224 case SMB_INFO_QUERY_ALL_EAS
:
3226 /* We have data_size bytes to put EA's into. */
3227 size_t total_ea_len
= 0;
3228 DBG_DEBUG(" SMB_INFO_QUERY_ALL_EAS\n");
3230 status
= get_ea_list_from_fsp(mem_ctx
,
3232 &total_ea_len
, &ea_list
);
3233 if (!NT_STATUS_IS_OK(status
)) {
3237 if (!ea_list
|| (total_ea_len
> data_size
)) {
3239 SIVAL(pdata
,0,4); /* EA List Length must be set to 4 if no EA's. */
3243 data_size
= fill_ea_buffer(mem_ctx
, pdata
, data_size
, conn
, ea_list
);
3247 case SMB2_FILE_FULL_EA_INFORMATION
:
3249 /* We have data_size bytes to put EA's into. */
3250 size_t total_ea_len
= 0;
3251 struct ea_list
*ea_file_list
= NULL
;
3253 DBG_DEBUG("SMB2_INFO_QUERY_ALL_EAS\n");
3255 /*TODO: add filtering and index handling */
3258 get_ea_list_from_fsp(mem_ctx
,
3260 &total_ea_len
, &ea_file_list
);
3261 if (!NT_STATUS_IS_OK(status
)) {
3264 if (!ea_file_list
) {
3265 return NT_STATUS_NO_EAS_ON_FILE
;
3268 status
= fill_ea_chained_buffer(mem_ctx
,
3272 conn
, ea_file_list
);
3273 if (!NT_STATUS_IS_OK(status
)) {
3279 case SMB_FILE_BASIC_INFORMATION
:
3280 case SMB_QUERY_FILE_BASIC_INFO
:
3282 if (info_level
== SMB_QUERY_FILE_BASIC_INFO
) {
3283 DBG_DEBUG("SMB_QUERY_FILE_BASIC_INFO\n");
3284 data_size
= 36; /* w95 returns 40 bytes not 36 - why ?. */
3286 DBG_DEBUG("SMB_FILE_BASIC_INFORMATION\n");
3290 put_long_date_full_timespec(conn
->ts_res
,pdata
,&create_time_ts
);
3291 put_long_date_full_timespec(conn
->ts_res
,pdata
+8,&atime_ts
);
3292 put_long_date_full_timespec(conn
->ts_res
,pdata
+16,&mtime_ts
); /* write time */
3293 put_long_date_full_timespec(conn
->ts_res
,pdata
+24,&ctime_ts
); /* change time */
3294 SIVAL(pdata
,32,mode
);
3296 DBG_INFO("SMB_QFBI - create: %s access: %s "
3297 "write: %s change: %s mode: %x\n",
3298 ctime(&create_time_ts
.tv_sec
),
3299 ctime(&atime_ts
.tv_sec
),
3300 ctime(&mtime_ts
.tv_sec
),
3301 ctime(&ctime_ts
.tv_sec
),
3303 *fixed_portion
= data_size
;
3306 case SMB_FILE_STANDARD_INFORMATION
:
3307 case SMB_QUERY_FILE_STANDARD_INFO
:
3309 DBG_DEBUG("SMB_FILE_STANDARD_INFORMATION\n");
3311 SOFF_T(pdata
,0,allocation_size
);
3312 SOFF_T(pdata
,8,file_size
);
3313 SIVAL(pdata
,16,nlink
);
3314 SCVAL(pdata
,20,delete_pending
?1:0);
3315 SCVAL(pdata
,21,(mode
&FILE_ATTRIBUTE_DIRECTORY
)?1:0);
3316 SSVAL(pdata
,22,0); /* Padding. */
3317 *fixed_portion
= 24;
3320 case SMB_FILE_EA_INFORMATION
:
3321 case SMB_QUERY_FILE_EA_INFO
:
3323 unsigned int ea_size
=
3324 estimate_ea_size(smb_fname
->fsp
);
3325 DBG_DEBUG("SMB_FILE_EA_INFORMATION\n");
3328 SIVAL(pdata
,0,ea_size
);
3332 /* Get the 8.3 name - used if NT SMB was negotiated. */
3333 case SMB_QUERY_FILE_ALT_NAME_INFO
:
3334 case SMB_FILE_ALTERNATE_NAME_INFORMATION
:
3336 char mangled_name
[13];
3337 DBG_DEBUG("SMB_FILE_ALTERNATE_NAME_INFORMATION\n");
3338 if (!name_to_8_3(base_name
,mangled_name
,
3339 True
,conn
->params
)) {
3340 return NT_STATUS_NO_MEMORY
;
3342 status
= srvstr_push(dstart
, flags2
,
3343 pdata
+4, mangled_name
,
3344 PTR_DIFF(dend
, pdata
+4),
3346 if (!NT_STATUS_IS_OK(status
)) {
3349 data_size
= 4 + len
;
3355 case SMB_QUERY_FILE_NAME_INFO
:
3358 this must be *exactly* right for ACLs on mapped drives to work
3360 status
= srvstr_push(dstart
, flags2
,
3362 PTR_DIFF(dend
, pdata
+4),
3364 if (!NT_STATUS_IS_OK(status
)) {
3367 DBG_DEBUG("SMB_QUERY_FILE_NAME_INFO\n");
3368 data_size
= 4 + len
;
3373 case SMB_FILE_NORMALIZED_NAME_INFORMATION
:
3375 char *nfname
= NULL
;
3378 !conn_using_smb2(fsp
->conn
->sconn
)) {
3379 return NT_STATUS_INVALID_LEVEL
;
3382 nfname
= talloc_strdup(mem_ctx
, smb_fname
->base_name
);
3383 if (nfname
== NULL
) {
3384 return NT_STATUS_NO_MEMORY
;
3387 if (ISDOT(nfname
)) {
3390 string_replace(nfname
, '/', '\\');
3392 if (fsp_is_alternate_stream(fsp
)) {
3393 const char *s
= smb_fname
->stream_name
;
3394 const char *e
= NULL
;
3397 SMB_ASSERT(s
[0] != '\0');
3400 * smb_fname->stream_name is in form
3401 * of ':StrEam:$DATA', but we should only
3402 * append ':StrEam' here.
3405 e
= strchr(&s
[1], ':');
3411 nfname
= talloc_strndup_append(nfname
, s
, n
);
3412 if (nfname
== NULL
) {
3413 return NT_STATUS_NO_MEMORY
;
3417 status
= srvstr_push(dstart
, flags2
,
3419 PTR_DIFF(dend
, pdata
+4),
3421 if (!NT_STATUS_IS_OK(status
)) {
3424 DBG_DEBUG("SMB_FILE_NORMALIZED_NAME_INFORMATION\n");
3425 data_size
= 4 + len
;
3431 case SMB_FILE_ALLOCATION_INFORMATION
:
3432 case SMB_QUERY_FILE_ALLOCATION_INFO
:
3433 DBG_DEBUG("SMB_FILE_ALLOCATION_INFORMATION\n");
3435 SOFF_T(pdata
,0,allocation_size
);
3438 case SMB_FILE_END_OF_FILE_INFORMATION
:
3439 case SMB_QUERY_FILE_END_OF_FILEINFO
:
3440 DBG_DEBUG("SMB_FILE_END_OF_FILE_INFORMATION\n");
3442 SOFF_T(pdata
,0,file_size
);
3445 case SMB_QUERY_FILE_ALL_INFO
:
3446 case SMB_FILE_ALL_INFORMATION
:
3448 unsigned int ea_size
=
3449 estimate_ea_size(smb_fname
->fsp
);
3450 DBG_DEBUG("SMB_FILE_ALL_INFORMATION\n");
3451 put_long_date_full_timespec(conn
->ts_res
,pdata
,&create_time_ts
);
3452 put_long_date_full_timespec(conn
->ts_res
,pdata
+8,&atime_ts
);
3453 put_long_date_full_timespec(conn
->ts_res
,pdata
+16,&mtime_ts
); /* write time */
3454 put_long_date_full_timespec(conn
->ts_res
,pdata
+24,&ctime_ts
); /* change time */
3455 SIVAL(pdata
,32,mode
);
3456 SIVAL(pdata
,36,0); /* padding. */
3458 SOFF_T(pdata
,0,allocation_size
);
3459 SOFF_T(pdata
,8,file_size
);
3460 SIVAL(pdata
,16,nlink
);
3461 SCVAL(pdata
,20,delete_pending
);
3462 SCVAL(pdata
,21,(mode
&FILE_ATTRIBUTE_DIRECTORY
)?1:0);
3465 SIVAL(pdata
,0,ea_size
);
3466 pdata
+= 4; /* EA info */
3467 status
= srvstr_push(dstart
, flags2
,
3469 PTR_DIFF(dend
, pdata
+4),
3471 if (!NT_STATUS_IS_OK(status
)) {
3476 data_size
= PTR_DIFF(pdata
,(*ppdata
));
3477 *fixed_portion
= 10;
3481 case SMB2_FILE_ALL_INFORMATION
:
3483 unsigned int ea_size
=
3484 estimate_ea_size(smb_fname
->fsp
);
3485 DBG_DEBUG("SMB2_FILE_ALL_INFORMATION\n");
3486 put_long_date_full_timespec(conn
->ts_res
,pdata
+0x00,&create_time_ts
);
3487 put_long_date_full_timespec(conn
->ts_res
,pdata
+0x08,&atime_ts
);
3488 put_long_date_full_timespec(conn
->ts_res
,pdata
+0x10,&mtime_ts
); /* write time */
3489 put_long_date_full_timespec(conn
->ts_res
,pdata
+0x18,&ctime_ts
); /* change time */
3490 SIVAL(pdata
, 0x20, mode
);
3491 SIVAL(pdata
, 0x24, 0); /* padding. */
3492 SBVAL(pdata
, 0x28, allocation_size
);
3493 SBVAL(pdata
, 0x30, file_size
);
3494 SIVAL(pdata
, 0x38, nlink
);
3495 SCVAL(pdata
, 0x3C, delete_pending
);
3496 SCVAL(pdata
, 0x3D, (mode
&FILE_ATTRIBUTE_DIRECTORY
)?1:0);
3497 SSVAL(pdata
, 0x3E, 0); /* padding */
3498 SBVAL(pdata
, 0x40, file_id
);
3499 SIVAL(pdata
, 0x48, ea_size
);
3500 SIVAL(pdata
, 0x4C, access_mask
);
3501 SBVAL(pdata
, 0x50, pos
);
3502 SIVAL(pdata
, 0x58, mode
); /*TODO: mode != mode fix this!!! */
3503 SIVAL(pdata
, 0x5C, 0); /* No alignment needed. */
3507 status
= srvstr_push(dstart
, flags2
,
3509 PTR_DIFF(dend
, pdata
+4),
3511 if (!NT_STATUS_IS_OK(status
)) {
3516 data_size
= PTR_DIFF(pdata
,(*ppdata
));
3517 *fixed_portion
= 104;
3520 case SMB_FILE_INTERNAL_INFORMATION
:
3522 DBG_DEBUG("SMB_FILE_INTERNAL_INFORMATION\n");
3523 SBVAL(pdata
, 0, file_id
);
3528 case SMB_FILE_ACCESS_INFORMATION
:
3529 DBG_DEBUG("SMB_FILE_ACCESS_INFORMATION\n");
3530 SIVAL(pdata
, 0, access_mask
);
3535 case SMB_FILE_NAME_INFORMATION
:
3536 /* Pathname with leading '\'. */
3539 byte_len
= dos_PutUniCode(pdata
+4,dos_fname
,(size_t)max_data_bytes
,False
);
3540 DBG_DEBUG("SMB_FILE_NAME_INFORMATION\n");
3541 SIVAL(pdata
,0,byte_len
);
3542 data_size
= 4 + byte_len
;
3546 case SMB_FILE_DISPOSITION_INFORMATION
:
3547 DBG_DEBUG("SMB_FILE_DISPOSITION_INFORMATION\n");
3549 SCVAL(pdata
,0,delete_pending
);
3553 case SMB_FILE_POSITION_INFORMATION
:
3554 DBG_DEBUG("SMB_FILE_POSITION_INFORMATION\n");
3556 SOFF_T(pdata
,0,pos
);
3560 case SMB_FILE_MODE_INFORMATION
:
3561 DBG_DEBUG("SMB_FILE_MODE_INFORMATION\n");
3562 SIVAL(pdata
,0,mode
);
3567 case SMB_FILE_ALIGNMENT_INFORMATION
:
3568 DBG_DEBUG("SMB_FILE_ALIGNMENT_INFORMATION\n");
3569 SIVAL(pdata
,0,0); /* No alignment needed. */
3575 * NT4 server just returns "invalid query" to this - if we try
3576 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
3579 /* The first statement above is false - verified using Thursby
3580 * client against NT4 -- gcolley.
3582 case SMB_QUERY_FILE_STREAM_INFO
:
3583 case SMB_FILE_STREAM_INFORMATION
: {
3584 unsigned int num_streams
= 0;
3585 struct stream_struct
*streams
= NULL
;
3587 DBG_DEBUG("SMB_FILE_STREAM_INFORMATION\n");
3589 if (is_ntfs_stream_smb_fname(smb_fname
)) {
3590 return NT_STATUS_INVALID_PARAMETER
;
3593 status
= vfs_fstreaminfo(fsp
,
3598 if (!NT_STATUS_IS_OK(status
)) {
3599 DBG_DEBUG("could not get stream info: %s\n",
3604 status
= marshall_stream_info(num_streams
, streams
,
3605 pdata
, max_data_bytes
,
3608 if (!NT_STATUS_IS_OK(status
)) {
3609 DBG_DEBUG("marshall_stream_info failed: %s\n",
3611 TALLOC_FREE(streams
);
3615 TALLOC_FREE(streams
);
3617 *fixed_portion
= 32;
3621 case SMB_QUERY_COMPRESSION_INFO
:
3622 case SMB_FILE_COMPRESSION_INFORMATION
:
3623 DBG_DEBUG("SMB_FILE_COMPRESSION_INFORMATION\n");
3624 SOFF_T(pdata
,0,file_size
);
3625 SIVAL(pdata
,8,0); /* ??? */
3626 SIVAL(pdata
,12,0); /* ??? */
3628 *fixed_portion
= 16;
3631 case SMB_FILE_NETWORK_OPEN_INFORMATION
:
3632 DBG_DEBUG("SMB_FILE_NETWORK_OPEN_INFORMATION\n");
3633 put_long_date_full_timespec(conn
->ts_res
,pdata
,&create_time_ts
);
3634 put_long_date_full_timespec(conn
->ts_res
,pdata
+8,&atime_ts
);
3635 put_long_date_full_timespec(conn
->ts_res
,pdata
+16,&mtime_ts
); /* write time */
3636 put_long_date_full_timespec(conn
->ts_res
,pdata
+24,&ctime_ts
); /* change time */
3637 SOFF_T(pdata
,32,allocation_size
);
3638 SOFF_T(pdata
,40,file_size
);
3639 SIVAL(pdata
,48,mode
);
3640 SIVAL(pdata
,52,0); /* ??? */
3642 *fixed_portion
= 56;
3645 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION
: {
3648 DBG_DEBUG("SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n");
3650 (void)fsctl_get_reparse_tag(fsp
, &tag
);
3652 DBG_DEBUG("tag=%"PRIu32
"\n", tag
);
3654 SIVAL(pdata
, 0, mode
);
3655 SIVAL(pdata
, 4, tag
);
3661 * SMB2 UNIX Extensions.
3663 case SMB2_FILE_POSIX_INFORMATION_INTERNAL
:
3665 struct smb3_file_posix_information info
= {};
3666 uint8_t buf
[sizeof(info
)];
3667 struct ndr_push ndr
= {
3669 .alloc_size
= sizeof(buf
),
3670 .fixed_buf_size
= true,
3672 enum ndr_err_code ndr_err
;
3674 if (!conn_using_smb2(conn
->sconn
)) {
3675 return NT_STATUS_INVALID_LEVEL
;
3678 return NT_STATUS_INVALID_HANDLE
;
3680 if (!fsp
->fsp_flags
.posix_open
) {
3681 return NT_STATUS_INVALID_LEVEL
;
3684 smb3_file_posix_information_init(
3685 conn
, &smb_fname
->st
, 0, mode
, &info
);
3687 ndr_err
= ndr_push_smb3_file_posix_information(
3688 &ndr
, NDR_SCALARS
|NDR_BUFFERS
, &info
);
3689 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
3690 return NT_STATUS_INSUFFICIENT_RESOURCES
;
3693 memcpy(pdata
, buf
, ndr
.offset
);
3694 data_size
= ndr
.offset
;
3699 return NT_STATUS_INVALID_LEVEL
;
3702 *pdata_size
= data_size
;
3703 return NT_STATUS_OK
;
3706 /****************************************************************************
3707 Set a hard link (called by UNIX extensions and by NT rename with HARD link
3709 ****************************************************************************/
3711 NTSTATUS
hardlink_internals(TALLOC_CTX
*ctx
,
3712 connection_struct
*conn
,
3713 struct smb_request
*req
,
3714 bool overwrite_if_exists
,
3715 const struct smb_filename
*smb_fname_old
,
3716 struct smb_filename
*smb_fname_new
)
3718 NTSTATUS status
= NT_STATUS_OK
;
3721 struct smb_filename
*parent_fname_old
= NULL
;
3722 struct smb_filename
*base_name_old
= NULL
;
3723 struct smb_filename
*parent_fname_new
= NULL
;
3724 struct smb_filename
*base_name_new
= NULL
;
3726 /* source must already exist. */
3727 if (!VALID_STAT(smb_fname_old
->st
)) {
3728 status
= NT_STATUS_OBJECT_NAME_NOT_FOUND
;
3732 /* No links from a directory. */
3733 if (S_ISDIR(smb_fname_old
->st
.st_ex_mode
)) {
3734 status
= NT_STATUS_FILE_IS_A_DIRECTORY
;
3738 /* Setting a hardlink to/from a stream isn't currently supported. */
3739 ok
= is_ntfs_stream_smb_fname(smb_fname_old
);
3741 DBG_DEBUG("Old name has streams\n");
3742 status
= NT_STATUS_INVALID_PARAMETER
;
3745 ok
= is_ntfs_stream_smb_fname(smb_fname_new
);
3747 DBG_DEBUG("New name has streams\n");
3748 status
= NT_STATUS_INVALID_PARAMETER
;
3752 if (smb_fname_old
->twrp
!= 0) {
3753 status
= NT_STATUS_NOT_SAME_DEVICE
;
3757 status
= parent_pathref(talloc_tos(),
3762 if (!NT_STATUS_IS_OK(status
)) {
3766 status
= parent_pathref(talloc_tos(),
3771 if (!NT_STATUS_IS_OK(status
)) {
3775 if (VALID_STAT(smb_fname_new
->st
)) {
3776 if (overwrite_if_exists
) {
3777 if (S_ISDIR(smb_fname_new
->st
.st_ex_mode
)) {
3778 status
= NT_STATUS_FILE_IS_A_DIRECTORY
;
3781 status
= unlink_internals(conn
,
3783 FILE_ATTRIBUTE_NORMAL
,
3784 NULL
, /* new_dirfsp */
3786 if (!NT_STATUS_IS_OK(status
)) {
3790 /* Disallow if newname already exists. */
3791 status
= NT_STATUS_OBJECT_NAME_COLLISION
;
3796 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
3797 smb_fname_old
->base_name
, smb_fname_new
->base_name
));
3799 ret
= SMB_VFS_LINKAT(conn
,
3800 parent_fname_old
->fsp
,
3802 parent_fname_new
->fsp
,
3807 status
= map_nt_error_from_unix(errno
);
3808 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
3809 nt_errstr(status
), smb_fname_old
->base_name
,
3810 smb_fname_new
->base_name
));
3815 NOTIFY_ACTION_ADDED
|
3816 NOTIFY_ACTION_DIRLEASE_BREAK
,
3817 FILE_NOTIFY_CHANGE_FILE_NAME
,
3819 fsp_get_smb2_lease(smb_fname_old
->fsp
));
3823 TALLOC_FREE(parent_fname_old
);
3824 TALLOC_FREE(parent_fname_new
);
3828 /****************************************************************************
3829 Deal with setting the time from any of the setfilepathinfo functions.
3830 NOTE !!!! The check for FILE_WRITE_ATTRIBUTES access must be done *before*
3831 calling this function.
3832 ****************************************************************************/
3834 NTSTATUS
smb_set_file_time(connection_struct
*conn
,
3836 struct smb_filename
*smb_fname
,
3837 struct smb_file_time
*ft
,
3838 bool setting_write_time
)
3840 const struct smb2_lease
*lease
= NULL
;
3841 struct files_struct
*set_fsp
= NULL
;
3842 struct timeval_buf tbuf
[4];
3843 uint32_t action
= NOTIFY_ACTION_MODIFIED
;
3845 FILE_NOTIFY_CHANGE_LAST_ACCESS
3846 |FILE_NOTIFY_CHANGE_LAST_WRITE
3847 |FILE_NOTIFY_CHANGE_CREATION
;
3850 if (!VALID_STAT(smb_fname
->st
)) {
3851 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
3856 return NT_STATUS_OK
;
3859 set_fsp
= metadata_fsp(fsp
);
3861 /* get some defaults (no modifications) if any info is zero or -1. */
3862 if (is_omit_timespec(&ft
->create_time
)) {
3863 filter
&= ~FILE_NOTIFY_CHANGE_CREATION
;
3866 if (is_omit_timespec(&ft
->atime
)) {
3867 filter
&= ~FILE_NOTIFY_CHANGE_LAST_ACCESS
;
3870 if (is_omit_timespec(&ft
->mtime
)) {
3871 filter
&= ~FILE_NOTIFY_CHANGE_LAST_WRITE
;
3874 if (!setting_write_time
) {
3875 /* ft->mtime comes from change time, not write time. */
3876 filter
&= ~FILE_NOTIFY_CHANGE_LAST_WRITE
;
3879 /* Ensure the resolution is the correct for
3880 * what we can store on this filesystem. */
3882 round_timespec(conn
->ts_res
, &ft
->create_time
);
3883 round_timespec(conn
->ts_res
, &ft
->ctime
);
3884 round_timespec(conn
->ts_res
, &ft
->atime
);
3885 round_timespec(conn
->ts_res
, &ft
->mtime
);
3887 DBG_DEBUG("actime: %s\n ",
3888 timespec_string_buf(&ft
->atime
, true, &tbuf
[0]));
3889 DBG_DEBUG("modtime: %s\n ",
3890 timespec_string_buf(&ft
->mtime
, true, &tbuf
[1]));
3891 DBG_DEBUG("ctime: %s\n ",
3892 timespec_string_buf(&ft
->ctime
, true, &tbuf
[2]));
3893 DBG_DEBUG("createtime: %s\n ",
3894 timespec_string_buf(&ft
->create_time
, true, &tbuf
[3]));
3896 if (setting_write_time
) {
3898 * This was a Windows setfileinfo on an open file.
3899 * NT does this a lot. We also need to
3900 * set the time here, as it can be read by
3901 * FindFirst/FindNext and with the patch for bug #2045
3902 * in smbd/fileio.c it ensures that this timestamp is
3903 * kept sticky even after a write. We save the request
3904 * away and will set it on file close and after a write. JRA.
3907 DBG_DEBUG("setting pending modtime to %s\n",
3908 timespec_string_buf(&ft
->mtime
, true, &tbuf
[0]));
3910 set_sticky_write_time_fsp(set_fsp
, ft
->mtime
);
3911 action
|= NOTIFY_ACTION_DIRLEASE_BREAK
;
3912 lease
= fsp_get_smb2_lease(fsp
);
3915 DBG_DEBUG("setting utimes to modified values.\n");
3917 ret
= file_ntimes(conn
, set_fsp
, ft
);
3919 return map_nt_error_from_unix(errno
);
3927 return NT_STATUS_OK
;
3930 /****************************************************************************
3931 Deal with setting the dosmode from any of the setfilepathinfo functions.
3932 NB. The check for FILE_WRITE_ATTRIBUTES access on this path must have been
3933 done before calling this function.
3934 ****************************************************************************/
3936 static NTSTATUS
smb_set_file_dosmode(connection_struct
*conn
,
3937 struct files_struct
*fsp
,
3940 struct files_struct
*dos_fsp
= NULL
;
3941 uint32_t current_dosmode
;
3944 if (!VALID_STAT(fsp
->fsp_name
->st
)) {
3945 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
3948 dos_fsp
= metadata_fsp(fsp
);
3951 if (S_ISDIR(fsp
->fsp_name
->st
.st_ex_mode
)) {
3952 dosmode
|= FILE_ATTRIBUTE_DIRECTORY
;
3954 dosmode
&= ~FILE_ATTRIBUTE_DIRECTORY
;
3958 DBG_DEBUG("dosmode: 0x%" PRIx32
"\n", dosmode
);
3960 /* check the mode isn't different, before changing it */
3962 return NT_STATUS_OK
;
3964 current_dosmode
= fdos_mode(dos_fsp
);
3965 if (dosmode
== current_dosmode
) {
3966 return NT_STATUS_OK
;
3969 DBG_DEBUG("file %s : setting dos mode 0x%" PRIx32
"\n",
3970 fsp_str_dbg(dos_fsp
), dosmode
);
3972 ret
= file_set_dosmode(conn
, dos_fsp
->fsp_name
, dosmode
, NULL
, false);
3974 DBG_WARNING("file_set_dosmode of %s failed: %s\n",
3975 fsp_str_dbg(dos_fsp
), strerror(errno
));
3976 return map_nt_error_from_unix(errno
);
3979 return NT_STATUS_OK
;
3982 /****************************************************************************
3983 Deal with setting the size from any of the setfilepathinfo functions.
3984 ****************************************************************************/
3986 NTSTATUS
smb_set_file_size(connection_struct
*conn
,
3987 struct smb_request
*req
,
3989 struct smb_filename
*smb_fname
,
3990 const SMB_STRUCT_STAT
*psbuf
,
3992 bool fail_after_createfile
)
3994 NTSTATUS status
= NT_STATUS_OK
;
3995 files_struct
*new_fsp
= NULL
;
3997 if (!VALID_STAT(*psbuf
)) {
3998 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
4001 DBG_INFO("size: %"PRIu64
", file_size_stat=%"PRIu64
"\n",
4003 get_file_size_stat(psbuf
));
4005 if (size
== get_file_size_stat(psbuf
)) {
4007 return NT_STATUS_OK
;
4009 if (!fsp
->fsp_flags
.modified
) {
4010 return NT_STATUS_OK
;
4012 trigger_write_time_update_immediate(fsp
);
4013 return NT_STATUS_OK
;
4016 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
4017 smb_fname_str_dbg(smb_fname
), (double)size
));
4020 !fsp
->fsp_flags
.is_pathref
&&
4021 fsp_get_io_fd(fsp
) != -1)
4023 /* Handle based call. */
4024 status
= check_any_access_fsp(fsp
, FILE_WRITE_DATA
);
4025 if (!NT_STATUS_IS_OK(status
)) {
4029 if (vfs_set_filelen(fsp
, size
) == -1) {
4030 return map_nt_error_from_unix(errno
);
4032 trigger_write_time_update_immediate(fsp
);
4033 return NT_STATUS_OK
;
4036 status
= SMB_VFS_CREATE_FILE(
4040 smb_fname
, /* fname */
4041 FILE_WRITE_DATA
, /* access_mask */
4042 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
4044 FILE_OPEN
, /* create_disposition*/
4045 0, /* create_options */
4046 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
4047 0, /* oplock_request */
4049 0, /* allocation_size */
4050 0, /* private_flags */
4053 &new_fsp
, /* result */
4055 NULL
, NULL
); /* create context */
4057 if (!NT_STATUS_IS_OK(status
)) {
4058 /* NB. We check for open_was_deferred in the caller. */
4062 /* See RAW-SFILEINFO-END-OF-FILE */
4063 if (fail_after_createfile
) {
4064 close_file_free(req
, &new_fsp
, NORMAL_CLOSE
);
4065 return NT_STATUS_INVALID_LEVEL
;
4068 if (vfs_set_filelen(new_fsp
, size
) == -1) {
4069 status
= map_nt_error_from_unix(errno
);
4070 close_file_free(req
, &new_fsp
, NORMAL_CLOSE
);
4074 trigger_write_time_update_immediate(new_fsp
);
4075 close_file_free(req
, &new_fsp
, NORMAL_CLOSE
);
4076 return NT_STATUS_OK
;
4079 /****************************************************************************
4080 Deal with SMB_INFO_SET_EA.
4081 ****************************************************************************/
4083 static NTSTATUS
smb_info_set_ea(connection_struct
*conn
,
4087 struct smb_filename
*smb_fname
)
4089 struct ea_list
*ea_list
= NULL
;
4090 TALLOC_CTX
*ctx
= NULL
;
4091 NTSTATUS status
= NT_STATUS_OK
;
4093 if (total_data
< 10) {
4095 /* OS/2 workplace shell seems to send SET_EA requests of "null"
4096 length. They seem to have no effect. Bug #3212. JRA */
4098 if ((total_data
== 4) && (IVAL(pdata
,0) == 4)) {
4099 /* We're done. We only get EA info in this call. */
4100 return NT_STATUS_OK
;
4103 return NT_STATUS_INVALID_PARAMETER
;
4106 if (IVAL(pdata
,0) > total_data
) {
4107 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
4108 IVAL(pdata
,0), (unsigned int)total_data
));
4109 return NT_STATUS_INVALID_PARAMETER
;
4113 ea_list
= read_ea_list(ctx
, pdata
+ 4, total_data
- 4);
4115 return NT_STATUS_INVALID_PARAMETER
;
4120 * The only way fsp can be NULL here is if
4121 * smb_fname points at a symlink and
4122 * and we're in POSIX context.
4123 * Ensure this is the case.
4125 * In this case we cannot set the EA.
4127 SMB_ASSERT(smb_fname
->flags
& SMB_FILENAME_POSIX_PATH
);
4128 return NT_STATUS_ACCESS_DENIED
;
4131 status
= set_ea(conn
, fsp
, ea_list
);
4136 /****************************************************************************
4137 Deal with SMB_FILE_FULL_EA_INFORMATION set.
4138 ****************************************************************************/
4140 static NTSTATUS
smb_set_file_full_ea_info(connection_struct
*conn
,
4145 struct ea_list
*ea_list
= NULL
;
4149 return NT_STATUS_INVALID_HANDLE
;
4152 if (!lp_ea_support(SNUM(conn
))) {
4153 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
4154 "EA's not supported.\n",
4155 (unsigned int)total_data
));
4156 return NT_STATUS_EAS_NOT_SUPPORTED
;
4159 if (total_data
< 10) {
4160 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
4162 (unsigned int)total_data
));
4163 return NT_STATUS_INVALID_PARAMETER
;
4166 ea_list
= read_nttrans_ea_list(talloc_tos(),
4171 return NT_STATUS_INVALID_PARAMETER
;
4174 status
= set_ea(conn
, fsp
, ea_list
);
4176 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
4177 smb_fname_str_dbg(fsp
->fsp_name
),
4178 nt_errstr(status
) ));
4184 /****************************************************************************
4185 Deal with SMB_SET_FILE_DISPOSITION_INFO.
4186 ****************************************************************************/
4188 NTSTATUS
smb_check_file_disposition_info(struct files_struct
*fsp
,
4191 bool *_delete_on_close
)
4193 bool delete_on_close
;
4194 uint32_t dosmode
= 0;
4197 if (total_data
< 1) {
4198 return NT_STATUS_INVALID_PARAMETER
;
4202 return NT_STATUS_INVALID_HANDLE
;
4205 delete_on_close
= (PULL_LE_U8(data
, 0) ? true : false);
4206 *_delete_on_close
= delete_on_close
;
4208 dosmode
= fdos_mode(fsp
);
4210 DBG_DEBUG("file [%s] dosmode = %u, delete_on_close = %s\n",
4212 (unsigned int)dosmode
,
4213 delete_on_close
? "yes" : "no");
4215 if (!delete_on_close
) {
4216 return NT_STATUS_OK
;
4219 status
= can_set_delete_on_close(fsp
, dosmode
);
4220 if (!NT_STATUS_IS_OK(status
)) {
4224 return NT_STATUS_OK
;
4227 NTSTATUS
smb_set_file_disposition_info(connection_struct
*conn
,
4231 struct smb_filename
*smb_fname
)
4234 bool delete_on_close
;
4236 status
= smb_check_file_disposition_info(fsp
,
4240 if (!NT_STATUS_IS_OK(status
)) {
4244 /* The set is across all open files on this dev/inode pair. */
4245 if (!set_delete_on_close(fsp
, delete_on_close
,
4246 conn
->session_info
->security_token
,
4247 conn
->session_info
->unix_token
)) {
4248 return NT_STATUS_ACCESS_DENIED
;
4250 return NT_STATUS_OK
;
4253 /****************************************************************************
4254 Deal with SMB_FILE_POSITION_INFORMATION.
4255 ****************************************************************************/
4257 static NTSTATUS
smb_file_position_information(connection_struct
*conn
,
4262 uint64_t position_information
;
4264 if (total_data
< 8) {
4265 return NT_STATUS_INVALID_PARAMETER
;
4269 /* Ignore on pathname based set. */
4270 return NT_STATUS_OK
;
4273 position_information
= (uint64_t)IVAL(pdata
,0);
4274 position_information
|= (((uint64_t)IVAL(pdata
,4)) << 32);
4276 DEBUG(10,("smb_file_position_information: Set file position "
4277 "information for file %s to %.0f\n", fsp_str_dbg(fsp
),
4278 (double)position_information
));
4279 fh_set_position_information(fsp
->fh
, position_information
);
4280 return NT_STATUS_OK
;
4283 /****************************************************************************
4284 Deal with SMB_FILE_MODE_INFORMATION.
4285 ****************************************************************************/
4287 static NTSTATUS
smb_file_mode_information(connection_struct
*conn
,
4293 if (total_data
< 4) {
4294 return NT_STATUS_INVALID_PARAMETER
;
4296 mode
= IVAL(pdata
,0);
4297 if (mode
!= 0 && mode
!= 2 && mode
!= 4 && mode
!= 6) {
4298 return NT_STATUS_INVALID_PARAMETER
;
4300 return NT_STATUS_OK
;
4303 /****************************************************************************
4304 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
4305 ****************************************************************************/
4307 NTSTATUS
smb2_parse_file_rename_information(TALLOC_CTX
*ctx
,
4308 struct connection_struct
*conn
,
4309 struct smb_request
*req
,
4313 struct smb_filename
*smb_fname_src
,
4315 struct files_struct
**_dst_dirfsp
,
4316 struct smb_filename
**_smb_fname_dst
,
4317 char **_dst_original_lcomp
)
4319 char *newname
= NULL
;
4320 struct files_struct
*dst_dirfsp
= NULL
;
4321 struct smb_filename
*smb_fname_dst
= NULL
;
4322 char *dst_original_lcomp
= NULL
;
4323 uint32_t ucf_flags
= ucf_flags_from_smb_request(req
);
4324 bool overwrite
= false;
4329 return NT_STATUS_INVALID_HANDLE
;
4332 if (total_data
< 20) {
4333 return NT_STATUS_INVALID_PARAMETER
;
4336 overwrite
= (CVAL(pdata
,0) ? True
: False
);
4337 len
= IVAL(pdata
,16);
4339 if (len
> (total_data
- 20) || (len
== 0)) {
4340 return NT_STATUS_INVALID_PARAMETER
;
4343 (void)srvstr_pull_talloc(ctx
,
4351 if (newname
== NULL
) {
4352 return NT_STATUS_INVALID_PARAMETER
;
4355 /* SMB2 rename paths are never DFS. */
4356 req
->flags2
&= ~FLAGS2_DFS_PATHNAMES
;
4357 ucf_flags
&= ~UCF_DFS_PATHNAME
;
4359 status
= check_path_syntax(newname
,
4360 fsp
->fsp_name
->flags
& SMB_FILENAME_POSIX_PATH
);
4361 if (!NT_STATUS_IS_OK(status
)) {
4362 TALLOC_FREE(newname
);
4366 DBG_DEBUG("got name |%s|\n", newname
);
4368 if (newname
[0] == ':') {
4369 /* Create an smb_fname to call rename_internals_fsp() with. */
4370 smb_fname_dst
= synthetic_smb_fname(talloc_tos(),
4371 fsp
->base_fsp
->fsp_name
->base_name
,
4374 fsp
->base_fsp
->fsp_name
->twrp
,
4375 fsp
->base_fsp
->fsp_name
->flags
);
4376 if (smb_fname_dst
== NULL
) {
4377 TALLOC_FREE(newname
);
4378 return NT_STATUS_NO_MEMORY
;
4382 status
= filename_convert_dirfsp(ctx
,
4386 0, /* Never a TWRP. */
4389 if (!NT_STATUS_IS_OK(status
)) {
4395 * Set the original last component, since
4396 * rename_internals_fsp() requires it.
4398 dst_original_lcomp
= get_original_lcomp(smb_fname_dst
,
4402 if (dst_original_lcomp
== NULL
) {
4403 TALLOC_FREE(newname
);
4404 TALLOC_FREE(smb_fname_dst
);
4405 return NT_STATUS_NO_MEMORY
;
4409 *_overwrite
= overwrite
;
4410 *_dst_dirfsp
= dst_dirfsp
;
4411 *_smb_fname_dst
= smb_fname_dst
;
4412 *_dst_original_lcomp
= dst_original_lcomp
;
4413 return NT_STATUS_OK
;
4416 static NTSTATUS
smb2_file_rename_information(connection_struct
*conn
,
4417 struct smb_request
*req
,
4421 struct share_mode_lock
**lck
,
4422 struct smb_filename
*smb_fname_src
)
4425 struct files_struct
*dst_dirfsp
= NULL
;
4426 struct smb_filename
*smb_fname_dst
= NULL
;
4427 char *dst_original_lcomp
= NULL
;
4428 NTSTATUS status
= NT_STATUS_OK
;
4429 TALLOC_CTX
*ctx
= talloc_tos();
4431 status
= smb2_parse_file_rename_information(ctx
,
4441 &dst_original_lcomp
);
4442 if (!NT_STATUS_IS_OK(status
)) {
4446 DBG_DEBUG("SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
4449 smb_fname_str_dbg(smb_fname_dst
));
4451 status
= rename_internals_fsp(conn
,
4456 (FILE_ATTRIBUTE_HIDDEN
|FILE_ATTRIBUTE_SYSTEM
),
4459 TALLOC_FREE(smb_fname_dst
);
4463 static NTSTATUS
smb2_file_link_information(connection_struct
*conn
,
4464 struct smb_request
*req
,
4468 struct smb_filename
*smb_fname_src
)
4472 char *newname
= NULL
;
4473 struct files_struct
*dst_dirfsp
= NULL
;
4474 struct smb_filename
*smb_fname_dst
= NULL
;
4475 NTSTATUS status
= NT_STATUS_OK
;
4476 uint32_t ucf_flags
= ucf_flags_from_smb_request(req
);
4478 TALLOC_CTX
*ctx
= talloc_tos();
4481 return NT_STATUS_INVALID_HANDLE
;
4484 if (total_data
< 20) {
4485 return NT_STATUS_INVALID_PARAMETER
;
4488 overwrite
= (CVAL(pdata
,0) ? true : false);
4489 len
= IVAL(pdata
,16);
4491 if (len
> (total_data
- 20) || (len
== 0)) {
4492 return NT_STATUS_INVALID_PARAMETER
;
4495 ret
= srvstr_pull_talloc(ctx
,
4503 if (ret
== (size_t)-1 || newname
== NULL
) {
4504 return NT_STATUS_INVALID_PARAMETER
;
4507 /* SMB2 hardlink paths are never DFS. */
4508 req
->flags2
&= ~FLAGS2_DFS_PATHNAMES
;
4509 ucf_flags
&= ~UCF_DFS_PATHNAME
;
4511 status
= check_path_syntax(newname
,
4512 fsp
->fsp_name
->flags
& SMB_FILENAME_POSIX_PATH
);
4513 if (!NT_STATUS_IS_OK(status
)) {
4517 DBG_DEBUG("got name |%s|\n", newname
);
4519 status
= filename_convert_dirfsp(ctx
,
4526 if (!NT_STATUS_IS_OK(status
)) {
4530 if (fsp
->base_fsp
) {
4531 /* No stream names. */
4532 return NT_STATUS_NOT_SUPPORTED
;
4535 DBG_DEBUG("SMB_FILE_LINK_INFORMATION (%s) %s -> %s\n",
4536 fsp_fnum_dbg(fsp
), fsp_str_dbg(fsp
),
4537 smb_fname_str_dbg(smb_fname_dst
));
4538 status
= hardlink_internals(ctx
,
4545 TALLOC_FREE(smb_fname_dst
);
4549 static NTSTATUS
smb_file_link_information(connection_struct
*conn
,
4550 struct smb_request
*req
,
4554 struct smb_filename
*smb_fname_src
)
4558 char *newname
= NULL
;
4559 struct files_struct
*dst_dirfsp
= NULL
;
4560 struct smb_filename
*smb_fname_dst
= NULL
;
4561 NTSTATUS status
= NT_STATUS_OK
;
4562 uint32_t ucf_flags
= ucf_flags_from_smb_request(req
);
4563 NTTIME dst_twrp
= 0;
4564 TALLOC_CTX
*ctx
= talloc_tos();
4567 return NT_STATUS_INVALID_HANDLE
;
4570 if (total_data
< 20) {
4571 return NT_STATUS_INVALID_PARAMETER
;
4574 overwrite
= (CVAL(pdata
,0) ? true : false);
4575 len
= IVAL(pdata
,16);
4577 if (len
> (total_data
- 20) || (len
== 0)) {
4578 return NT_STATUS_INVALID_PARAMETER
;
4581 if (smb_fname_src
->flags
& SMB_FILENAME_POSIX_PATH
) {
4582 srvstr_get_path_posix(ctx
,
4590 ucf_flags
|= UCF_POSIX_PATHNAMES
;
4592 srvstr_get_path(ctx
,
4601 if (!NT_STATUS_IS_OK(status
)) {
4605 DEBUG(10,("smb_file_link_information: got name |%s|\n",
4608 if (ucf_flags
& UCF_GMT_PATHNAME
) {
4609 extract_snapshot_token(newname
, &dst_twrp
);
4611 /* hardlink paths are never DFS. */
4612 ucf_flags
&= ~UCF_DFS_PATHNAME
;
4614 status
= filename_convert_dirfsp(ctx
,
4621 if (!NT_STATUS_IS_OK(status
)) {
4625 if (fsp
->base_fsp
) {
4626 /* No stream names. */
4627 return NT_STATUS_NOT_SUPPORTED
;
4630 DEBUG(10,("smb_file_link_information: "
4631 "SMB_FILE_LINK_INFORMATION (%s) %s -> %s\n",
4632 fsp_fnum_dbg(fsp
), fsp_str_dbg(fsp
),
4633 smb_fname_str_dbg(smb_fname_dst
)));
4634 status
= hardlink_internals(ctx
,
4641 TALLOC_FREE(smb_fname_dst
);
4646 /****************************************************************************
4647 Deal with SMB_FILE_RENAME_INFORMATION.
4648 ****************************************************************************/
4650 static NTSTATUS
smb_file_rename_information(connection_struct
*conn
,
4651 struct smb_request
*req
,
4655 struct smb_filename
*smb_fname_src
)
4660 char *newname
= NULL
;
4661 struct files_struct
*dst_dirfsp
= NULL
;
4662 struct smb_filename
*smb_fname_dst
= NULL
;
4663 const char *dst_original_lcomp
= NULL
;
4664 NTSTATUS status
= NT_STATUS_OK
;
4666 TALLOC_CTX
*ctx
= talloc_tos();
4668 if (total_data
< 13) {
4669 return NT_STATUS_INVALID_PARAMETER
;
4672 overwrite
= (CVAL(pdata
,0) != 0);
4673 root_fid
= IVAL(pdata
,4);
4674 len
= IVAL(pdata
,8);
4676 if (len
> (total_data
- 12) || (len
== 0) || (root_fid
!= 0)) {
4677 return NT_STATUS_INVALID_PARAMETER
;
4680 if (req
->posix_pathnames
) {
4681 srvstr_get_path_posix(ctx
,
4690 srvstr_get_path(ctx
,
4699 if (!NT_STATUS_IS_OK(status
)) {
4703 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
4706 /* Check the new name has no '/' characters. */
4707 if (strchr_m(newname
, '/')) {
4708 return NT_STATUS_NOT_SUPPORTED
;
4711 if (fsp
&& fsp
->base_fsp
) {
4712 /* newname must be a stream name. */
4713 if (newname
[0] != ':') {
4714 return NT_STATUS_NOT_SUPPORTED
;
4717 /* Create an smb_fname to call rename_internals_fsp() with. */
4718 smb_fname_dst
= synthetic_smb_fname(talloc_tos(),
4719 fsp
->base_fsp
->fsp_name
->base_name
,
4722 fsp
->base_fsp
->fsp_name
->twrp
,
4723 fsp
->base_fsp
->fsp_name
->flags
);
4724 if (smb_fname_dst
== NULL
) {
4725 status
= NT_STATUS_NO_MEMORY
;
4730 * Get the original last component, since
4731 * rename_internals_fsp() requires it.
4733 dst_original_lcomp
= get_original_lcomp(smb_fname_dst
,
4737 if (dst_original_lcomp
== NULL
) {
4738 status
= NT_STATUS_NO_MEMORY
;
4744 * Build up an smb_fname_dst based on the filename passed in.
4745 * We basically just strip off the last component, and put on
4746 * the newname instead.
4748 char *base_name
= NULL
;
4749 uint32_t ucf_flags
= ucf_flags_from_smb_request(req
);
4750 NTTIME dst_twrp
= 0;
4752 /* newname must *not* be a stream name. */
4753 if (newname
[0] == ':') {
4754 return NT_STATUS_NOT_SUPPORTED
;
4758 * Strip off the last component (filename) of the path passed
4761 base_name
= talloc_strdup(ctx
, smb_fname_src
->base_name
);
4763 return NT_STATUS_NO_MEMORY
;
4765 p
= strrchr_m(base_name
, '/');
4769 base_name
= talloc_strdup(ctx
, "");
4771 return NT_STATUS_NO_MEMORY
;
4774 /* Append the new name. */
4775 base_name
= talloc_asprintf_append(base_name
,
4779 return NT_STATUS_NO_MEMORY
;
4782 if (ucf_flags
& UCF_GMT_PATHNAME
) {
4783 extract_snapshot_token(base_name
, &dst_twrp
);
4786 /* The newname is *not* a DFS path. */
4787 ucf_flags
&= ~UCF_DFS_PATHNAME
;
4789 status
= filename_convert_dirfsp(ctx
,
4797 if (!NT_STATUS_IS_OK(status
)) {
4800 dst_original_lcomp
= get_original_lcomp(smb_fname_dst
,
4804 if (dst_original_lcomp
== NULL
) {
4805 status
= NT_STATUS_NO_MEMORY
;
4810 if (fsp
!= NULL
&& fsp
->fsp_flags
.is_fsa
) {
4811 DEBUG(10,("smb_file_rename_information: "
4812 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
4813 fsp_fnum_dbg(fsp
), fsp_str_dbg(fsp
),
4814 smb_fname_str_dbg(smb_fname_dst
)));
4817 * If no pathnames are open below this directory,
4820 if (have_file_open_below(fsp
)) {
4821 status
= NT_STATUS_ACCESS_DENIED
;
4825 status
= rename_internals_fsp(conn
,
4833 DEBUG(10,("smb_file_rename_information: "
4834 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
4835 smb_fname_str_dbg(smb_fname_src
),
4836 smb_fname_str_dbg(smb_fname_dst
)));
4837 status
= rename_internals(ctx
,
4840 NULL
, /* src_dirfsp */
4846 FILE_WRITE_ATTRIBUTES
);
4849 TALLOC_FREE(smb_fname_dst
);
4853 /****************************************************************************
4854 Deal with SMB_SET_FILE_BASIC_INFO.
4855 ****************************************************************************/
4857 static NTSTATUS
smb_set_file_basic_info(connection_struct
*conn
,
4861 struct smb_filename
*smb_fname
)
4863 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
4864 struct smb_file_time ft
;
4865 uint32_t dosmode
= 0;
4866 NTSTATUS status
= NT_STATUS_OK
;
4868 init_smb_file_time(&ft
);
4870 if (total_data
< 36) {
4871 return NT_STATUS_INVALID_PARAMETER
;
4875 return NT_STATUS_INVALID_HANDLE
;
4878 status
= check_any_access_fsp(fsp
, FILE_WRITE_ATTRIBUTES
);
4879 if (!NT_STATUS_IS_OK(status
)) {
4883 /* Set the attributes */
4884 dosmode
= IVAL(pdata
,32);
4885 status
= smb_set_file_dosmode(conn
, fsp
, dosmode
);
4886 if (!NT_STATUS_IS_OK(status
)) {
4891 ft
.create_time
= pull_long_date_full_timespec(pdata
);
4894 ft
.atime
= pull_long_date_full_timespec(pdata
+8);
4897 ft
.mtime
= pull_long_date_full_timespec(pdata
+16);
4900 ft
.ctime
= pull_long_date_full_timespec(pdata
+24);
4902 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
4903 smb_fname_str_dbg(smb_fname
)));
4905 status
= smb_set_file_time(conn
, fsp
, smb_fname
, &ft
, true);
4906 if (!NT_STATUS_IS_OK(status
)) {
4910 if (fsp
->fsp_flags
.modified
) {
4911 trigger_write_time_update_immediate(fsp
);
4913 return NT_STATUS_OK
;
4916 /****************************************************************************
4917 Deal with SMB_INFO_STANDARD.
4918 ****************************************************************************/
4920 static NTSTATUS
smb_set_info_standard(connection_struct
*conn
,
4924 struct smb_filename
*smb_fname
)
4927 struct smb_file_time ft
;
4929 init_smb_file_time(&ft
);
4931 if (total_data
< 12) {
4932 return NT_STATUS_INVALID_PARAMETER
;
4936 return NT_STATUS_INVALID_HANDLE
;
4940 ft
.create_time
= time_t_to_full_timespec(srv_make_unix_date2(pdata
));
4942 ft
.atime
= time_t_to_full_timespec(srv_make_unix_date2(pdata
+4));
4944 ft
.mtime
= time_t_to_full_timespec(srv_make_unix_date2(pdata
+8));
4946 DEBUG(10,("smb_set_info_standard: file %s\n",
4947 smb_fname_str_dbg(smb_fname
)));
4949 status
= check_any_access_fsp(fsp
, FILE_WRITE_ATTRIBUTES
);
4950 if (!NT_STATUS_IS_OK(status
)) {
4954 status
= smb_set_file_time(conn
, fsp
, smb_fname
, &ft
, true);
4955 if (!NT_STATUS_IS_OK(status
)) {
4959 if (fsp
->fsp_flags
.modified
) {
4960 trigger_write_time_update_immediate(fsp
);
4962 return NT_STATUS_OK
;
4965 /****************************************************************************
4966 Deal with SMB_SET_FILE_ALLOCATION_INFO.
4967 ****************************************************************************/
4969 static NTSTATUS
smb_set_file_allocation_info(connection_struct
*conn
,
4970 struct smb_request
*req
,
4974 struct smb_filename
*smb_fname
)
4976 uint64_t allocation_size
= 0;
4977 NTSTATUS status
= NT_STATUS_OK
;
4978 files_struct
*new_fsp
= NULL
;
4980 if (!VALID_STAT(smb_fname
->st
)) {
4981 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
4984 if (total_data
< 8) {
4985 return NT_STATUS_INVALID_PARAMETER
;
4988 allocation_size
= (uint64_t)IVAL(pdata
,0);
4989 allocation_size
|= (((uint64_t)IVAL(pdata
,4)) << 32);
4990 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
4991 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname
),
4992 (double)allocation_size
));
4994 if (allocation_size
) {
4995 allocation_size
= smb_roundup(conn
, allocation_size
);
4998 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
4999 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname
),
5000 (double)allocation_size
));
5003 !fsp
->fsp_flags
.is_pathref
&&
5004 fsp_get_io_fd(fsp
) != -1)
5006 /* Open file handle. */
5007 status
= check_any_access_fsp(fsp
, FILE_WRITE_DATA
);
5008 if (!NT_STATUS_IS_OK(status
)) {
5012 /* Only change if needed. */
5013 if (allocation_size
!= get_file_size_stat(&smb_fname
->st
)) {
5014 if (vfs_allocate_file_space(fsp
, allocation_size
) == -1) {
5015 return map_nt_error_from_unix(errno
);
5018 /* But always update the time. */
5020 * This is equivalent to a write. Ensure it's seen immediately
5021 * if there are no pending writes.
5023 trigger_write_time_update_immediate(fsp
);
5024 return NT_STATUS_OK
;
5027 /* Pathname or stat or directory file. */
5028 status
= SMB_VFS_CREATE_FILE(
5032 smb_fname
, /* fname */
5033 FILE_WRITE_DATA
, /* access_mask */
5034 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
5036 FILE_OPEN
, /* create_disposition*/
5037 0, /* create_options */
5038 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
5039 0, /* oplock_request */
5041 0, /* allocation_size */
5042 0, /* private_flags */
5045 &new_fsp
, /* result */
5047 NULL
, NULL
); /* create context */
5049 if (!NT_STATUS_IS_OK(status
)) {
5050 /* NB. We check for open_was_deferred in the caller. */
5054 /* Only change if needed. */
5055 if (allocation_size
!= get_file_size_stat(&smb_fname
->st
)) {
5056 if (vfs_allocate_file_space(new_fsp
, allocation_size
) == -1) {
5057 status
= map_nt_error_from_unix(errno
);
5058 close_file_free(req
, &new_fsp
, NORMAL_CLOSE
);
5063 /* Changing the allocation size should set the last mod time. */
5065 * This is equivalent to a write. Ensure it's seen immediately
5066 * if there are no pending writes.
5068 trigger_write_time_update_immediate(new_fsp
);
5069 close_file_free(req
, &new_fsp
, NORMAL_CLOSE
);
5070 return NT_STATUS_OK
;
5073 /****************************************************************************
5074 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
5075 ****************************************************************************/
5077 static NTSTATUS
smb_set_file_end_of_file_info(connection_struct
*conn
,
5078 struct smb_request
*req
,
5082 struct smb_filename
*smb_fname
,
5083 bool fail_after_createfile
)
5087 if (total_data
< 8) {
5088 return NT_STATUS_INVALID_PARAMETER
;
5091 size
= IVAL(pdata
,0);
5092 size
|= (((off_t
)IVAL(pdata
,4)) << 32);
5093 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
5094 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname
),
5097 return smb_set_file_size(conn
, req
,
5102 fail_after_createfile
);
5108 * Called from the SMB1 and SMB2 code. For the path-based SMB1 code, there may
5109 * not be a full fsp from the FSA layer.
5111 * lck may be NULL, currently only passed for SMB2 rename requests.
5113 NTSTATUS
smbd_do_setfilepathinfo(connection_struct
*conn
,
5114 struct smb_request
*req
,
5115 TALLOC_CTX
*mem_ctx
,
5116 uint16_t info_level
,
5118 struct share_mode_lock
**lck
,
5119 struct smb_filename
*smb_fname
,
5124 NTSTATUS status
= NT_STATUS_OK
;
5125 int data_return_size
= 0;
5129 DEBUG(3,("smbd_do_setfilepathinfo: %s (%s) info_level=%d "
5130 "totdata=%d\n", smb_fname_str_dbg(smb_fname
),
5132 info_level
, total_data
));
5134 SMB_ASSERT(fsp
!= NULL
);
5136 switch (info_level
) {
5138 case SMB_INFO_STANDARD
:
5140 status
= smb_set_info_standard(conn
,
5148 case SMB_INFO_SET_EA
:
5150 status
= smb_info_set_ea(conn
,
5158 case SMB_SET_FILE_BASIC_INFO
:
5159 case SMB_FILE_BASIC_INFORMATION
:
5161 status
= smb_set_file_basic_info(conn
,
5169 case SMB_FILE_ALLOCATION_INFORMATION
:
5170 case SMB_SET_FILE_ALLOCATION_INFO
:
5172 status
= smb_set_file_allocation_info(conn
, req
,
5180 case SMB_FILE_END_OF_FILE_INFORMATION
:
5181 case SMB_SET_FILE_END_OF_FILE_INFO
:
5184 * XP/Win7 both fail after the createfile with
5185 * SMB_SET_FILE_END_OF_FILE_INFO but not
5186 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
5187 * The level is known here, so pass it down
5191 (info_level
== SMB_SET_FILE_END_OF_FILE_INFO
);
5193 status
= smb_set_file_end_of_file_info(conn
, req
,
5202 case SMB_FILE_DISPOSITION_INFORMATION
:
5203 case SMB_SET_FILE_DISPOSITION_INFO
: /* Set delete on close for open file. */
5205 status
= smb_set_file_disposition_info(conn
,
5213 case SMB_FILE_POSITION_INFORMATION
:
5215 status
= smb_file_position_information(conn
,
5222 case SMB_FILE_FULL_EA_INFORMATION
:
5224 status
= smb_set_file_full_ea_info(conn
,
5231 /* From tridge Samba4 :
5232 * MODE_INFORMATION in setfileinfo (I have no
5233 * idea what "mode information" on a file is - it takes a value of 0,
5234 * 2, 4 or 6. What could it be?).
5237 case SMB_FILE_MODE_INFORMATION
:
5239 status
= smb_file_mode_information(conn
,
5245 /* [MS-SMB2] 3.3.5.21.1 states we MUST fail with STATUS_NOT_SUPPORTED. */
5246 case SMB_FILE_VALID_DATA_LENGTH_INFORMATION
:
5247 case SMB_FILE_SHORT_NAME_INFORMATION
:
5248 return NT_STATUS_NOT_SUPPORTED
;
5250 case SMB_FILE_RENAME_INFORMATION
:
5252 status
= smb_file_rename_information(conn
, req
,
5258 case SMB2_FILE_RENAME_INFORMATION_INTERNAL
:
5260 /* SMB2 rename information. */
5261 status
= smb2_file_rename_information(conn
,
5271 case SMB_FILE_LINK_INFORMATION
:
5273 if (conn_using_smb2(conn
->sconn
)) {
5274 status
= smb2_file_link_information(conn
,
5281 status
= smb_file_link_information(conn
,
5292 return NT_STATUS_INVALID_LEVEL
;
5295 if (!NT_STATUS_IS_OK(status
)) {
5299 *ret_data_size
= data_return_size
;
5300 return NT_STATUS_OK
;
5303 static uint32_t generate_volume_serial_number(
5304 const struct loadparm_substitution
*lp_sub
,
5307 int serial
= lp_volume_serial_number(snum
);
5308 return serial
!= -1 ? serial
:
5309 str_checksum(lp_servicename(talloc_tos(), lp_sub
, snum
)) ^
5310 (str_checksum(get_local_machine_name())<<16);