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"
52 #define DIR_ENTRY_SAFETY_MARGIN 4096
54 static uint32_t generate_volume_serial_number(
55 const struct loadparm_substitution
*lp_sub
,
58 /****************************************************************************
59 Check if an open file handle is a symlink.
60 ****************************************************************************/
62 NTSTATUS
refuse_symlink_fsp(const files_struct
*fsp
)
65 if (!VALID_STAT(fsp
->fsp_name
->st
)) {
66 return NT_STATUS_ACCESS_DENIED
;
68 if (S_ISLNK(fsp
->fsp_name
->st
.st_ex_mode
)) {
69 return NT_STATUS_ACCESS_DENIED
;
71 if (fsp_get_pathref_fd(fsp
) == -1) {
72 return NT_STATUS_ACCESS_DENIED
;
78 * Check that one or more of the rights in access mask are
79 * allowed. Iow, access_requested can contain more then one right and
80 * it is sufficient having only one of those granted to pass.
82 NTSTATUS
check_any_access_fsp(struct files_struct
*fsp
,
83 uint32_t access_requested
)
85 const uint32_t ro_access
= SEC_RIGHTS_FILE_READ
| SEC_FILE_EXECUTE
;
86 uint32_t ro_access_granted
= 0;
87 uint32_t access_granted
= 0;
90 if (fsp
->fsp_flags
.is_fsa
) {
91 access_granted
= fsp
->access_mask
;
96 if (!(mask
& access_requested
)) {
101 status
= smbd_check_access_rights_fsp(
106 if (NT_STATUS_IS_OK(status
)) {
107 access_granted
|= mask
;
108 if (fsp
->fsp_name
->twrp
== 0) {
110 * We can only optimize
111 * the non-snapshot case
119 if ((access_granted
& access_requested
) == 0) {
120 return NT_STATUS_ACCESS_DENIED
;
123 if (fsp
->fsp_name
->twrp
== 0) {
127 ro_access_granted
= access_granted
& ro_access
;
128 if ((ro_access_granted
& access_requested
) == 0) {
129 return NT_STATUS_MEDIA_WRITE_PROTECTED
;
135 /********************************************************************
136 Roundup a value to the nearest allocation roundup size boundary.
137 Only do this for Windows clients.
138 ********************************************************************/
140 uint64_t smb_roundup(connection_struct
*conn
, uint64_t val
)
142 uint64_t rval
= lp_allocation_roundup_size(SNUM(conn
));
144 /* Only roundup for Windows clients. */
145 enum remote_arch_types ra_type
= get_remote_arch();
146 if (rval
&& (ra_type
!= RA_SAMBA
) && (ra_type
!= RA_CIFSFS
)) {
147 val
= SMB_ROUNDUP(val
,rval
);
152 /****************************************************************************
153 Utility functions for dealing with extended attributes.
154 ****************************************************************************/
156 /****************************************************************************
157 Refuse to allow clients to overwrite our private xattrs.
158 ****************************************************************************/
160 bool samba_private_attr_name(const char *unix_ea_name
)
162 bool prohibited
= false;
164 prohibited
|= strequal(unix_ea_name
, SAMBA_POSIX_INHERITANCE_EA_NAME
);
165 prohibited
|= strequal(unix_ea_name
, SAMBA_XATTR_DOS_ATTRIB
);
166 prohibited
|= strequal(unix_ea_name
, SAMBA_XATTR_MARKER
);
167 prohibited
|= strequal(unix_ea_name
, SAMBA_XATTR_REPARSE_ATTRIB
);
168 prohibited
|= strequal(unix_ea_name
, XATTR_NTACL_NAME
);
169 prohibited
|= strequal(unix_ea_name
, AFPINFO_EA_NETATALK
);
175 if (strncasecmp_m(unix_ea_name
, SAMBA_XATTR_DOSSTREAM_PREFIX
,
176 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX
)) == 0) {
182 /****************************************************************************
183 Get one EA value. Fill in a struct ea_struct.
184 ****************************************************************************/
186 NTSTATUS
get_ea_value_fsp(TALLOC_CTX
*mem_ctx
,
189 struct ea_struct
*pea
)
191 /* Get the value of this xattr. Max size is 64k. */
192 size_t attr_size
= 256;
195 size_t max_xattr_size
= 0;
199 return NT_STATUS_INVALID_HANDLE
;
201 status
= refuse_symlink_fsp(fsp
);
202 if (!NT_STATUS_IS_OK(status
)) {
206 max_xattr_size
= lp_smbd_max_xattr_size(SNUM(fsp
->conn
));
210 val
= talloc_realloc(mem_ctx
, val
, char, attr_size
);
212 return NT_STATUS_NO_MEMORY
;
215 sizeret
= SMB_VFS_FGETXATTR(fsp
, ea_name
, val
, attr_size
);
216 if (sizeret
== -1 && errno
== ERANGE
&& attr_size
< max_xattr_size
) {
217 attr_size
= max_xattr_size
;
222 return map_nt_error_from_unix(errno
);
225 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name
, (unsigned int)sizeret
));
226 dump_data(10, (uint8_t *)val
, sizeret
);
229 if (strnequal(ea_name
, "user.", 5)) {
230 pea
->name
= talloc_strdup(mem_ctx
, &ea_name
[5]);
232 pea
->name
= talloc_strdup(mem_ctx
, ea_name
);
234 if (pea
->name
== NULL
) {
236 return NT_STATUS_NO_MEMORY
;
238 pea
->value
.data
= (unsigned char *)val
;
239 pea
->value
.length
= (size_t)sizeret
;
243 NTSTATUS
get_ea_names_from_fsp(TALLOC_CTX
*mem_ctx
,
249 /* Get a list of all xattrs. Max namesize is 64k. */
250 size_t ea_namelist_size
= 1024;
251 char *ea_namelist
= smallbuf
;
252 char *to_free
= NULL
;
257 ssize_t sizeret
= -1;
265 if ((fsp
== NULL
) || !NT_STATUS_IS_OK(refuse_symlink_fsp(fsp
))) {
267 * Callers may pass fsp == NULL when passing smb_fname->fsp of a
268 * symlink. This is ok, handle it here, by just return no EA's
274 sizeret
= SMB_VFS_FLISTXATTR(fsp
, ea_namelist
,
277 if ((sizeret
== -1) && (errno
== ERANGE
)) {
278 ea_namelist_size
= 65536;
279 ea_namelist
= talloc_array(mem_ctx
, char, ea_namelist_size
);
280 if (ea_namelist
== NULL
) {
281 return NT_STATUS_NO_MEMORY
;
283 to_free
= ea_namelist
;
285 sizeret
= SMB_VFS_FLISTXATTR(fsp
, ea_namelist
,
290 status
= map_nt_error_from_unix(errno
);
291 TALLOC_FREE(to_free
);
295 DBG_DEBUG("ea_namelist size = %zd\n", sizeret
);
298 TALLOC_FREE(to_free
);
303 * Ensure the result is 0-terminated
306 if (ea_namelist
[sizeret
-1] != '\0') {
307 TALLOC_FREE(to_free
);
308 return NT_STATUS_INTERNAL_ERROR
;
316 for (p
= ea_namelist
; p
- ea_namelist
< sizeret
; p
+= strlen(p
)+1) {
320 *pnum_names
= num_names
;
322 if (pnames
== NULL
) {
323 TALLOC_FREE(to_free
);
327 names
= talloc_array(mem_ctx
, char *, num_names
);
329 DEBUG(0, ("talloc failed\n"));
330 TALLOC_FREE(to_free
);
331 return NT_STATUS_NO_MEMORY
;
334 if (ea_namelist
== smallbuf
) {
335 ea_namelist
= talloc_memdup(names
, smallbuf
, sizeret
);
336 if (ea_namelist
== NULL
) {
338 return NT_STATUS_NO_MEMORY
;
341 talloc_steal(names
, ea_namelist
);
343 ea_namelist
= talloc_realloc(names
, ea_namelist
, char,
345 if (ea_namelist
== NULL
) {
347 return NT_STATUS_NO_MEMORY
;
353 for (p
= ea_namelist
; p
- ea_namelist
< sizeret
; p
+= strlen(p
)+1) {
354 names
[num_names
++] = p
;
362 /****************************************************************************
363 Return a linked list of the total EA's. Plus the total size
364 ****************************************************************************/
366 static NTSTATUS
get_ea_list_from_fsp(TALLOC_CTX
*mem_ctx
,
368 size_t *pea_total_len
,
369 struct ea_list
**ea_list
)
371 /* Get a list of all xattrs. Max namesize is 64k. */
374 struct ea_list
*ea_list_head
= NULL
;
375 bool posix_pathnames
= false;
386 if (!lp_ea_support(SNUM(fsp
->conn
))) {
390 if (fsp_is_alternate_stream(fsp
)) {
391 return NT_STATUS_INVALID_PARAMETER
;
394 posix_pathnames
= (fsp
->fsp_name
->flags
& SMB_FILENAME_POSIX_PATH
);
396 status
= get_ea_names_from_fsp(talloc_tos(),
401 if (!NT_STATUS_IS_OK(status
)) {
405 if (num_names
== 0) {
409 for (i
=0; i
<num_names
; i
++) {
410 struct ea_list
*listp
;
414 * POSIX EA names are divided into several namespaces by
415 * means of string prefixes. Usually, the system controls
416 * semantics for each namespace, but the 'user' namespace is
417 * available for arbitrary use, which comes closest to
418 * Windows EA semantics. Hence, we map POSIX EAs from the
419 * 'user' namespace to Windows EAs, and just ignore all the
420 * other namespaces. Also, a few specific names in the 'user'
421 * namespace are used by Samba internally. Filter them out as
422 * well, and only present the EAs that are available for
425 if (!strnequal(names
[i
], "user.", 5)
426 || samba_private_attr_name(names
[i
]))
430 * Filter out any underlying POSIX EA names
431 * that a Windows client can't handle.
433 if (!posix_pathnames
&&
434 is_invalid_windows_ea_name(names
[i
])) {
438 listp
= talloc(mem_ctx
, struct ea_list
);
440 return NT_STATUS_NO_MEMORY
;
443 status
= get_ea_value_fsp(listp
,
448 if (!NT_STATUS_IS_OK(status
)) {
453 if (listp
->ea
.value
.length
== 0) {
455 * We can never return a zero length EA.
456 * Windows reports the EA's as corrupted.
460 } else if (listp
->ea
.value
.length
> 65536) {
462 * SMB clients may report error with file
463 * if large EA is presented to them.
465 DBG_ERR("EA [%s] on file [%s] exceeds "
466 "maximum permitted EA size of 64KiB: %zu\n.",
467 listp
->ea
.name
, fsp_str_dbg(fsp
),
468 listp
->ea
.value
.length
);
473 push_ascii_fstring(dos_ea_name
, listp
->ea
.name
);
476 4 + strlen(dos_ea_name
) + 1 + listp
->ea
.value
.length
;
478 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
479 "= %u\n", (unsigned int)*pea_total_len
, dos_ea_name
,
480 (unsigned int)listp
->ea
.value
.length
));
482 DLIST_ADD_END(ea_list_head
, listp
);
486 /* Add on 4 for total length. */
487 if (*pea_total_len
) {
491 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
492 (unsigned int)*pea_total_len
));
494 *ea_list
= ea_list_head
;
498 /****************************************************************************
499 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
501 ****************************************************************************/
503 static unsigned int fill_ea_buffer(TALLOC_CTX
*mem_ctx
, char *pdata
, unsigned int total_data_size
,
504 connection_struct
*conn
, struct ea_list
*ea_list
)
506 unsigned int ret_data_size
= 4;
509 SMB_ASSERT(total_data_size
>= 4);
511 if (!lp_ea_support(SNUM(conn
))) {
516 for (p
= pdata
+ 4; ea_list
; ea_list
= ea_list
->next
) {
519 push_ascii_fstring(dos_ea_name
, ea_list
->ea
.name
);
520 dos_namelen
= strlen(dos_ea_name
);
521 if (dos_namelen
> 255 || dos_namelen
== 0) {
524 if (ea_list
->ea
.value
.length
> 65535) {
527 if (4 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
> total_data_size
) {
531 /* We know we have room. */
532 SCVAL(p
,0,ea_list
->ea
.flags
);
533 SCVAL(p
,1,dos_namelen
);
534 SSVAL(p
,2,ea_list
->ea
.value
.length
);
535 strlcpy(p
+4, dos_ea_name
, dos_namelen
+1);
536 if (ea_list
->ea
.value
.length
> 0) {
537 memcpy(p
+ 4 + dos_namelen
+ 1,
538 ea_list
->ea
.value
.data
,
539 ea_list
->ea
.value
.length
);
542 total_data_size
-= 4 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
;
543 p
+= 4 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
;
546 ret_data_size
= PTR_DIFF(p
, pdata
);
547 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size
));
548 SIVAL(pdata
,0,ret_data_size
);
549 return ret_data_size
;
552 static NTSTATUS
fill_ea_chained_buffer(TALLOC_CTX
*mem_ctx
,
554 unsigned int total_data_size
,
555 unsigned int *ret_data_size
,
556 connection_struct
*conn
,
557 struct ea_list
*ea_list
)
559 uint8_t *p
= (uint8_t *)pdata
;
560 uint8_t *last_start
= NULL
;
561 bool do_store_data
= (pdata
!= NULL
);
565 if (!lp_ea_support(SNUM(conn
))) {
566 return NT_STATUS_NO_EAS_ON_FILE
;
569 for (; ea_list
; ea_list
= ea_list
->next
) {
575 if (last_start
!= NULL
&& do_store_data
) {
576 SIVAL(last_start
, 0, PTR_DIFF(p
, last_start
));
580 push_ascii_fstring(dos_ea_name
, ea_list
->ea
.name
);
581 dos_namelen
= strlen(dos_ea_name
);
582 if (dos_namelen
> 255 || dos_namelen
== 0) {
583 return NT_STATUS_INTERNAL_ERROR
;
585 if (ea_list
->ea
.value
.length
> 65535) {
586 return NT_STATUS_INTERNAL_ERROR
;
589 this_size
= 0x08 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
;
592 pad
= (4 - (this_size
% 4)) % 4;
597 if (this_size
> total_data_size
) {
598 return NT_STATUS_INFO_LENGTH_MISMATCH
;
601 /* We know we have room. */
602 SIVAL(p
, 0x00, 0); /* next offset */
603 SCVAL(p
, 0x04, ea_list
->ea
.flags
);
604 SCVAL(p
, 0x05, dos_namelen
);
605 SSVAL(p
, 0x06, ea_list
->ea
.value
.length
);
606 strlcpy((char *)(p
+0x08), dos_ea_name
, dos_namelen
+1);
607 memcpy(p
+ 0x08 + dos_namelen
+ 1, ea_list
->ea
.value
.data
, ea_list
->ea
.value
.length
);
609 memset(p
+ 0x08 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
,
613 total_data_size
-= this_size
;
619 *ret_data_size
= PTR_DIFF(p
, pdata
);
620 DEBUG(10,("fill_ea_chained_buffer: data_size = %u\n", *ret_data_size
));
624 unsigned int estimate_ea_size(files_struct
*fsp
)
626 size_t total_ea_len
= 0;
628 struct ea_list
*ea_list
= NULL
;
636 if (!lp_ea_support(SNUM(fsp
->conn
))) {
640 mem_ctx
= talloc_stackframe();
642 /* If this is a stream fsp, then we need to instead find the
643 * estimated ea len from the main file, not the stream
644 * (streams cannot have EAs), but the estimate isn't just 0 in
646 fsp
= metadata_fsp(fsp
);
647 (void)get_ea_list_from_fsp(mem_ctx
,
652 if(conn_using_smb2(fsp
->conn
->sconn
)) {
653 unsigned int ret_data_size
;
655 * We're going to be using fill_ea_chained_buffer() to
656 * marshall EA's - this size is significantly larger
657 * than the SMB1 buffer. Re-calculate the size without
660 status
= fill_ea_chained_buffer(mem_ctx
,
666 if (!NT_STATUS_IS_OK(status
)) {
669 total_ea_len
= ret_data_size
;
671 TALLOC_FREE(mem_ctx
);
675 /****************************************************************************
676 Ensure the EA name is case insensitive by matching any existing EA name.
677 ****************************************************************************/
679 static void canonicalize_ea_name(files_struct
*fsp
,
680 fstring unix_ea_name
)
683 TALLOC_CTX
*mem_ctx
= talloc_tos();
684 struct ea_list
*ea_list
;
685 NTSTATUS status
= get_ea_list_from_fsp(mem_ctx
,
689 if (!NT_STATUS_IS_OK(status
)) {
693 for (; ea_list
; ea_list
= ea_list
->next
) {
694 if (strequal(&unix_ea_name
[5], ea_list
->ea
.name
)) {
695 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
696 &unix_ea_name
[5], ea_list
->ea
.name
));
697 strlcpy(&unix_ea_name
[5], ea_list
->ea
.name
, sizeof(fstring
)-5);
703 /****************************************************************************
704 Set or delete an extended attribute.
705 ****************************************************************************/
707 NTSTATUS
set_ea(connection_struct
*conn
, files_struct
*fsp
,
708 struct ea_list
*ea_list
)
711 bool posix_pathnames
= false;
713 if (!lp_ea_support(SNUM(conn
))) {
714 return NT_STATUS_EAS_NOT_SUPPORTED
;
718 return NT_STATUS_INVALID_HANDLE
;
721 posix_pathnames
= (fsp
->fsp_name
->flags
& SMB_FILENAME_POSIX_PATH
);
723 status
= refuse_symlink_fsp(fsp
);
724 if (!NT_STATUS_IS_OK(status
)) {
728 status
= check_any_access_fsp(fsp
, FILE_WRITE_EA
);
729 if (!NT_STATUS_IS_OK(status
)) {
733 /* Setting EAs on streams isn't supported. */
734 if (fsp_is_alternate_stream(fsp
)) {
735 return NT_STATUS_INVALID_PARAMETER
;
739 * Filter out invalid Windows EA names - before
740 * we set *any* of them.
743 if (!posix_pathnames
&& ea_list_has_invalid_name(ea_list
)) {
744 return STATUS_INVALID_EA_NAME
;
747 for (;ea_list
; ea_list
= ea_list
->next
) {
749 fstring unix_ea_name
;
752 * Complementing the forward mapping from POSIX EAs to
753 * Windows EAs in get_ea_list_from_fsp(), here we map in the
754 * opposite direction from Windows EAs to the 'user' namespace
755 * of POSIX EAs. Hence, all POSIX EA names the we set here must
756 * start with a 'user.' prefix.
758 fstrcpy(unix_ea_name
, "user.");
759 fstrcat(unix_ea_name
, ea_list
->ea
.name
);
761 canonicalize_ea_name(fsp
, unix_ea_name
);
763 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name
, (unsigned int)ea_list
->ea
.value
.length
));
765 if (samba_private_attr_name(unix_ea_name
)) {
766 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name
));
767 return NT_STATUS_ACCESS_DENIED
;
770 if (ea_list
->ea
.value
.length
== 0) {
771 /* Remove the attribute. */
772 DBG_DEBUG("deleting ea name %s on "
773 "file %s by file descriptor.\n",
774 unix_ea_name
, fsp_str_dbg(fsp
));
775 ret
= SMB_VFS_FREMOVEXATTR(fsp
, unix_ea_name
);
777 /* Removing a non existent attribute always succeeds. */
778 if (ret
== -1 && errno
== ENOATTR
) {
779 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
785 DEBUG(10,("set_ea: setting ea name %s on file "
786 "%s by file descriptor.\n",
787 unix_ea_name
, fsp_str_dbg(fsp
)));
788 ret
= SMB_VFS_FSETXATTR(fsp
, unix_ea_name
,
789 ea_list
->ea
.value
.data
, ea_list
->ea
.value
.length
, 0);
794 if (errno
== ENOTSUP
) {
795 return NT_STATUS_EAS_NOT_SUPPORTED
;
798 return map_nt_error_from_unix(errno
);
805 /****************************************************************************
806 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
807 ****************************************************************************/
809 struct ea_list
*read_ea_list(TALLOC_CTX
*ctx
, const char *pdata
, size_t data_size
)
811 struct ea_list
*ea_list_head
= NULL
;
813 size_t bytes_used
= 0;
815 while (offset
< data_size
) {
816 struct ea_list
*eal
= read_ea_list_entry(ctx
, pdata
+ offset
, data_size
- offset
, &bytes_used
);
822 DLIST_ADD_END(ea_list_head
, eal
);
823 offset
+= bytes_used
;
829 /****************************************************************************
830 Count the total EA size needed.
831 ****************************************************************************/
833 static size_t ea_list_size(struct ea_list
*ealist
)
836 struct ea_list
*listp
;
839 for (listp
= ealist
; listp
; listp
= listp
->next
) {
840 push_ascii_fstring(dos_ea_name
, listp
->ea
.name
);
841 ret
+= 4 + strlen(dos_ea_name
) + 1 + listp
->ea
.value
.length
;
843 /* Add on 4 for total length. */
851 /****************************************************************************
852 Return a union of EA's from a file list and a list of names.
853 The TALLOC context for the two lists *MUST* be identical as we steal
854 memory from one list to add to another. JRA.
855 ****************************************************************************/
857 static struct ea_list
*ea_list_union(struct ea_list
*name_list
, struct ea_list
*file_list
, size_t *total_ea_len
)
859 struct ea_list
*nlistp
, *flistp
;
861 for (nlistp
= name_list
; nlistp
; nlistp
= nlistp
->next
) {
862 for (flistp
= file_list
; flistp
; flistp
= flistp
->next
) {
863 if (strequal(nlistp
->ea
.name
, flistp
->ea
.name
)) {
869 /* Copy the data from this entry. */
870 nlistp
->ea
.flags
= flistp
->ea
.flags
;
871 nlistp
->ea
.value
= flistp
->ea
.value
;
874 nlistp
->ea
.flags
= 0;
875 ZERO_STRUCT(nlistp
->ea
.value
);
879 *total_ea_len
= ea_list_size(name_list
);
883 /****************************************************************************
884 Return the filetype for UNIX extensions.
885 ****************************************************************************/
887 static uint32_t unix_filetype(mode_t mode
)
890 return UNIX_TYPE_FILE
;
891 else if(S_ISDIR(mode
))
892 return UNIX_TYPE_DIR
;
894 else if(S_ISLNK(mode
))
895 return UNIX_TYPE_SYMLINK
;
898 else if(S_ISCHR(mode
))
899 return UNIX_TYPE_CHARDEV
;
902 else if(S_ISBLK(mode
))
903 return UNIX_TYPE_BLKDEV
;
906 else if(S_ISFIFO(mode
))
907 return UNIX_TYPE_FIFO
;
910 else if(S_ISSOCK(mode
))
911 return UNIX_TYPE_SOCKET
;
914 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode
));
915 return UNIX_TYPE_UNKNOWN
;
918 /****************************************************************************
919 Map wire perms onto standard UNIX permissions. Obey share restrictions.
920 ****************************************************************************/
922 NTSTATUS
unix_perms_from_wire(connection_struct
*conn
,
923 const SMB_STRUCT_STAT
*psbuf
,
925 enum perm_type ptype
,
930 if (perms
== SMB_MODE_NO_CHANGE
) {
931 if (!VALID_STAT(*psbuf
)) {
932 return NT_STATUS_INVALID_PARAMETER
;
934 *ret_perms
= psbuf
->st_ex_mode
;
939 ret
= wire_perms_to_unix(perms
);
941 if (ptype
== PERM_NEW_FILE
) {
943 * "create mask"/"force create mode" are
944 * only applied to new files, not existing ones.
946 ret
&= lp_create_mask(SNUM(conn
));
947 /* Add in force bits */
948 ret
|= lp_force_create_mode(SNUM(conn
));
949 } else if (ptype
== PERM_NEW_DIR
) {
951 * "directory mask"/"force directory mode" are
952 * only applied to new directories, not existing ones.
954 ret
&= lp_directory_mask(SNUM(conn
));
955 /* Add in force bits */
956 ret
|= lp_force_directory_mode(SNUM(conn
));
963 /****************************************************************************
964 Get a level dependent lanman2 dir entry.
965 ****************************************************************************/
967 struct smbd_dirptr_lanman2_state
{
968 connection_struct
*conn
;
970 bool check_mangled_names
;
974 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX
*ctx
,
980 struct smbd_dirptr_lanman2_state
*state
=
981 (struct smbd_dirptr_lanman2_state
*)private_data
;
983 char mangled_name
[13]; /* mangled 8.3 name. */
987 /* Mangle fname if it's an illegal name. */
988 if (mangle_must_mangle(dname
, state
->conn
->params
)) {
990 * Slow path - ensure we can push the original name as UCS2. If
991 * not, then just don't return this name.
995 size_t len
= (strlen(dname
) + 2) * 4; /* Allow enough space. */
996 uint8_t *tmp
= talloc_array(talloc_tos(),
1000 status
= srvstr_push(NULL
,
1001 FLAGS2_UNICODE_STRINGS
,
1010 if (!NT_STATUS_IS_OK(status
)) {
1014 ok
= name_to_8_3(dname
, mangled_name
,
1015 true, state
->conn
->params
);
1019 fname
= mangled_name
;
1024 got_match
= mask_match(fname
, mask
,
1025 state
->case_sensitive
);
1027 if(!got_match
&& state
->check_mangled_names
&&
1028 !mangle_is_8_3(fname
, false, state
->conn
->params
)) {
1030 * It turns out that NT matches wildcards against
1031 * both long *and* short names. This may explain some
1032 * of the wildcard weirdness from old DOS clients
1033 * that some people have been seeing.... JRA.
1035 /* Force the mangling into 8.3. */
1036 ok
= name_to_8_3(fname
, mangled_name
,
1037 false, state
->conn
->params
);
1042 got_match
= mask_match(mangled_name
, mask
,
1043 state
->case_sensitive
);
1050 *_fname
= talloc_strdup(ctx
, fname
);
1051 if (*_fname
== NULL
) {
1058 static uint32_t get_dirent_ea_size(uint32_t mode
, files_struct
*fsp
)
1060 if (!(mode
& FILE_ATTRIBUTE_REPARSE_POINT
)) {
1061 unsigned ea_size
= estimate_ea_size(fsp
);
1064 return IO_REPARSE_TAG_DFS
;
1067 static NTSTATUS
smbd_marshall_dir_entry(TALLOC_CTX
*ctx
,
1068 connection_struct
*conn
,
1070 uint32_t info_level
,
1071 struct ea_list
*name_list
,
1072 bool check_mangled_names
,
1073 bool requires_resume_key
,
1076 const struct smb_filename
*smb_fname
,
1077 int space_remaining
,
1083 uint64_t *last_entry_off
)
1085 char *p
, *q
, *pdata
= *ppdata
;
1087 uint64_t file_size
= 0;
1088 uint64_t allocation_size
= 0;
1089 uint64_t file_id
= 0;
1091 struct timespec mdate_ts
= {0};
1092 struct timespec adate_ts
= {0};
1093 struct timespec cdate_ts
= {0};
1094 struct timespec create_date_ts
= {0};
1096 char *last_entry_ptr
;
1101 struct readdir_attr_data
*readdir_attr_data
= NULL
;
1104 if (!(mode
& FILE_ATTRIBUTE_DIRECTORY
)) {
1105 file_size
= get_file_size_stat(&smb_fname
->st
);
1107 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
, NULL
, &smb_fname
->st
);
1110 * Skip SMB_VFS_FREADDIR_ATTR if the directory entry is a symlink or
1113 if (smb_fname
->fsp
!= NULL
&&
1114 !(mode
& FILE_ATTRIBUTE_REPARSE_POINT
)) {
1115 status
= SMB_VFS_FREADDIR_ATTR(smb_fname
->fsp
,
1117 &readdir_attr_data
);
1118 if (!NT_STATUS_IS_OK(status
)) {
1119 if (!NT_STATUS_EQUAL(NT_STATUS_NOT_SUPPORTED
,
1126 file_id
= SMB_VFS_FS_FILE_ID(conn
, &smb_fname
->st
);
1128 mdate_ts
= smb_fname
->st
.st_ex_mtime
;
1129 adate_ts
= smb_fname
->st
.st_ex_atime
;
1130 create_date_ts
= get_create_timespec(conn
, NULL
, smb_fname
);
1131 cdate_ts
= get_change_timespec(conn
, NULL
, smb_fname
);
1133 if (lp_dos_filetime_resolution(SNUM(conn
))) {
1134 dos_filetime_timespec(&create_date_ts
);
1135 dos_filetime_timespec(&mdate_ts
);
1136 dos_filetime_timespec(&adate_ts
);
1137 dos_filetime_timespec(&cdate_ts
);
1140 /* align the record */
1141 SMB_ASSERT(align
>= 1);
1143 off
= (int)PTR_DIFF(pdata
, base_data
);
1144 pad
= (off
+ (align
-1)) & ~(align
-1);
1147 if (pad
&& pad
> space_remaining
) {
1148 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1149 "for padding (wanted %u, had %d)\n",
1152 return STATUS_MORE_ENTRIES
; /* Not finished - just out of space */
1156 /* initialize padding to 0 */
1158 memset(pdata
, 0, pad
);
1160 space_remaining
-= pad
;
1162 DEBUG(10,("smbd_marshall_dir_entry: space_remaining = %d\n",
1172 switch (info_level
) {
1173 case SMB_FIND_INFO_STANDARD
:
1174 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1175 if(requires_resume_key
) {
1179 srv_put_dos_date2_ts(p
, 0, create_date_ts
);
1180 srv_put_dos_date2_ts(p
, 4, adate_ts
);
1181 srv_put_dos_date2_ts(p
, 8, mdate_ts
);
1182 SIVAL(p
,12,(uint32_t)file_size
);
1183 SIVAL(p
,16,(uint32_t)allocation_size
);
1187 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1188 p
+= ucs2_align(base_data
, p
, 0);
1190 status
= srvstr_push(base_data
, flags2
, p
,
1191 fname
, PTR_DIFF(end_data
, p
),
1192 STR_TERMINATE
, &len
);
1193 if (!NT_STATUS_IS_OK(status
)) {
1196 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1198 SCVAL(nameptr
, -1, len
- 2);
1200 SCVAL(nameptr
, -1, 0);
1204 SCVAL(nameptr
, -1, len
- 1);
1206 SCVAL(nameptr
, -1, 0);
1212 case SMB_FIND_EA_SIZE
:
1213 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
1214 if (requires_resume_key
) {
1218 srv_put_dos_date2_ts(p
, 0, create_date_ts
);
1219 srv_put_dos_date2_ts(p
, 4, adate_ts
);
1220 srv_put_dos_date2_ts(p
, 8, mdate_ts
);
1221 SIVAL(p
,12,(uint32_t)file_size
);
1222 SIVAL(p
,16,(uint32_t)allocation_size
);
1225 ea_size
= estimate_ea_size(smb_fname
->fsp
);
1226 SIVAL(p
,22,ea_size
); /* Extended attributes */
1230 status
= srvstr_push(base_data
, flags2
,
1231 p
, fname
, PTR_DIFF(end_data
, p
),
1232 STR_TERMINATE
| STR_NOALIGN
, &len
);
1233 if (!NT_STATUS_IS_OK(status
)) {
1236 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1249 SCVAL(nameptr
,0,len
);
1251 SCVAL(p
,0,0); p
+= 1; /* Extra zero byte ? - why.. */
1254 case SMB_FIND_EA_LIST
:
1256 struct ea_list
*file_list
= NULL
;
1259 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
1261 return NT_STATUS_INVALID_PARAMETER
;
1263 if (requires_resume_key
) {
1267 srv_put_dos_date2_ts(p
, 0, create_date_ts
);
1268 srv_put_dos_date2_ts(p
, 4, adate_ts
);
1269 srv_put_dos_date2_ts(p
, 8, mdate_ts
);
1270 SIVAL(p
,12,(uint32_t)file_size
);
1271 SIVAL(p
,16,(uint32_t)allocation_size
);
1273 p
+= 22; /* p now points to the EA area. */
1275 status
= get_ea_list_from_fsp(ctx
,
1277 &ea_len
, &file_list
);
1278 if (!NT_STATUS_IS_OK(status
)) {
1281 name_list
= ea_list_union(name_list
, file_list
, &ea_len
);
1283 /* We need to determine if this entry will fit in the space available. */
1284 /* Max string size is 255 bytes. */
1285 if (PTR_DIFF(p
+ 255 + ea_len
,pdata
) > space_remaining
) {
1286 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1287 "(wanted %u, had %d)\n",
1288 (unsigned int)PTR_DIFF(p
+ 255 + ea_len
,pdata
),
1290 return STATUS_MORE_ENTRIES
; /* Not finished - just out of space */
1293 /* Push the ea_data followed by the name. */
1294 p
+= fill_ea_buffer(ctx
, p
, space_remaining
, conn
, name_list
);
1296 status
= srvstr_push(base_data
, flags2
,
1297 p
+ 1, fname
, PTR_DIFF(end_data
, p
+1),
1298 STR_TERMINATE
| STR_NOALIGN
, &len
);
1299 if (!NT_STATUS_IS_OK(status
)) {
1302 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1315 SCVAL(nameptr
,0,len
);
1317 SCVAL(p
,0,0); p
+= 1; /* Extra zero byte ? - why.. */
1321 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
1322 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1323 was_8_3
= mangle_is_8_3(fname
, True
, conn
->params
);
1325 SIVAL(p
,0,reskey
); p
+= 4;
1326 put_long_date_full_timespec(conn
->ts_res
,p
,&create_date_ts
); p
+= 8;
1327 put_long_date_full_timespec(conn
->ts_res
,p
,&adate_ts
); p
+= 8;
1328 put_long_date_full_timespec(conn
->ts_res
,p
,&mdate_ts
); p
+= 8;
1329 put_long_date_full_timespec(conn
->ts_res
,p
,&cdate_ts
); p
+= 8;
1330 SOFF_T(p
,0,file_size
); p
+= 8;
1331 SOFF_T(p
,0,allocation_size
); p
+= 8;
1332 SIVAL(p
,0,mode
); p
+= 4;
1333 q
= p
; p
+= 4; /* q is placeholder for name length. */
1334 ea_size
= get_dirent_ea_size(mode
, smb_fname
->fsp
);
1335 SIVAL(p
, 0, ea_size
);
1337 /* Clear the short name buffer. This is
1338 * IMPORTANT as not doing so will trigger
1339 * a Win2k client bug. JRA.
1341 if (!was_8_3
&& check_mangled_names
) {
1342 char mangled_name
[13]; /* mangled 8.3 name. */
1343 if (!name_to_8_3(fname
,mangled_name
,True
,
1345 /* Error - mangle failed ! */
1346 memset(mangled_name
,'\0',12);
1348 mangled_name
[12] = 0;
1349 status
= srvstr_push(base_data
, flags2
,
1350 p
+2, mangled_name
, 24,
1351 STR_UPPER
|STR_UNICODE
, &len
);
1352 if (!NT_STATUS_IS_OK(status
)) {
1356 memset(p
+ 2 + len
,'\0',24 - len
);
1363 status
= srvstr_push(base_data
, flags2
, p
,
1364 fname
, PTR_DIFF(end_data
, p
),
1365 STR_TERMINATE_ASCII
, &len
);
1366 if (!NT_STATUS_IS_OK(status
)) {
1372 len
= PTR_DIFF(p
, pdata
);
1373 pad
= (len
+ (align
-1)) & ~(align
-1);
1375 * offset to the next entry, the caller
1376 * will overwrite it for the last entry
1377 * that's why we always include the padding
1381 * set padding to zero
1384 memset(p
, 0, pad
- len
);
1391 case SMB_FIND_FILE_DIRECTORY_INFO
:
1392 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1394 SIVAL(p
,0,reskey
); p
+= 4;
1395 put_long_date_full_timespec(conn
->ts_res
,p
,&create_date_ts
); p
+= 8;
1396 put_long_date_full_timespec(conn
->ts_res
,p
,&adate_ts
); p
+= 8;
1397 put_long_date_full_timespec(conn
->ts_res
,p
,&mdate_ts
); p
+= 8;
1398 put_long_date_full_timespec(conn
->ts_res
,p
,&cdate_ts
); p
+= 8;
1399 SOFF_T(p
,0,file_size
); p
+= 8;
1400 SOFF_T(p
,0,allocation_size
); p
+= 8;
1401 SIVAL(p
,0,mode
); p
+= 4;
1402 status
= srvstr_push(base_data
, flags2
,
1403 p
+ 4, fname
, PTR_DIFF(end_data
, p
+4),
1404 STR_TERMINATE_ASCII
, &len
);
1405 if (!NT_STATUS_IS_OK(status
)) {
1411 len
= PTR_DIFF(p
, pdata
);
1412 pad
= (len
+ (align
-1)) & ~(align
-1);
1414 * offset to the next entry, the caller
1415 * will overwrite it for the last entry
1416 * that's why we always include the padding
1420 * set padding to zero
1423 memset(p
, 0, pad
- len
);
1430 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
1431 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1433 SIVAL(p
,0,reskey
); p
+= 4;
1434 put_long_date_full_timespec(conn
->ts_res
,p
,&create_date_ts
); p
+= 8;
1435 put_long_date_full_timespec(conn
->ts_res
,p
,&adate_ts
); p
+= 8;
1436 put_long_date_full_timespec(conn
->ts_res
,p
,&mdate_ts
); p
+= 8;
1437 put_long_date_full_timespec(conn
->ts_res
,p
,&cdate_ts
); p
+= 8;
1438 SOFF_T(p
,0,file_size
); p
+= 8;
1439 SOFF_T(p
,0,allocation_size
); p
+= 8;
1440 SIVAL(p
,0,mode
); p
+= 4;
1441 q
= p
; p
+= 4; /* q is placeholder for name length. */
1442 ea_size
= get_dirent_ea_size(mode
, smb_fname
->fsp
);
1443 SIVAL(p
, 0, ea_size
);
1445 status
= srvstr_push(base_data
, flags2
, p
,
1446 fname
, PTR_DIFF(end_data
, p
),
1447 STR_TERMINATE_ASCII
, &len
);
1448 if (!NT_STATUS_IS_OK(status
)) {
1454 len
= PTR_DIFF(p
, pdata
);
1455 pad
= (len
+ (align
-1)) & ~(align
-1);
1457 * offset to the next entry, the caller
1458 * will overwrite it for the last entry
1459 * that's why we always include the padding
1463 * set padding to zero
1466 memset(p
, 0, pad
- len
);
1473 case SMB_FIND_FILE_NAMES_INFO
:
1474 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1476 SIVAL(p
,0,reskey
); p
+= 4;
1478 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1479 acl on a dir (tridge) */
1480 status
= srvstr_push(base_data
, flags2
, p
,
1481 fname
, PTR_DIFF(end_data
, p
),
1482 STR_TERMINATE_ASCII
, &len
);
1483 if (!NT_STATUS_IS_OK(status
)) {
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_FULL_DIRECTORY_INFO
:
1509 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1511 SIVAL(p
,0,reskey
); p
+= 4;
1512 put_long_date_full_timespec(conn
->ts_res
,p
,&create_date_ts
); p
+= 8;
1513 put_long_date_full_timespec(conn
->ts_res
,p
,&adate_ts
); p
+= 8;
1514 put_long_date_full_timespec(conn
->ts_res
,p
,&mdate_ts
); p
+= 8;
1515 put_long_date_full_timespec(conn
->ts_res
,p
,&cdate_ts
); p
+= 8;
1516 SOFF_T(p
,0,file_size
); p
+= 8;
1517 SOFF_T(p
,0,allocation_size
); p
+= 8;
1518 SIVAL(p
,0,mode
); p
+= 4;
1519 q
= p
; p
+= 4; /* q is placeholder for name length. */
1520 ea_size
= get_dirent_ea_size(mode
, smb_fname
->fsp
);
1521 SIVAL(p
, 0, ea_size
);
1523 SIVAL(p
,0,0); p
+= 4; /* Unknown - reserved ? */
1524 SBVAL(p
,0,file_id
); p
+= 8;
1525 status
= srvstr_push(base_data
, flags2
, p
,
1526 fname
, PTR_DIFF(end_data
, p
),
1527 STR_TERMINATE_ASCII
, &len
);
1528 if (!NT_STATUS_IS_OK(status
)) {
1534 len
= PTR_DIFF(p
, pdata
);
1535 pad
= (len
+ (align
-1)) & ~(align
-1);
1537 * offset to the next entry, the caller
1538 * will overwrite it for the last entry
1539 * that's why we always include the padding
1543 * set padding to zero
1546 memset(p
, 0, pad
- len
);
1553 case SMB_FIND_ID_BOTH_DIRECTORY_INFO
:
1554 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1555 was_8_3
= mangle_is_8_3(fname
, True
, conn
->params
);
1557 SIVAL(p
,0,reskey
); p
+= 4;
1558 put_long_date_full_timespec(conn
->ts_res
,p
,&create_date_ts
); p
+= 8;
1559 put_long_date_full_timespec(conn
->ts_res
,p
,&adate_ts
); p
+= 8;
1560 put_long_date_full_timespec(conn
->ts_res
,p
,&mdate_ts
); p
+= 8;
1561 put_long_date_full_timespec(conn
->ts_res
,p
,&cdate_ts
); p
+= 8;
1562 SOFF_T(p
,0,file_size
); p
+= 8;
1563 SOFF_T(p
,0,allocation_size
); p
+= 8;
1564 SIVAL(p
,0,mode
); p
+= 4;
1565 q
= p
; p
+= 4; /* q is placeholder for name length */
1566 if (readdir_attr_data
&&
1567 readdir_attr_data
->type
== RDATTR_AAPL
) {
1569 * OS X specific SMB2 extension negotiated via
1570 * AAPL create context: return max_access in
1573 ea_size
= readdir_attr_data
->attr_data
.aapl
.max_access
;
1575 ea_size
= get_dirent_ea_size(mode
, smb_fname
->fsp
);
1577 SIVAL(p
,0,ea_size
); /* Extended attributes */
1580 if (readdir_attr_data
&&
1581 readdir_attr_data
->type
== RDATTR_AAPL
) {
1583 * OS X specific SMB2 extension negotiated via
1584 * AAPL create context: return resource fork
1585 * length and compressed FinderInfo in
1588 * According to documentation short_name_len
1589 * should be 0, but on the wire behaviour
1590 * shows its set to 24 by clients.
1594 /* Resourefork length */
1595 SBVAL(p
, 2, readdir_attr_data
->attr_data
.aapl
.rfork_size
);
1597 /* Compressed FinderInfo */
1598 memcpy(p
+ 10, &readdir_attr_data
->attr_data
.aapl
.finder_info
, 16);
1599 } else if (!was_8_3
&& check_mangled_names
) {
1600 char mangled_name
[13]; /* mangled 8.3 name. */
1601 if (!name_to_8_3(fname
,mangled_name
,True
,
1603 /* Error - mangle failed ! */
1604 memset(mangled_name
,'\0',12);
1606 mangled_name
[12] = 0;
1607 status
= srvstr_push(base_data
, flags2
,
1608 p
+2, mangled_name
, 24,
1609 STR_UPPER
|STR_UNICODE
, &len
);
1610 if (!NT_STATUS_IS_OK(status
)) {
1615 memset(p
+ 2 + len
,'\0',24 - len
);
1619 /* Clear the short name buffer. This is
1620 * IMPORTANT as not doing so will trigger
1621 * a Win2k client bug. JRA.
1628 if (readdir_attr_data
&&
1629 readdir_attr_data
->type
== RDATTR_AAPL
) {
1631 * OS X specific SMB2 extension negotiated via
1632 * AAPL create context: return UNIX mode in
1635 uint16_t aapl_mode
= (uint16_t)readdir_attr_data
->attr_data
.aapl
.unix_mode
;
1636 SSVAL(p
, 0, aapl_mode
);
1642 SBVAL(p
,0,file_id
); p
+= 8;
1643 status
= srvstr_push(base_data
, flags2
, p
,
1644 fname
, PTR_DIFF(end_data
, p
),
1645 STR_TERMINATE_ASCII
, &len
);
1646 if (!NT_STATUS_IS_OK(status
)) {
1652 len
= PTR_DIFF(p
, pdata
);
1653 pad
= (len
+ (align
-1)) & ~(align
-1);
1655 * offset to the next entry, the caller
1656 * will overwrite it for the last entry
1657 * that's why we always include the padding
1661 * set padding to zero
1664 memset(p
, 0, pad
- len
);
1671 /* CIFS UNIX Extension. */
1673 case SMB_FIND_FILE_UNIX
:
1674 case SMB_FIND_FILE_UNIX_INFO2
:
1676 SIVAL(p
,0,reskey
); p
+= 4; /* Used for continuing search. */
1678 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1680 if (info_level
== SMB_FIND_FILE_UNIX
) {
1681 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
1682 p
= store_file_unix_basic(conn
, p
,
1683 NULL
, &smb_fname
->st
);
1684 status
= srvstr_push(base_data
, flags2
, p
,
1685 fname
, PTR_DIFF(end_data
, p
),
1686 STR_TERMINATE
, &len
);
1687 if (!NT_STATUS_IS_OK(status
)) {
1691 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
1692 p
= store_file_unix_basic_info2(conn
, p
,
1693 NULL
, &smb_fname
->st
);
1696 status
= srvstr_push(base_data
, flags2
, p
, fname
,
1697 PTR_DIFF(end_data
, p
), 0, &len
);
1698 if (!NT_STATUS_IS_OK(status
)) {
1701 SIVAL(nameptr
, 0, len
);
1706 len
= PTR_DIFF(p
, pdata
);
1707 pad
= (len
+ (align
-1)) & ~(align
-1);
1709 * offset to the next entry, the caller
1710 * will overwrite it for the last entry
1711 * that's why we always include the padding
1715 * set padding to zero
1718 memset(p
, 0, pad
- len
);
1723 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1727 /* SMB2 UNIX Extension. */
1729 case SMB2_FILE_POSIX_INFORMATION
:
1731 struct smb3_file_posix_information info
= {};
1732 uint8_t buf
[sizeof(info
)];
1733 struct ndr_push ndr
= {
1735 .alloc_size
= sizeof(buf
),
1736 .fixed_buf_size
= true,
1738 enum ndr_err_code ndr_err
;
1741 SIVAL(p
,0,reskey
); p
+= 4;
1743 DBG_DEBUG("SMB2_FILE_POSIX_INFORMATION\n");
1745 if (!conn_using_smb2(conn
->sconn
)) {
1746 return NT_STATUS_INVALID_LEVEL
;
1749 smb3_file_posix_information_init(
1750 conn
, &smb_fname
->st
, 0, mode
, &info
);
1752 ndr_err
= ndr_push_smb3_file_posix_information(
1753 &ndr
, NDR_SCALARS
|NDR_BUFFERS
, &info
);
1754 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
1755 return NT_STATUS_INSUFFICIENT_RESOURCES
;
1758 memcpy(p
, buf
, ndr
.offset
);
1763 status
= srvstr_push(base_data
, flags2
, p
, fname
,
1764 PTR_DIFF(end_data
, p
), 0, &len
);
1765 if (!NT_STATUS_IS_OK(status
)) {
1768 SIVAL(nameptr
, 0, len
);
1772 len
= PTR_DIFF(p
, pdata
);
1773 pad
= (len
+ (align
-1)) & ~(align
-1);
1775 * offset to the next entry, the caller
1776 * will overwrite it for the last entry
1777 * that's why we always include the padding
1784 return NT_STATUS_INVALID_LEVEL
;
1787 if (PTR_DIFF(p
,pdata
) > space_remaining
) {
1788 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1789 "(wanted %u, had %d)\n",
1790 (unsigned int)PTR_DIFF(p
,pdata
),
1792 return STATUS_MORE_ENTRIES
; /* Not finished - just out of space */
1795 /* Setup the last entry pointer, as an offset from base_data */
1796 *last_entry_off
= PTR_DIFF(last_entry_ptr
,base_data
);
1797 /* Advance the data pointer to the next slot */
1800 return NT_STATUS_OK
;
1803 NTSTATUS
smbd_dirptr_lanman2_entry(TALLOC_CTX
*ctx
,
1804 connection_struct
*conn
,
1805 struct dptr_struct
*dirptr
,
1807 const char *path_mask
,
1810 int requires_resume_key
,
1819 int space_remaining
,
1820 struct smb_filename
**_smb_fname
,
1821 int *_last_entry_off
,
1822 struct ea_list
*name_list
,
1823 struct file_id
*file_id
)
1826 const char *mask
= NULL
;
1829 struct smb_filename
*smb_fname
= NULL
;
1830 struct smbd_dirptr_lanman2_state state
;
1832 uint64_t last_entry_off
= 0;
1834 enum mangled_names_options mangled_names
;
1835 bool marshall_with_83_names
;
1837 mangled_names
= lp_mangled_names(conn
->params
);
1841 state
.info_level
= info_level
;
1842 if (mangled_names
!= MANGLED_NAMES_NO
) {
1843 state
.check_mangled_names
= true;
1845 state
.case_sensitive
= dptr_case_sensitive(dirptr
);
1847 p
= strrchr_m(path_mask
,'/');
1858 ok
= smbd_dirptr_get_entry(ctx
,
1865 smbd_dirptr_lanman2_match_fn
,
1871 return NT_STATUS_END_OF_FILE
;
1874 marshall_with_83_names
= (mangled_names
== MANGLED_NAMES_YES
);
1876 status
= smbd_marshall_dir_entry(ctx
,
1881 marshall_with_83_names
,
1882 requires_resume_key
,
1893 if (NT_STATUS_EQUAL(status
, NT_STATUS_ILLEGAL_CHARACTER
)) {
1894 DEBUG(1,("Conversion error: illegal character: %s\n",
1895 smb_fname_str_dbg(smb_fname
)));
1898 if (file_id
!= NULL
) {
1899 *file_id
= vfs_file_id_from_sbuf(conn
, &smb_fname
->st
);
1902 if (NT_STATUS_EQUAL(status
, STATUS_MORE_ENTRIES
)) {
1903 smbd_dirptr_push_overflow(dirptr
, &fname
, &smb_fname
, mode
);
1906 if (!NT_STATUS_IS_OK(status
)) {
1907 TALLOC_FREE(smb_fname
);
1912 smbd_dirptr_set_last_name_sent(dirptr
, &smb_fname
->base_name
);
1914 if (_smb_fname
!= NULL
) {
1916 * smb_fname is already talloc'ed off ctx.
1917 * We just need to make sure we don't return
1918 * any stream_name, and replace base_name
1919 * with fname in case base_name got mangled.
1920 * This allows us to preserve any smb_fname->fsp
1921 * for asynchronous handle lookups.
1923 TALLOC_FREE(smb_fname
->stream_name
);
1926 * smbd_dirptr_set_last_name_sent() above consumed
1929 smb_fname
->base_name
= talloc_strdup(smb_fname
, fname
);
1931 if (smb_fname
->base_name
== NULL
) {
1932 TALLOC_FREE(smb_fname
);
1934 return NT_STATUS_NO_MEMORY
;
1936 *_smb_fname
= smb_fname
;
1938 TALLOC_FREE(smb_fname
);
1942 *_last_entry_off
= last_entry_off
;
1943 return NT_STATUS_OK
;
1946 unsigned char *create_volume_objectid(connection_struct
*conn
, unsigned char objid
[16])
1948 const struct loadparm_substitution
*lp_sub
=
1949 loadparm_s3_global_substitution();
1951 E_md4hash(lp_servicename(talloc_tos(), lp_sub
, SNUM(conn
)),objid
);
1955 static void samba_extended_info_version(struct smb_extended_info
*extended_info
)
1957 SMB_ASSERT(extended_info
!= NULL
);
1959 extended_info
->samba_magic
= SAMBA_EXTENDED_INFO_MAGIC
;
1960 extended_info
->samba_version
= ((SAMBA_VERSION_MAJOR
& 0xff) << 24)
1961 | ((SAMBA_VERSION_MINOR
& 0xff) << 16)
1962 | ((SAMBA_VERSION_RELEASE
& 0xff) << 8);
1963 #ifdef SAMBA_VERSION_REVISION
1964 extended_info
->samba_version
|= (tolower(*SAMBA_VERSION_REVISION
) - 'a' + 1) & 0xff;
1966 extended_info
->samba_subversion
= 0;
1967 #ifdef SAMBA_VERSION_RC_RELEASE
1968 extended_info
->samba_subversion
|= (SAMBA_VERSION_RC_RELEASE
& 0xff) << 24;
1970 #ifdef SAMBA_VERSION_PRE_RELEASE
1971 extended_info
->samba_subversion
|= (SAMBA_VERSION_PRE_RELEASE
& 0xff) << 16;
1974 #ifdef SAMBA_VERSION_VENDOR_PATCH
1975 extended_info
->samba_subversion
|= (SAMBA_VERSION_VENDOR_PATCH
& 0xffff);
1977 extended_info
->samba_gitcommitdate
= 0;
1978 #ifdef SAMBA_VERSION_COMMIT_TIME
1979 unix_to_nt_time(&extended_info
->samba_gitcommitdate
, SAMBA_VERSION_COMMIT_TIME
);
1982 memset(extended_info
->samba_version_string
, 0,
1983 sizeof(extended_info
->samba_version_string
));
1985 snprintf (extended_info
->samba_version_string
,
1986 sizeof(extended_info
->samba_version_string
),
1987 "%s", samba_version_string());
1990 static bool fsinfo_unix_valid_level(connection_struct
*conn
,
1991 struct files_struct
*fsp
,
1992 uint16_t info_level
)
1994 if (conn_using_smb2(conn
->sconn
) &&
1995 fsp
->posix_flags
== FSP_POSIX_FLAGS_OPEN
&&
1996 info_level
== SMB2_FS_POSIX_INFORMATION_INTERNAL
)
2000 #if defined(SMB1SERVER)
2001 if (lp_smb1_unix_extensions() &&
2002 info_level
== SMB_QUERY_POSIX_FS_INFO
) {
2010 * fsp is only valid for SMB2.
2012 NTSTATUS
smbd_do_qfsinfo(struct smbXsrv_connection
*xconn
,
2013 connection_struct
*conn
,
2014 TALLOC_CTX
*mem_ctx
,
2015 uint16_t info_level
,
2017 unsigned int max_data_bytes
,
2018 size_t *fixed_portion
,
2019 struct files_struct
*fsp
,
2020 struct smb_filename
*fname
,
2024 const struct loadparm_substitution
*lp_sub
=
2025 loadparm_s3_global_substitution();
2026 char *pdata
, *end_data
;
2029 const char *vname
= volume_label(talloc_tos(), SNUM(conn
));
2030 int snum
= SNUM(conn
);
2031 const char *fstype
= lp_fstype(SNUM(conn
));
2032 const char *filename
= NULL
;
2033 const uint64_t bytes_per_sector
= 512;
2034 uint32_t additional_flags
= 0;
2035 struct smb_filename smb_fname
;
2037 NTSTATUS status
= NT_STATUS_OK
;
2041 if (fname
== NULL
|| fname
->base_name
== NULL
) {
2044 filename
= fname
->base_name
;
2048 if (info_level
!= SMB_QUERY_CIFS_UNIX_INFO
) {
2049 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
2050 "info level (0x%x) on IPC$.\n",
2051 (unsigned int)info_level
));
2052 return NT_STATUS_ACCESS_DENIED
;
2056 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level
));
2058 smb_fname
= (struct smb_filename
) {
2059 .base_name
= discard_const_p(char, filename
),
2060 .flags
= fname
? fname
->flags
: 0,
2061 .twrp
= fname
? fname
->twrp
: 0,
2064 if(info_level
!= SMB_FS_QUOTA_INFORMATION
2065 && SMB_VFS_STAT(conn
, &smb_fname
) != 0) {
2066 DEBUG(2,("stat of . failed (%s)\n", strerror(errno
)));
2067 return map_nt_error_from_unix(errno
);
2072 if (max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
< max_data_bytes
) {
2073 return NT_STATUS_INVALID_PARAMETER
;
2076 *ppdata
= (char *)SMB_REALLOC(
2077 *ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
2078 if (*ppdata
== NULL
) {
2079 return NT_STATUS_NO_MEMORY
;
2083 memset((char *)pdata
,'\0',max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
2084 end_data
= pdata
+ max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
- 1;
2088 switch (info_level
) {
2089 case SMB_INFO_ALLOCATION
:
2091 uint64_t dfree
,dsize
,bsize
,block_size
,sectors_per_unit
;
2093 df_ret
= get_dfree_info(conn
, &smb_fname
, &bsize
,
2095 if (df_ret
== (uint64_t)-1) {
2096 return map_nt_error_from_unix(errno
);
2099 block_size
= lp_block_size(snum
);
2100 if (bsize
< block_size
) {
2101 uint64_t factor
= block_size
/bsize
;
2106 if (bsize
> block_size
) {
2107 uint64_t factor
= bsize
/block_size
;
2112 sectors_per_unit
= bsize
/bytes_per_sector
;
2114 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2115 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st
.st_ex_dev
, (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
2116 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
2119 * For large drives, return max values and not modulo.
2121 dsize
= MIN(dsize
, UINT32_MAX
);
2122 dfree
= MIN(dfree
, UINT32_MAX
);
2124 SIVAL(pdata
,l1_idFileSystem
,st
.st_ex_dev
);
2125 SIVAL(pdata
,l1_cSectorUnit
,sectors_per_unit
);
2126 SIVAL(pdata
,l1_cUnit
,dsize
);
2127 SIVAL(pdata
,l1_cUnitAvail
,dfree
);
2128 SSVAL(pdata
,l1_cbSector
,bytes_per_sector
);
2132 case SMB_INFO_VOLUME
:
2133 /* Return volume name */
2135 * Add volume serial number - hash of a combination of
2136 * the called hostname and the service name.
2138 serial
= generate_volume_serial_number(lp_sub
, snum
);
2139 SIVAL(pdata
,0,serial
);
2141 * Win2k3 and previous mess this up by sending a name length
2142 * one byte short. I believe only older clients (OS/2 Win9x) use
2143 * this call so try fixing this by adding a terminating null to
2144 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2146 status
= srvstr_push(
2148 pdata
+l2_vol_szVolLabel
, vname
,
2149 PTR_DIFF(end_data
, pdata
+l2_vol_szVolLabel
),
2150 STR_NOALIGN
|STR_TERMINATE
, &len
);
2151 if (!NT_STATUS_IS_OK(status
)) {
2154 SCVAL(pdata
,l2_vol_cch
,len
);
2155 data_len
= l2_vol_szVolLabel
+ len
;
2156 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %u, "
2157 "name = %s serial = 0x%04"PRIx32
"\n",
2158 (unsigned)convert_timespec_to_time_t(st
.st_ex_ctime
),
2159 (unsigned)len
, vname
, serial
));
2162 case SMB_QUERY_FS_ATTRIBUTE_INFO
:
2163 case SMB_FS_ATTRIBUTE_INFORMATION
:
2165 additional_flags
= 0;
2166 #if defined(HAVE_SYS_QUOTAS)
2167 additional_flags
|= FILE_VOLUME_QUOTAS
;
2170 if(lp_nt_acl_support(SNUM(conn
))) {
2171 additional_flags
|= FILE_PERSISTENT_ACLS
;
2174 /* Capabilities are filled in at connection time through STATVFS call */
2175 additional_flags
|= conn
->fs_capabilities
;
2176 additional_flags
|= lp_parm_int(conn
->params
->service
,
2177 "share", "fake_fscaps",
2180 SIVAL(pdata
,0,FILE_CASE_PRESERVED_NAMES
|FILE_CASE_SENSITIVE_SEARCH
|
2181 FILE_SUPPORTS_OBJECT_IDS
|FILE_UNICODE_ON_DISK
|
2182 additional_flags
); /* FS ATTRIBUTES */
2184 SIVAL(pdata
,4,255); /* Max filename component length */
2185 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2186 and will think we can't do long filenames */
2187 status
= srvstr_push(pdata
, flags2
, pdata
+12, fstype
,
2188 PTR_DIFF(end_data
, pdata
+12),
2190 if (!NT_STATUS_IS_OK(status
)) {
2194 data_len
= 12 + len
;
2195 if (max_data_bytes
>= 16 && data_len
> max_data_bytes
) {
2196 /* the client only requested a portion of the
2198 data_len
= max_data_bytes
;
2199 status
= STATUS_BUFFER_OVERFLOW
;
2201 *fixed_portion
= 16;
2204 case SMB_QUERY_FS_LABEL_INFO
:
2205 case SMB_FS_LABEL_INFORMATION
:
2206 status
= srvstr_push(pdata
, flags2
, pdata
+4, vname
,
2207 PTR_DIFF(end_data
, pdata
+4), 0, &len
);
2208 if (!NT_STATUS_IS_OK(status
)) {
2215 case SMB_QUERY_FS_VOLUME_INFO
:
2216 case SMB_FS_VOLUME_INFORMATION
:
2217 put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER
,
2218 pdata
, &st
.st_ex_btime
);
2220 * Add volume serial number - hash of a combination of
2221 * the called hostname and the service name.
2223 serial
= generate_volume_serial_number(lp_sub
, snum
);
2224 SIVAL(pdata
,8,serial
);
2226 /* Max label len is 32 characters. */
2227 status
= srvstr_push(pdata
, flags2
, pdata
+18, vname
,
2228 PTR_DIFF(end_data
, pdata
+18),
2230 if (!NT_STATUS_IS_OK(status
)) {
2233 SIVAL(pdata
,12,len
);
2236 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO "
2237 "namelen = %d, vol=%s serv=%s "
2238 "serial=0x%04"PRIx32
"\n",
2239 (int)strlen(vname
),vname
,
2240 lp_servicename(talloc_tos(), lp_sub
, snum
),
2242 if (max_data_bytes
>= 24 && data_len
> max_data_bytes
) {
2243 /* the client only requested a portion of the
2245 data_len
= max_data_bytes
;
2246 status
= STATUS_BUFFER_OVERFLOW
;
2248 *fixed_portion
= 24;
2251 case SMB_QUERY_FS_SIZE_INFO
:
2252 case SMB_FS_SIZE_INFORMATION
:
2254 uint64_t dfree
,dsize
,bsize
,block_size
,sectors_per_unit
;
2256 df_ret
= get_dfree_info(conn
, &smb_fname
, &bsize
,
2258 if (df_ret
== (uint64_t)-1) {
2259 return map_nt_error_from_unix(errno
);
2261 block_size
= lp_block_size(snum
);
2262 if (bsize
< block_size
) {
2263 uint64_t factor
= block_size
/bsize
;
2268 if (bsize
> block_size
) {
2269 uint64_t factor
= bsize
/block_size
;
2274 sectors_per_unit
= bsize
/bytes_per_sector
;
2275 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2276 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
2277 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
2278 SBIG_UINT(pdata
,0,dsize
);
2279 SBIG_UINT(pdata
,8,dfree
);
2280 SIVAL(pdata
,16,sectors_per_unit
);
2281 SIVAL(pdata
,20,bytes_per_sector
);
2282 *fixed_portion
= 24;
2286 case SMB_FS_FULL_SIZE_INFORMATION
:
2288 uint64_t dfree
,dsize
,bsize
,block_size
,sectors_per_unit
;
2290 df_ret
= get_dfree_info(conn
, &smb_fname
, &bsize
,
2292 if (df_ret
== (uint64_t)-1) {
2293 return map_nt_error_from_unix(errno
);
2295 block_size
= lp_block_size(snum
);
2296 if (bsize
< block_size
) {
2297 uint64_t factor
= block_size
/bsize
;
2302 if (bsize
> block_size
) {
2303 uint64_t factor
= bsize
/block_size
;
2308 sectors_per_unit
= bsize
/bytes_per_sector
;
2309 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2310 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
2311 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
2312 SBIG_UINT(pdata
,0,dsize
); /* Total Allocation units. */
2313 SBIG_UINT(pdata
,8,dfree
); /* Caller available allocation units. */
2314 SBIG_UINT(pdata
,16,dfree
); /* Actual available allocation units. */
2315 SIVAL(pdata
,24,sectors_per_unit
); /* Sectors per allocation unit. */
2316 SIVAL(pdata
,28,bytes_per_sector
); /* Bytes per sector. */
2317 *fixed_portion
= 32;
2321 case SMB_QUERY_FS_DEVICE_INFO
:
2322 case SMB_FS_DEVICE_INFORMATION
:
2324 uint32_t characteristics
= FILE_DEVICE_IS_MOUNTED
;
2326 if (!CAN_WRITE(conn
)) {
2327 characteristics
|= FILE_READ_ONLY_DEVICE
;
2330 SIVAL(pdata
,0,FILE_DEVICE_DISK
); /* dev type */
2331 SIVAL(pdata
,4,characteristics
);
2336 #ifdef HAVE_SYS_QUOTAS
2337 case SMB_FS_QUOTA_INFORMATION
:
2339 * what we have to send --metze:
2341 * Unknown1: 24 NULL bytes
2342 * Soft Quota Threshold: 8 bytes seems like uint64_t or so
2343 * Hard Quota Limit: 8 bytes seems like uint64_t or so
2344 * Quota Flags: 2 byte :
2345 * Unknown3: 6 NULL bytes
2349 * details for Quota Flags:
2351 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2352 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2353 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2354 * 0x0001 Enable Quotas: enable quota for this fs
2358 /* we need to fake up a fsp here,
2359 * because its not send in this call
2361 files_struct tmpfsp
;
2362 SMB_NTQUOTA_STRUCT quotas
;
2364 ZERO_STRUCT(tmpfsp
);
2365 ZERO_STRUCT(quotas
);
2368 tmpfsp
.fnum
= FNUM_FIELD_INVALID
;
2371 if (get_current_uid(conn
) != 0) {
2372 DEBUG(0,("get_user_quota: access_denied "
2373 "service [%s] user [%s]\n",
2374 lp_servicename(talloc_tos(), lp_sub
, SNUM(conn
)),
2375 conn
->session_info
->unix_info
->unix_name
));
2376 return NT_STATUS_ACCESS_DENIED
;
2379 status
= vfs_get_ntquota(&tmpfsp
, SMB_USER_FS_QUOTA_TYPE
,
2381 if (!NT_STATUS_IS_OK(status
)) {
2382 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), lp_sub
, SNUM(conn
))));
2388 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
2389 lp_servicename(talloc_tos(), lp_sub
, SNUM(conn
))));
2391 /* Unknown1 24 NULL bytes*/
2392 SBIG_UINT(pdata
,0,(uint64_t)0);
2393 SBIG_UINT(pdata
,8,(uint64_t)0);
2394 SBIG_UINT(pdata
,16,(uint64_t)0);
2396 /* Default Soft Quota 8 bytes */
2397 SBIG_UINT(pdata
,24,quotas
.softlim
);
2399 /* Default Hard Quota 8 bytes */
2400 SBIG_UINT(pdata
,32,quotas
.hardlim
);
2402 /* Quota flag 2 bytes */
2403 SSVAL(pdata
,40,quotas
.qflags
);
2405 /* Unknown3 6 NULL bytes */
2411 #endif /* HAVE_SYS_QUOTAS */
2412 case SMB_FS_OBJECTID_INFORMATION
:
2414 unsigned char objid
[16];
2415 struct smb_extended_info extended_info
;
2416 memcpy(pdata
,create_volume_objectid(conn
, objid
),16);
2417 samba_extended_info_version (&extended_info
);
2418 SIVAL(pdata
,16,extended_info
.samba_magic
);
2419 SIVAL(pdata
,20,extended_info
.samba_version
);
2420 SIVAL(pdata
,24,extended_info
.samba_subversion
);
2421 SBIG_UINT(pdata
,28,extended_info
.samba_gitcommitdate
);
2422 memcpy(pdata
+36,extended_info
.samba_version_string
,28);
2427 case SMB_FS_SECTOR_SIZE_INFORMATION
:
2431 * These values match a physical Windows Server 2012
2432 * share backed by NTFS atop spinning rust.
2434 DEBUG(5, ("SMB_FS_SECTOR_SIZE_INFORMATION:"));
2435 /* logical_bytes_per_sector */
2436 SIVAL(pdata
, 0, bytes_per_sector
);
2437 /* phys_bytes_per_sector_atomic */
2438 SIVAL(pdata
, 4, bytes_per_sector
);
2439 /* phys_bytes_per_sector_perf */
2440 SIVAL(pdata
, 8, bytes_per_sector
);
2441 /* fs_effective_phys_bytes_per_sector_atomic */
2442 SIVAL(pdata
, 12, bytes_per_sector
);
2444 SIVAL(pdata
, 16, SSINFO_FLAGS_ALIGNED_DEVICE
2445 | SSINFO_FLAGS_PARTITION_ALIGNED_ON_DEVICE
);
2446 /* byte_off_sector_align */
2447 SIVAL(pdata
, 20, 0);
2448 /* byte_off_partition_align */
2449 SIVAL(pdata
, 24, 0);
2450 *fixed_portion
= 28;
2455 #if defined(WITH_SMB1SERVER)
2457 * Query the version and capabilities of the CIFS UNIX extensions
2461 case SMB_QUERY_CIFS_UNIX_INFO
:
2463 bool large_write
= lp_min_receive_file_size() &&
2464 !smb1_srv_is_signing_active(xconn
);
2465 bool large_read
= !smb1_srv_is_signing_active(xconn
);
2466 int encrypt_caps
= 0;
2468 if (!lp_smb1_unix_extensions()) {
2469 return NT_STATUS_INVALID_LEVEL
;
2472 switch (conn
->encrypt_level
) {
2473 case SMB_SIGNING_OFF
:
2476 case SMB_SIGNING_DESIRED
:
2477 case SMB_SIGNING_IF_REQUIRED
:
2478 case SMB_SIGNING_DEFAULT
:
2479 encrypt_caps
= CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP
;
2481 case SMB_SIGNING_REQUIRED
:
2482 encrypt_caps
= CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP
|
2483 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP
;
2484 large_write
= false;
2490 SSVAL(pdata
,0,CIFS_UNIX_MAJOR_VERSION
);
2491 SSVAL(pdata
,2,CIFS_UNIX_MINOR_VERSION
);
2493 /* We have POSIX ACLs, pathname, encryption,
2494 * large read/write, and locking capability. */
2496 SBIG_UINT(pdata
,4,((uint64_t)(
2497 CIFS_UNIX_POSIX_ACLS_CAP
|
2498 CIFS_UNIX_POSIX_PATHNAMES_CAP
|
2499 CIFS_UNIX_FCNTL_LOCKS_CAP
|
2500 CIFS_UNIX_EXTATTR_CAP
|
2501 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP
|
2503 (large_read
? CIFS_UNIX_LARGE_READ_CAP
: 0) |
2505 CIFS_UNIX_LARGE_WRITE_CAP
: 0))));
2510 case SMB_QUERY_POSIX_FS_INFO
:
2511 case SMB2_FS_POSIX_INFORMATION_INTERNAL
:
2514 struct vfs_statvfs_struct svfs
;
2516 if (!fsinfo_unix_valid_level(conn
, fsp
, info_level
)) {
2517 return NT_STATUS_INVALID_LEVEL
;
2520 rc
= SMB_VFS_STATVFS(conn
, &smb_fname
, &svfs
);
2524 SIVAL(pdata
,0,svfs
.OptimalTransferSize
);
2525 SIVAL(pdata
,4,svfs
.BlockSize
);
2526 SBIG_UINT(pdata
,8,svfs
.TotalBlocks
);
2527 SBIG_UINT(pdata
,16,svfs
.BlocksAvail
);
2528 SBIG_UINT(pdata
,24,svfs
.UserBlocksAvail
);
2529 SBIG_UINT(pdata
,32,svfs
.TotalFileNodes
);
2530 SBIG_UINT(pdata
,40,svfs
.FreeFileNodes
);
2531 SBIG_UINT(pdata
,48,svfs
.FsIdentifier
);
2532 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO successful\n"));
2534 } else if (rc
== EOPNOTSUPP
) {
2535 return NT_STATUS_INVALID_LEVEL
;
2536 #endif /* EOPNOTSUPP */
2538 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(talloc_tos(), lp_sub
, SNUM(conn
))));
2539 return NT_STATUS_DOS(ERRSRV
, ERRerror
);
2544 case SMB_QUERY_POSIX_WHOAMI
:
2550 if (!lp_smb1_unix_extensions()) {
2551 return NT_STATUS_INVALID_LEVEL
;
2554 if (max_data_bytes
< 40) {
2555 return NT_STATUS_BUFFER_TOO_SMALL
;
2558 if (security_session_user_level(conn
->session_info
, NULL
) < SECURITY_USER
) {
2559 flags
|= SMB_WHOAMI_GUEST
;
2562 /* NOTE: 8 bytes for UID/GID, irrespective of native
2563 * platform size. This matches
2564 * SMB_QUERY_FILE_UNIX_BASIC and friends.
2566 data_len
= 4 /* flags */
2573 + 4 /* pad/reserved */
2574 + (conn
->session_info
->unix_token
->ngroups
* 8)
2576 + (conn
->session_info
->security_token
->num_sids
*
2580 SIVAL(pdata
, 0, flags
);
2581 SIVAL(pdata
, 4, SMB_WHOAMI_MASK
);
2583 (uint64_t)conn
->session_info
->unix_token
->uid
);
2584 SBIG_UINT(pdata
, 16,
2585 (uint64_t)conn
->session_info
->unix_token
->gid
);
2588 if (data_len
>= max_data_bytes
) {
2589 /* Potential overflow, skip the GIDs and SIDs. */
2591 SIVAL(pdata
, 24, 0); /* num_groups */
2592 SIVAL(pdata
, 28, 0); /* num_sids */
2593 SIVAL(pdata
, 32, 0); /* num_sid_bytes */
2594 SIVAL(pdata
, 36, 0); /* reserved */
2600 SIVAL(pdata
, 24, conn
->session_info
->unix_token
->ngroups
);
2601 SIVAL(pdata
, 28, conn
->session_info
->security_token
->num_sids
);
2603 /* We walk the SID list twice, but this call is fairly
2604 * infrequent, and I don't expect that it's performance
2605 * sensitive -- jpeach
2607 for (i
= 0, sid_bytes
= 0;
2608 i
< conn
->session_info
->security_token
->num_sids
; ++i
) {
2609 sid_bytes
+= ndr_size_dom_sid(
2610 &conn
->session_info
->security_token
->sids
[i
],
2614 /* SID list byte count */
2615 SIVAL(pdata
, 32, sid_bytes
);
2617 /* 4 bytes pad/reserved - must be zero */
2618 SIVAL(pdata
, 36, 0);
2622 for (i
= 0; i
< conn
->session_info
->unix_token
->ngroups
; ++i
) {
2623 SBIG_UINT(pdata
, data_len
,
2624 (uint64_t)conn
->session_info
->unix_token
->groups
[i
]);
2630 i
< conn
->session_info
->security_token
->num_sids
; ++i
) {
2631 int sid_len
= ndr_size_dom_sid(
2632 &conn
->session_info
->security_token
->sids
[i
],
2635 sid_linearize((uint8_t *)(pdata
+ data_len
),
2637 &conn
->session_info
->security_token
->sids
[i
]);
2638 data_len
+= sid_len
;
2644 case SMB_MAC_QUERY_FS_INFO
:
2646 * Thursby MAC extension... ONLY on NTFS filesystems
2647 * once we do streams then we don't need this
2649 if (strequal(lp_fstype(SNUM(conn
)),"NTFS")) {
2651 SIVAL(pdata
,84,0x100); /* Don't support mac... */
2657 return NT_STATUS_INVALID_LEVEL
;
2660 *ret_data_len
= data_len
;
2664 NTSTATUS
smb_set_fsquota(connection_struct
*conn
,
2665 struct smb_request
*req
,
2667 const DATA_BLOB
*qdata
)
2669 const struct loadparm_substitution
*lp_sub
=
2670 loadparm_s3_global_substitution();
2672 SMB_NTQUOTA_STRUCT quotas
;
2674 ZERO_STRUCT(quotas
);
2677 if ((get_current_uid(conn
) != 0) || !CAN_WRITE(conn
)) {
2678 DBG_NOTICE("access_denied service [%s] user [%s]\n",
2679 lp_servicename(talloc_tos(), lp_sub
, SNUM(conn
)),
2680 conn
->session_info
->unix_info
->unix_name
);
2681 return NT_STATUS_ACCESS_DENIED
;
2684 if (!check_fsp_ntquota_handle(conn
, req
,
2686 DBG_WARNING("no valid QUOTA HANDLE\n");
2687 return NT_STATUS_INVALID_HANDLE
;
2690 /* note: normally there're 48 bytes,
2691 * but we didn't use the last 6 bytes for now
2694 if (qdata
->length
< 42) {
2695 DBG_ERR("requires total_data(%zu) >= 42 bytes!\n",
2697 return NT_STATUS_INVALID_PARAMETER
;
2700 /* unknown_1 24 NULL bytes in pdata*/
2702 /* the soft quotas 8 bytes (uint64_t)*/
2703 quotas
.softlim
= BVAL(qdata
->data
,24);
2705 /* the hard quotas 8 bytes (uint64_t)*/
2706 quotas
.hardlim
= BVAL(qdata
->data
,32);
2708 /* quota_flags 2 bytes **/
2709 quotas
.qflags
= SVAL(qdata
->data
,40);
2711 /* unknown_2 6 NULL bytes follow*/
2713 /* now set the quotas */
2714 if (vfs_set_ntquota(fsp
, SMB_USER_FS_QUOTA_TYPE
, NULL
, "as
)!=0) {
2715 DBG_WARNING("vfs_set_ntquota() failed for service [%s]\n",
2716 lp_servicename(talloc_tos(), lp_sub
, SNUM(conn
)));
2717 status
= map_nt_error_from_unix(errno
);
2719 status
= NT_STATUS_OK
;
2724 NTSTATUS
smbd_do_setfsinfo(connection_struct
*conn
,
2725 struct smb_request
*req
,
2726 TALLOC_CTX
*mem_ctx
,
2727 uint16_t info_level
,
2729 const DATA_BLOB
*pdata
)
2731 switch (info_level
) {
2732 case SMB_FS_QUOTA_INFORMATION
:
2734 return smb_set_fsquota(conn
,
2743 return NT_STATUS_INVALID_LEVEL
;
2746 /****************************************************************************
2747 Store the FILE_UNIX_BASIC info.
2748 ****************************************************************************/
2750 char *store_file_unix_basic(connection_struct
*conn
,
2753 const SMB_STRUCT_STAT
*psbuf
)
2757 DBG_DEBUG("SMB_QUERY_FILE_UNIX_BASIC\n");
2758 DBG_NOTICE("st_mode=%o\n", (int)psbuf
->st_ex_mode
);
2760 SOFF_T(pdata
,0,get_file_size_stat(psbuf
)); /* File size 64 Bit */
2763 SOFF_T(pdata
,0,SMB_VFS_GET_ALLOC_SIZE(conn
,fsp
,psbuf
)); /* Number of bytes used on disk - 64 Bit */
2766 put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER
, pdata
, &psbuf
->st_ex_ctime
); /* Change Time 64 Bit */
2767 put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER
,pdata
+8, &psbuf
->st_ex_atime
); /* Last access time 64 Bit */
2768 put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER
, pdata
+16, &psbuf
->st_ex_mtime
); /* Last modification time 64 Bit */
2771 SIVAL(pdata
,0,psbuf
->st_ex_uid
); /* user id for the owner */
2775 SIVAL(pdata
,0,psbuf
->st_ex_gid
); /* group id of owner */
2779 SIVAL(pdata
,0,unix_filetype(psbuf
->st_ex_mode
));
2782 if (S_ISBLK(psbuf
->st_ex_mode
) || S_ISCHR(psbuf
->st_ex_mode
)) {
2783 devno
= psbuf
->st_ex_rdev
;
2785 devno
= psbuf
->st_ex_dev
;
2788 SIVAL(pdata
,0,unix_dev_major(devno
)); /* Major device number if type is device */
2792 SIVAL(pdata
,0,unix_dev_minor(devno
)); /* Minor device number if type is device */
2796 SINO_T_VAL(pdata
, 0, psbuf
->st_ex_ino
); /* inode number */
2799 SIVAL(pdata
,0, unix_perms_to_wire(psbuf
->st_ex_mode
)); /* Standard UNIX file permissions */
2803 SIVAL(pdata
,0,psbuf
->st_ex_nlink
); /* number of hard links */
2810 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
2811 * the chflags(2) (or equivalent) flags.
2813 * XXX: this really should be behind the VFS interface. To do this, we would
2814 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
2815 * Each VFS module could then implement its own mapping as appropriate for the
2816 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
2818 static const struct {unsigned stat_fflag
; unsigned smb_fflag
;}
2822 { UF_NODUMP
, EXT_DO_NOT_BACKUP
},
2826 { UF_IMMUTABLE
, EXT_IMMUTABLE
},
2830 { UF_APPEND
, EXT_OPEN_APPEND_ONLY
},
2834 { UF_HIDDEN
, EXT_HIDDEN
},
2837 /* Do not remove. We need to guarantee that this array has at least one
2838 * entry to build on HP-UX.
2844 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT
*psbuf
,
2845 uint32_t *smb_fflags
, uint32_t *smb_fmask
)
2849 for (i
= 0; i
< ARRAY_SIZE(info2_flags_map
); ++i
) {
2850 *smb_fmask
|= info2_flags_map
[i
].smb_fflag
;
2851 if (psbuf
->st_ex_flags
& info2_flags_map
[i
].stat_fflag
) {
2852 *smb_fflags
|= info2_flags_map
[i
].smb_fflag
;
2857 bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT
*psbuf
,
2858 const uint32_t smb_fflags
,
2859 const uint32_t smb_fmask
,
2862 uint32_t max_fmask
= 0;
2865 *stat_fflags
= psbuf
->st_ex_flags
;
2867 /* For each flags requested in smb_fmask, check the state of the
2868 * corresponding flag in smb_fflags and set or clear the matching
2872 for (i
= 0; i
< ARRAY_SIZE(info2_flags_map
); ++i
) {
2873 max_fmask
|= info2_flags_map
[i
].smb_fflag
;
2874 if (smb_fmask
& info2_flags_map
[i
].smb_fflag
) {
2875 if (smb_fflags
& info2_flags_map
[i
].smb_fflag
) {
2876 *stat_fflags
|= info2_flags_map
[i
].stat_fflag
;
2878 *stat_fflags
&= ~info2_flags_map
[i
].stat_fflag
;
2883 /* If smb_fmask is asking to set any bits that are not supported by
2884 * our flag mappings, we should fail.
2886 if ((smb_fmask
& max_fmask
) != smb_fmask
) {
2894 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
2895 * of file flags and birth (create) time.
2897 char *store_file_unix_basic_info2(connection_struct
*conn
,
2900 const SMB_STRUCT_STAT
*psbuf
)
2902 uint32_t file_flags
= 0;
2903 uint32_t flags_mask
= 0;
2905 pdata
= store_file_unix_basic(conn
, pdata
, fsp
, psbuf
);
2907 /* Create (birth) time 64 bit */
2908 put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER
,pdata
, &psbuf
->st_ex_btime
);
2911 map_info2_flags_from_sbuf(psbuf
, &file_flags
, &flags_mask
);
2912 SIVAL(pdata
, 0, file_flags
); /* flags */
2913 SIVAL(pdata
, 4, flags_mask
); /* mask */
2919 static NTSTATUS
marshall_stream_info(unsigned int num_streams
,
2920 const struct stream_struct
*streams
,
2922 unsigned int max_data_bytes
,
2923 unsigned int *data_size
)
2926 unsigned int ofs
= 0;
2928 if (max_data_bytes
< 32) {
2929 return NT_STATUS_INFO_LENGTH_MISMATCH
;
2932 for (i
= 0; i
< num_streams
; i
++) {
2933 unsigned int next_offset
;
2935 smb_ucs2_t
*namebuf
;
2937 if (!push_ucs2_talloc(talloc_tos(), &namebuf
,
2938 streams
[i
].name
, &namelen
) ||
2941 return NT_STATUS_INVALID_PARAMETER
;
2945 * name_buf is now null-terminated, we need to marshall as not
2952 * We cannot overflow ...
2954 if ((ofs
+ 24 + namelen
) > max_data_bytes
) {
2955 DEBUG(10, ("refusing to overflow reply at stream %u\n",
2957 TALLOC_FREE(namebuf
);
2958 return STATUS_BUFFER_OVERFLOW
;
2961 SIVAL(data
, ofs
+4, namelen
);
2962 SOFF_T(data
, ofs
+8, streams
[i
].size
);
2963 SOFF_T(data
, ofs
+16, streams
[i
].alloc_size
);
2964 memcpy(data
+ofs
+24, namebuf
, namelen
);
2965 TALLOC_FREE(namebuf
);
2967 next_offset
= ofs
+ 24 + namelen
;
2969 if (i
== num_streams
-1) {
2970 SIVAL(data
, ofs
, 0);
2973 unsigned int align
= ndr_align_size(next_offset
, 8);
2975 if ((next_offset
+ align
) > max_data_bytes
) {
2976 DEBUG(10, ("refusing to overflow align "
2977 "reply at stream %u\n",
2979 TALLOC_FREE(namebuf
);
2980 return STATUS_BUFFER_OVERFLOW
;
2983 memset(data
+next_offset
, 0, align
);
2984 next_offset
+= align
;
2986 SIVAL(data
, ofs
, next_offset
- ofs
);
2993 DEBUG(10, ("max_data: %u, data_size: %u\n", max_data_bytes
, ofs
));
2997 return NT_STATUS_OK
;
3000 NTSTATUS
smbd_do_qfilepathinfo(connection_struct
*conn
,
3001 TALLOC_CTX
*mem_ctx
,
3002 struct smb_request
*req
,
3003 uint16_t info_level
,
3005 struct smb_filename
*smb_fname
,
3006 bool delete_pending
,
3007 struct timespec write_time_ts
,
3008 struct ea_list
*ea_list
,
3010 unsigned int max_data_bytes
,
3011 size_t *fixed_portion
,
3013 unsigned int *pdata_size
)
3015 char *pdata
= *ppdata
;
3016 char *dstart
, *dend
;
3017 unsigned int data_size
;
3018 struct timespec create_time_ts
, mtime_ts
, atime_ts
, ctime_ts
;
3019 SMB_STRUCT_STAT
*psbuf
= NULL
;
3020 SMB_STRUCT_STAT
*base_sp
= NULL
;
3027 uint64_t file_size
= 0;
3029 uint64_t allocation_size
= 0;
3030 uint64_t file_id
= 0;
3031 uint32_t access_mask
= 0;
3034 if (INFO_LEVEL_IS_UNIX(info_level
)) {
3037 if (lp_smb1_unix_extensions() && req
->posix_pathnames
) {
3038 DBG_DEBUG("SMB1 unix extensions activated\n");
3042 if (conn_using_smb2(conn
->sconn
) &&
3043 (fsp
->posix_flags
& FSP_POSIX_FLAGS_OPEN
))
3045 DBG_DEBUG("SMB2 posix open\n");
3050 return NT_STATUS_INVALID_LEVEL
;
3054 DBG_INFO("%s (%s) level=%d max_data=%u\n",
3055 smb_fname_str_dbg(smb_fname
),
3057 info_level
, max_data_bytes
);
3060 * In case of querying a symlink in POSIX context,
3061 * fsp will be NULL. fdos_mode() deals with it.
3064 smb_fname
= fsp
->fsp_name
;
3066 mode
= fdos_mode(fsp
);
3067 psbuf
= &smb_fname
->st
;
3070 base_sp
= fsp
->base_fsp
?
3071 &fsp
->base_fsp
->fsp_name
->st
:
3074 base_sp
= &smb_fname
->st
;
3077 nlink
= psbuf
->st_ex_nlink
;
3079 if (nlink
&& (mode
&FILE_ATTRIBUTE_DIRECTORY
)) {
3083 if ((nlink
> 0) && delete_pending
) {
3087 if (max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
< max_data_bytes
) {
3088 return NT_STATUS_INVALID_PARAMETER
;
3091 data_size
= max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
;
3092 *ppdata
= (char *)SMB_REALLOC(*ppdata
, data_size
);
3093 if (*ppdata
== NULL
) {
3094 return NT_STATUS_NO_MEMORY
;
3098 dend
= dstart
+ data_size
- 1;
3100 if (!is_omit_timespec(&write_time_ts
) &&
3101 !INFO_LEVEL_IS_UNIX(info_level
))
3103 update_stat_ex_mtime(psbuf
, write_time_ts
);
3106 create_time_ts
= get_create_timespec(conn
, fsp
, smb_fname
);
3107 mtime_ts
= psbuf
->st_ex_mtime
;
3108 atime_ts
= psbuf
->st_ex_atime
;
3109 ctime_ts
= get_change_timespec(conn
, fsp
, smb_fname
);
3111 if (lp_dos_filetime_resolution(SNUM(conn
))) {
3112 dos_filetime_timespec(&create_time_ts
);
3113 dos_filetime_timespec(&mtime_ts
);
3114 dos_filetime_timespec(&atime_ts
);
3115 dos_filetime_timespec(&ctime_ts
);
3118 p
= strrchr_m(smb_fname
->base_name
,'/');
3120 base_name
= smb_fname
->base_name
;
3125 /* NT expects the name to be in an exact form of the *full*
3126 filename. See the trans2 torture test */
3127 if (ISDOT(base_name
)) {
3128 dos_fname
= talloc_strdup(mem_ctx
, "\\");
3130 return NT_STATUS_NO_MEMORY
;
3133 dos_fname
= talloc_asprintf(mem_ctx
,
3135 smb_fname
->base_name
);
3137 return NT_STATUS_NO_MEMORY
;
3139 if (is_named_stream(smb_fname
)) {
3140 dos_fname
= talloc_asprintf(dos_fname
, "%s",
3141 smb_fname
->stream_name
);
3143 return NT_STATUS_NO_MEMORY
;
3147 string_replace(dos_fname
, '/', '\\');
3150 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
, fsp
, psbuf
);
3152 if (fsp
== NULL
|| !fsp
->fsp_flags
.is_fsa
) {
3153 /* Do we have this path open ? */
3154 struct file_id fileid
= vfs_file_id_from_sbuf(conn
, psbuf
);
3155 files_struct
*fsp1
= file_find_di_first(
3156 conn
->sconn
, fileid
, true);
3157 if (fsp1
&& fsp1
->initial_allocation_size
) {
3158 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
, fsp1
, psbuf
);
3162 if (!(mode
& FILE_ATTRIBUTE_DIRECTORY
)) {
3163 file_size
= get_file_size_stat(psbuf
);
3167 pos
= fh_get_position_information(fsp
->fh
);
3171 access_mask
= fsp
->access_mask
;
3173 /* GENERIC_EXECUTE mapping from Windows */
3174 access_mask
= 0x12019F;
3177 /* This should be an index number - looks like
3180 I think this causes us to fail the IFSKIT
3181 BasicFileInformationTest. -tpot */
3182 file_id
= SMB_VFS_FS_FILE_ID(conn
, base_sp
);
3186 switch (info_level
) {
3187 case SMB_INFO_STANDARD
:
3188 DBG_DEBUG("SMB_INFO_STANDARD\n");
3190 srv_put_dos_date2_ts(pdata
,
3193 srv_put_dos_date2_ts(pdata
,
3196 srv_put_dos_date2_ts(pdata
,
3198 mtime_ts
); /* write time */
3199 SIVAL(pdata
,l1_cbFile
,(uint32_t)file_size
);
3200 SIVAL(pdata
,l1_cbFileAlloc
,(uint32_t)allocation_size
);
3201 SSVAL(pdata
,l1_attrFile
,mode
);
3204 case SMB_INFO_QUERY_EA_SIZE
:
3206 unsigned int ea_size
=
3207 estimate_ea_size(smb_fname
->fsp
);
3208 DBG_DEBUG("SMB_INFO_QUERY_EA_SIZE\n");
3210 srv_put_dos_date2_ts(pdata
, 0, create_time_ts
);
3211 srv_put_dos_date2_ts(pdata
, 4, atime_ts
);
3212 srv_put_dos_date2_ts(pdata
,
3214 mtime_ts
); /* write time */
3215 SIVAL(pdata
,12,(uint32_t)file_size
);
3216 SIVAL(pdata
,16,(uint32_t)allocation_size
);
3217 SSVAL(pdata
,20,mode
);
3218 SIVAL(pdata
,22,ea_size
);
3222 case SMB_INFO_IS_NAME_VALID
:
3223 DBG_DEBUG("SMB_INFO_IS_NAME_VALID\n");
3225 /* os/2 needs this ? really ?*/
3226 return NT_STATUS_DOS(ERRDOS
, ERRbadfunc
);
3228 /* This is only reached for qpathinfo */
3232 case SMB_INFO_QUERY_EAS_FROM_LIST
:
3234 size_t total_ea_len
= 0;
3235 struct ea_list
*ea_file_list
= NULL
;
3236 DBG_DEBUG("SMB_INFO_QUERY_EAS_FROM_LIST\n");
3239 get_ea_list_from_fsp(mem_ctx
,
3241 &total_ea_len
, &ea_file_list
);
3242 if (!NT_STATUS_IS_OK(status
)) {
3246 ea_list
= ea_list_union(ea_list
, ea_file_list
, &total_ea_len
);
3248 if (!ea_list
|| (total_ea_len
> data_size
)) {
3250 SIVAL(pdata
,0,4); /* EA List Length must be set to 4 if no EA's. */
3254 data_size
= fill_ea_buffer(mem_ctx
, pdata
, data_size
, conn
, ea_list
);
3258 case SMB_INFO_QUERY_ALL_EAS
:
3260 /* We have data_size bytes to put EA's into. */
3261 size_t total_ea_len
= 0;
3262 DBG_DEBUG(" SMB_INFO_QUERY_ALL_EAS\n");
3264 status
= get_ea_list_from_fsp(mem_ctx
,
3266 &total_ea_len
, &ea_list
);
3267 if (!NT_STATUS_IS_OK(status
)) {
3271 if (!ea_list
|| (total_ea_len
> data_size
)) {
3273 SIVAL(pdata
,0,4); /* EA List Length must be set to 4 if no EA's. */
3277 data_size
= fill_ea_buffer(mem_ctx
, pdata
, data_size
, conn
, ea_list
);
3281 case SMB2_FILE_FULL_EA_INFORMATION
:
3283 /* We have data_size bytes to put EA's into. */
3284 size_t total_ea_len
= 0;
3285 struct ea_list
*ea_file_list
= NULL
;
3287 DBG_DEBUG("SMB2_INFO_QUERY_ALL_EAS\n");
3289 /*TODO: add filtering and index handling */
3292 get_ea_list_from_fsp(mem_ctx
,
3294 &total_ea_len
, &ea_file_list
);
3295 if (!NT_STATUS_IS_OK(status
)) {
3298 if (!ea_file_list
) {
3299 return NT_STATUS_NO_EAS_ON_FILE
;
3302 status
= fill_ea_chained_buffer(mem_ctx
,
3306 conn
, ea_file_list
);
3307 if (!NT_STATUS_IS_OK(status
)) {
3313 case SMB_FILE_BASIC_INFORMATION
:
3314 case SMB_QUERY_FILE_BASIC_INFO
:
3316 if (info_level
== SMB_QUERY_FILE_BASIC_INFO
) {
3317 DBG_DEBUG("SMB_QUERY_FILE_BASIC_INFO\n");
3318 data_size
= 36; /* w95 returns 40 bytes not 36 - why ?. */
3320 DBG_DEBUG("SMB_FILE_BASIC_INFORMATION\n");
3324 put_long_date_full_timespec(conn
->ts_res
,pdata
,&create_time_ts
);
3325 put_long_date_full_timespec(conn
->ts_res
,pdata
+8,&atime_ts
);
3326 put_long_date_full_timespec(conn
->ts_res
,pdata
+16,&mtime_ts
); /* write time */
3327 put_long_date_full_timespec(conn
->ts_res
,pdata
+24,&ctime_ts
); /* change time */
3328 SIVAL(pdata
,32,mode
);
3330 DBG_INFO("SMB_QFBI - create: %s access: %s "
3331 "write: %s change: %s mode: %x\n",
3332 ctime(&create_time_ts
.tv_sec
),
3333 ctime(&atime_ts
.tv_sec
),
3334 ctime(&mtime_ts
.tv_sec
),
3335 ctime(&ctime_ts
.tv_sec
),
3337 *fixed_portion
= data_size
;
3340 case SMB_FILE_STANDARD_INFORMATION
:
3341 case SMB_QUERY_FILE_STANDARD_INFO
:
3343 DBG_DEBUG("SMB_FILE_STANDARD_INFORMATION\n");
3345 SOFF_T(pdata
,0,allocation_size
);
3346 SOFF_T(pdata
,8,file_size
);
3347 SIVAL(pdata
,16,nlink
);
3348 SCVAL(pdata
,20,delete_pending
?1:0);
3349 SCVAL(pdata
,21,(mode
&FILE_ATTRIBUTE_DIRECTORY
)?1:0);
3350 SSVAL(pdata
,22,0); /* Padding. */
3351 *fixed_portion
= 24;
3354 case SMB_FILE_EA_INFORMATION
:
3355 case SMB_QUERY_FILE_EA_INFO
:
3357 unsigned int ea_size
=
3358 estimate_ea_size(smb_fname
->fsp
);
3359 DBG_DEBUG("SMB_FILE_EA_INFORMATION\n");
3362 SIVAL(pdata
,0,ea_size
);
3366 /* Get the 8.3 name - used if NT SMB was negotiated. */
3367 case SMB_QUERY_FILE_ALT_NAME_INFO
:
3368 case SMB_FILE_ALTERNATE_NAME_INFORMATION
:
3370 char mangled_name
[13];
3371 DBG_DEBUG("SMB_FILE_ALTERNATE_NAME_INFORMATION\n");
3372 if (!name_to_8_3(base_name
,mangled_name
,
3373 True
,conn
->params
)) {
3374 return NT_STATUS_NO_MEMORY
;
3376 status
= srvstr_push(dstart
, flags2
,
3377 pdata
+4, mangled_name
,
3378 PTR_DIFF(dend
, pdata
+4),
3380 if (!NT_STATUS_IS_OK(status
)) {
3383 data_size
= 4 + len
;
3389 case SMB_QUERY_FILE_NAME_INFO
:
3392 this must be *exactly* right for ACLs on mapped drives to work
3394 status
= srvstr_push(dstart
, flags2
,
3396 PTR_DIFF(dend
, pdata
+4),
3398 if (!NT_STATUS_IS_OK(status
)) {
3401 DBG_DEBUG("SMB_QUERY_FILE_NAME_INFO\n");
3402 data_size
= 4 + len
;
3407 case SMB_FILE_NORMALIZED_NAME_INFORMATION
:
3409 char *nfname
= NULL
;
3412 !conn_using_smb2(fsp
->conn
->sconn
)) {
3413 return NT_STATUS_INVALID_LEVEL
;
3416 nfname
= talloc_strdup(mem_ctx
, smb_fname
->base_name
);
3417 if (nfname
== NULL
) {
3418 return NT_STATUS_NO_MEMORY
;
3421 if (ISDOT(nfname
)) {
3424 string_replace(nfname
, '/', '\\');
3426 if (fsp_is_alternate_stream(fsp
)) {
3427 const char *s
= smb_fname
->stream_name
;
3428 const char *e
= NULL
;
3431 SMB_ASSERT(s
[0] != '\0');
3434 * smb_fname->stream_name is in form
3435 * of ':StrEam:$DATA', but we should only
3436 * append ':StrEam' here.
3439 e
= strchr(&s
[1], ':');
3445 nfname
= talloc_strndup_append(nfname
, s
, n
);
3446 if (nfname
== NULL
) {
3447 return NT_STATUS_NO_MEMORY
;
3451 status
= srvstr_push(dstart
, flags2
,
3453 PTR_DIFF(dend
, pdata
+4),
3455 if (!NT_STATUS_IS_OK(status
)) {
3458 DBG_DEBUG("SMB_FILE_NORMALIZED_NAME_INFORMATION\n");
3459 data_size
= 4 + len
;
3465 case SMB_FILE_ALLOCATION_INFORMATION
:
3466 case SMB_QUERY_FILE_ALLOCATION_INFO
:
3467 DBG_DEBUG("SMB_FILE_ALLOCATION_INFORMATION\n");
3469 SOFF_T(pdata
,0,allocation_size
);
3472 case SMB_FILE_END_OF_FILE_INFORMATION
:
3473 case SMB_QUERY_FILE_END_OF_FILEINFO
:
3474 DBG_DEBUG("SMB_FILE_END_OF_FILE_INFORMATION\n");
3476 SOFF_T(pdata
,0,file_size
);
3479 case SMB_QUERY_FILE_ALL_INFO
:
3480 case SMB_FILE_ALL_INFORMATION
:
3482 unsigned int ea_size
=
3483 estimate_ea_size(smb_fname
->fsp
);
3484 DBG_DEBUG("SMB_FILE_ALL_INFORMATION\n");
3485 put_long_date_full_timespec(conn
->ts_res
,pdata
,&create_time_ts
);
3486 put_long_date_full_timespec(conn
->ts_res
,pdata
+8,&atime_ts
);
3487 put_long_date_full_timespec(conn
->ts_res
,pdata
+16,&mtime_ts
); /* write time */
3488 put_long_date_full_timespec(conn
->ts_res
,pdata
+24,&ctime_ts
); /* change time */
3489 SIVAL(pdata
,32,mode
);
3490 SIVAL(pdata
,36,0); /* padding. */
3492 SOFF_T(pdata
,0,allocation_size
);
3493 SOFF_T(pdata
,8,file_size
);
3494 SIVAL(pdata
,16,nlink
);
3495 SCVAL(pdata
,20,delete_pending
);
3496 SCVAL(pdata
,21,(mode
&FILE_ATTRIBUTE_DIRECTORY
)?1:0);
3499 SIVAL(pdata
,0,ea_size
);
3500 pdata
+= 4; /* EA info */
3501 status
= srvstr_push(dstart
, flags2
,
3503 PTR_DIFF(dend
, pdata
+4),
3505 if (!NT_STATUS_IS_OK(status
)) {
3510 data_size
= PTR_DIFF(pdata
,(*ppdata
));
3511 *fixed_portion
= 10;
3515 case SMB2_FILE_ALL_INFORMATION
:
3517 unsigned int ea_size
=
3518 estimate_ea_size(smb_fname
->fsp
);
3519 DBG_DEBUG("SMB2_FILE_ALL_INFORMATION\n");
3520 put_long_date_full_timespec(conn
->ts_res
,pdata
+0x00,&create_time_ts
);
3521 put_long_date_full_timespec(conn
->ts_res
,pdata
+0x08,&atime_ts
);
3522 put_long_date_full_timespec(conn
->ts_res
,pdata
+0x10,&mtime_ts
); /* write time */
3523 put_long_date_full_timespec(conn
->ts_res
,pdata
+0x18,&ctime_ts
); /* change time */
3524 SIVAL(pdata
, 0x20, mode
);
3525 SIVAL(pdata
, 0x24, 0); /* padding. */
3526 SBVAL(pdata
, 0x28, allocation_size
);
3527 SBVAL(pdata
, 0x30, file_size
);
3528 SIVAL(pdata
, 0x38, nlink
);
3529 SCVAL(pdata
, 0x3C, delete_pending
);
3530 SCVAL(pdata
, 0x3D, (mode
&FILE_ATTRIBUTE_DIRECTORY
)?1:0);
3531 SSVAL(pdata
, 0x3E, 0); /* padding */
3532 SBVAL(pdata
, 0x40, file_id
);
3533 SIVAL(pdata
, 0x48, ea_size
);
3534 SIVAL(pdata
, 0x4C, access_mask
);
3535 SBVAL(pdata
, 0x50, pos
);
3536 SIVAL(pdata
, 0x58, mode
); /*TODO: mode != mode fix this!!! */
3537 SIVAL(pdata
, 0x5C, 0); /* No alignment needed. */
3541 status
= srvstr_push(dstart
, flags2
,
3543 PTR_DIFF(dend
, pdata
+4),
3545 if (!NT_STATUS_IS_OK(status
)) {
3550 data_size
= PTR_DIFF(pdata
,(*ppdata
));
3551 *fixed_portion
= 104;
3554 case SMB_FILE_INTERNAL_INFORMATION
:
3556 DBG_DEBUG("SMB_FILE_INTERNAL_INFORMATION\n");
3557 SBVAL(pdata
, 0, file_id
);
3562 case SMB_FILE_ACCESS_INFORMATION
:
3563 DBG_DEBUG("SMB_FILE_ACCESS_INFORMATION\n");
3564 SIVAL(pdata
, 0, access_mask
);
3569 case SMB_FILE_NAME_INFORMATION
:
3570 /* Pathname with leading '\'. */
3573 byte_len
= dos_PutUniCode(pdata
+4,dos_fname
,(size_t)max_data_bytes
,False
);
3574 DBG_DEBUG("SMB_FILE_NAME_INFORMATION\n");
3575 SIVAL(pdata
,0,byte_len
);
3576 data_size
= 4 + byte_len
;
3580 case SMB_FILE_DISPOSITION_INFORMATION
:
3581 DBG_DEBUG("SMB_FILE_DISPOSITION_INFORMATION\n");
3583 SCVAL(pdata
,0,delete_pending
);
3587 case SMB_FILE_POSITION_INFORMATION
:
3588 DBG_DEBUG("SMB_FILE_POSITION_INFORMATION\n");
3590 SOFF_T(pdata
,0,pos
);
3594 case SMB_FILE_MODE_INFORMATION
:
3595 DBG_DEBUG("SMB_FILE_MODE_INFORMATION\n");
3596 SIVAL(pdata
,0,mode
);
3601 case SMB_FILE_ALIGNMENT_INFORMATION
:
3602 DBG_DEBUG("SMB_FILE_ALIGNMENT_INFORMATION\n");
3603 SIVAL(pdata
,0,0); /* No alignment needed. */
3609 * NT4 server just returns "invalid query" to this - if we try
3610 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
3613 /* The first statement above is false - verified using Thursby
3614 * client against NT4 -- gcolley.
3616 case SMB_QUERY_FILE_STREAM_INFO
:
3617 case SMB_FILE_STREAM_INFORMATION
: {
3618 unsigned int num_streams
= 0;
3619 struct stream_struct
*streams
= NULL
;
3621 DBG_DEBUG("SMB_FILE_STREAM_INFORMATION\n");
3623 if (is_ntfs_stream_smb_fname(smb_fname
)) {
3624 return NT_STATUS_INVALID_PARAMETER
;
3627 status
= vfs_fstreaminfo(fsp
,
3632 if (!NT_STATUS_IS_OK(status
)) {
3633 DBG_DEBUG("could not get stream info: %s\n",
3638 status
= marshall_stream_info(num_streams
, streams
,
3639 pdata
, max_data_bytes
,
3642 if (!NT_STATUS_IS_OK(status
)) {
3643 DBG_DEBUG("marshall_stream_info failed: %s\n",
3645 TALLOC_FREE(streams
);
3649 TALLOC_FREE(streams
);
3651 *fixed_portion
= 32;
3655 case SMB_QUERY_COMPRESSION_INFO
:
3656 case SMB_FILE_COMPRESSION_INFORMATION
:
3657 DBG_DEBUG("SMB_FILE_COMPRESSION_INFORMATION\n");
3658 SOFF_T(pdata
,0,file_size
);
3659 SIVAL(pdata
,8,0); /* ??? */
3660 SIVAL(pdata
,12,0); /* ??? */
3662 *fixed_portion
= 16;
3665 case SMB_FILE_NETWORK_OPEN_INFORMATION
:
3666 DBG_DEBUG("SMB_FILE_NETWORK_OPEN_INFORMATION\n");
3667 put_long_date_full_timespec(conn
->ts_res
,pdata
,&create_time_ts
);
3668 put_long_date_full_timespec(conn
->ts_res
,pdata
+8,&atime_ts
);
3669 put_long_date_full_timespec(conn
->ts_res
,pdata
+16,&mtime_ts
); /* write time */
3670 put_long_date_full_timespec(conn
->ts_res
,pdata
+24,&ctime_ts
); /* change time */
3671 SOFF_T(pdata
,32,allocation_size
);
3672 SOFF_T(pdata
,40,file_size
);
3673 SIVAL(pdata
,48,mode
);
3674 SIVAL(pdata
,52,0); /* ??? */
3676 *fixed_portion
= 56;
3679 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION
:
3680 DBG_DEBUG(" SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n");
3681 SIVAL(pdata
,0,mode
);
3688 * SMB2 UNIX Extensions.
3690 case SMB2_FILE_POSIX_INFORMATION_INTERNAL
:
3692 struct smb3_file_posix_information info
= {};
3693 uint8_t buf
[sizeof(info
)];
3694 struct ndr_push ndr
= {
3696 .alloc_size
= sizeof(buf
),
3697 .fixed_buf_size
= true,
3699 enum ndr_err_code ndr_err
;
3701 if (!conn_using_smb2(conn
->sconn
)) {
3702 return NT_STATUS_INVALID_LEVEL
;
3705 return NT_STATUS_INVALID_HANDLE
;
3707 if (!(fsp
->posix_flags
& FSP_POSIX_FLAGS_OPEN
)) {
3708 return NT_STATUS_INVALID_LEVEL
;
3711 smb3_file_posix_information_init(
3712 conn
, &smb_fname
->st
, 0, mode
, &info
);
3714 ndr_err
= ndr_push_smb3_file_posix_information(
3715 &ndr
, NDR_SCALARS
|NDR_BUFFERS
, &info
);
3716 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
3717 return NT_STATUS_INSUFFICIENT_RESOURCES
;
3720 memcpy(pdata
, buf
, ndr
.offset
);
3721 data_size
= ndr
.offset
;
3726 return NT_STATUS_INVALID_LEVEL
;
3729 *pdata_size
= data_size
;
3730 return NT_STATUS_OK
;
3733 /****************************************************************************
3734 Set a hard link (called by UNIX extensions and by NT rename with HARD link
3736 ****************************************************************************/
3738 NTSTATUS
hardlink_internals(TALLOC_CTX
*ctx
,
3739 connection_struct
*conn
,
3740 struct smb_request
*req
,
3741 bool overwrite_if_exists
,
3742 const struct smb_filename
*smb_fname_old
,
3743 struct smb_filename
*smb_fname_new
)
3745 NTSTATUS status
= NT_STATUS_OK
;
3748 struct smb_filename
*parent_fname_old
= NULL
;
3749 struct smb_filename
*base_name_old
= NULL
;
3750 struct smb_filename
*parent_fname_new
= NULL
;
3751 struct smb_filename
*base_name_new
= NULL
;
3753 /* source must already exist. */
3754 if (!VALID_STAT(smb_fname_old
->st
)) {
3755 status
= NT_STATUS_OBJECT_NAME_NOT_FOUND
;
3759 /* No links from a directory. */
3760 if (S_ISDIR(smb_fname_old
->st
.st_ex_mode
)) {
3761 status
= NT_STATUS_FILE_IS_A_DIRECTORY
;
3765 /* Setting a hardlink to/from a stream isn't currently supported. */
3766 ok
= is_ntfs_stream_smb_fname(smb_fname_old
);
3768 DBG_DEBUG("Old name has streams\n");
3769 status
= NT_STATUS_INVALID_PARAMETER
;
3772 ok
= is_ntfs_stream_smb_fname(smb_fname_new
);
3774 DBG_DEBUG("New name has streams\n");
3775 status
= NT_STATUS_INVALID_PARAMETER
;
3779 if (smb_fname_old
->twrp
!= 0) {
3780 status
= NT_STATUS_NOT_SAME_DEVICE
;
3784 status
= parent_pathref(talloc_tos(),
3789 if (!NT_STATUS_IS_OK(status
)) {
3793 status
= parent_pathref(talloc_tos(),
3798 if (!NT_STATUS_IS_OK(status
)) {
3802 if (VALID_STAT(smb_fname_new
->st
)) {
3803 if (overwrite_if_exists
) {
3804 if (S_ISDIR(smb_fname_new
->st
.st_ex_mode
)) {
3805 status
= NT_STATUS_FILE_IS_A_DIRECTORY
;
3808 status
= unlink_internals(conn
,
3810 FILE_ATTRIBUTE_NORMAL
,
3811 NULL
, /* new_dirfsp */
3813 if (!NT_STATUS_IS_OK(status
)) {
3817 /* Disallow if newname already exists. */
3818 status
= NT_STATUS_OBJECT_NAME_COLLISION
;
3823 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
3824 smb_fname_old
->base_name
, smb_fname_new
->base_name
));
3826 ret
= SMB_VFS_LINKAT(conn
,
3827 parent_fname_old
->fsp
,
3829 parent_fname_new
->fsp
,
3834 status
= map_nt_error_from_unix(errno
);
3835 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
3836 nt_errstr(status
), smb_fname_old
->base_name
,
3837 smb_fname_new
->base_name
));
3842 TALLOC_FREE(parent_fname_old
);
3843 TALLOC_FREE(parent_fname_new
);
3847 /****************************************************************************
3848 Deal with setting the time from any of the setfilepathinfo functions.
3849 NOTE !!!! The check for FILE_WRITE_ATTRIBUTES access must be done *before*
3850 calling this function.
3851 ****************************************************************************/
3853 NTSTATUS
smb_set_file_time(connection_struct
*conn
,
3855 struct smb_filename
*smb_fname
,
3856 struct smb_file_time
*ft
,
3857 bool setting_write_time
)
3859 struct files_struct
*set_fsp
= NULL
;
3860 struct timeval_buf tbuf
[4];
3862 FILE_NOTIFY_CHANGE_LAST_ACCESS
3863 |FILE_NOTIFY_CHANGE_LAST_WRITE
3864 |FILE_NOTIFY_CHANGE_CREATION
;
3867 if (!VALID_STAT(smb_fname
->st
)) {
3868 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
3873 return NT_STATUS_OK
;
3876 set_fsp
= metadata_fsp(fsp
);
3878 /* get some defaults (no modifications) if any info is zero or -1. */
3879 if (is_omit_timespec(&ft
->create_time
)) {
3880 action
&= ~FILE_NOTIFY_CHANGE_CREATION
;
3883 if (is_omit_timespec(&ft
->atime
)) {
3884 action
&= ~FILE_NOTIFY_CHANGE_LAST_ACCESS
;
3887 if (is_omit_timespec(&ft
->mtime
)) {
3888 action
&= ~FILE_NOTIFY_CHANGE_LAST_WRITE
;
3891 if (!setting_write_time
) {
3892 /* ft->mtime comes from change time, not write time. */
3893 action
&= ~FILE_NOTIFY_CHANGE_LAST_WRITE
;
3896 /* Ensure the resolution is the correct for
3897 * what we can store on this filesystem. */
3899 round_timespec(conn
->ts_res
, &ft
->create_time
);
3900 round_timespec(conn
->ts_res
, &ft
->ctime
);
3901 round_timespec(conn
->ts_res
, &ft
->atime
);
3902 round_timespec(conn
->ts_res
, &ft
->mtime
);
3904 DBG_DEBUG("smb_set_filetime: actime: %s\n ",
3905 timespec_string_buf(&ft
->atime
, true, &tbuf
[0]));
3906 DBG_DEBUG("smb_set_filetime: modtime: %s\n ",
3907 timespec_string_buf(&ft
->mtime
, true, &tbuf
[1]));
3908 DBG_DEBUG("smb_set_filetime: ctime: %s\n ",
3909 timespec_string_buf(&ft
->ctime
, true, &tbuf
[2]));
3910 DBG_DEBUG("smb_set_file_time: createtime: %s\n ",
3911 timespec_string_buf(&ft
->create_time
, true, &tbuf
[3]));
3913 if (setting_write_time
) {
3915 * This was a Windows setfileinfo on an open file.
3916 * NT does this a lot. We also need to
3917 * set the time here, as it can be read by
3918 * FindFirst/FindNext and with the patch for bug #2045
3919 * in smbd/fileio.c it ensures that this timestamp is
3920 * kept sticky even after a write. We save the request
3921 * away and will set it on file close and after a write. JRA.
3924 DBG_DEBUG("setting pending modtime to %s\n",
3925 timespec_string_buf(&ft
->mtime
, true, &tbuf
[0]));
3927 if (set_fsp
!= NULL
) {
3928 set_sticky_write_time_fsp(set_fsp
, ft
->mtime
);
3930 set_sticky_write_time_path(
3931 vfs_file_id_from_sbuf(conn
, &smb_fname
->st
),
3936 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
3938 ret
= file_ntimes(conn
, set_fsp
, ft
);
3940 return map_nt_error_from_unix(errno
);
3943 notify_fname(conn
, NOTIFY_ACTION_MODIFIED
, action
,
3944 smb_fname
->base_name
);
3945 return NT_STATUS_OK
;
3948 /****************************************************************************
3949 Deal with setting the dosmode from any of the setfilepathinfo functions.
3950 NB. The check for FILE_WRITE_ATTRIBUTES access on this path must have been
3951 done before calling this function.
3952 ****************************************************************************/
3954 static NTSTATUS
smb_set_file_dosmode(connection_struct
*conn
,
3955 struct files_struct
*fsp
,
3958 struct files_struct
*dos_fsp
= NULL
;
3959 uint32_t current_dosmode
;
3962 if (!VALID_STAT(fsp
->fsp_name
->st
)) {
3963 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
3966 dos_fsp
= metadata_fsp(fsp
);
3969 if (S_ISDIR(fsp
->fsp_name
->st
.st_ex_mode
)) {
3970 dosmode
|= FILE_ATTRIBUTE_DIRECTORY
;
3972 dosmode
&= ~FILE_ATTRIBUTE_DIRECTORY
;
3976 DBG_DEBUG("dosmode: 0x%" PRIx32
"\n", dosmode
);
3978 /* check the mode isn't different, before changing it */
3980 return NT_STATUS_OK
;
3982 current_dosmode
= fdos_mode(dos_fsp
);
3983 if (dosmode
== current_dosmode
) {
3984 return NT_STATUS_OK
;
3987 DBG_DEBUG("file %s : setting dos mode 0x%" PRIx32
"\n",
3988 fsp_str_dbg(dos_fsp
), dosmode
);
3990 ret
= file_set_dosmode(conn
, dos_fsp
->fsp_name
, dosmode
, NULL
, false);
3992 DBG_WARNING("file_set_dosmode of %s failed: %s\n",
3993 fsp_str_dbg(dos_fsp
), strerror(errno
));
3994 return map_nt_error_from_unix(errno
);
3997 return NT_STATUS_OK
;
4000 /****************************************************************************
4001 Deal with setting the size from any of the setfilepathinfo functions.
4002 ****************************************************************************/
4004 NTSTATUS
smb_set_file_size(connection_struct
*conn
,
4005 struct smb_request
*req
,
4007 struct smb_filename
*smb_fname
,
4008 const SMB_STRUCT_STAT
*psbuf
,
4010 bool fail_after_createfile
)
4012 NTSTATUS status
= NT_STATUS_OK
;
4013 files_struct
*new_fsp
= NULL
;
4015 if (!VALID_STAT(*psbuf
)) {
4016 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
4019 DBG_INFO("size: %"PRIu64
", file_size_stat=%"PRIu64
"\n",
4021 get_file_size_stat(psbuf
));
4023 if (size
== get_file_size_stat(psbuf
)) {
4025 return NT_STATUS_OK
;
4027 if (!fsp
->fsp_flags
.modified
) {
4028 return NT_STATUS_OK
;
4030 trigger_write_time_update_immediate(fsp
);
4031 return NT_STATUS_OK
;
4034 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
4035 smb_fname_str_dbg(smb_fname
), (double)size
));
4038 !fsp
->fsp_flags
.is_pathref
&&
4039 fsp_get_io_fd(fsp
) != -1)
4041 /* Handle based call. */
4042 status
= check_any_access_fsp(fsp
, FILE_WRITE_DATA
);
4043 if (!NT_STATUS_IS_OK(status
)) {
4047 if (vfs_set_filelen(fsp
, size
) == -1) {
4048 return map_nt_error_from_unix(errno
);
4050 trigger_write_time_update_immediate(fsp
);
4051 return NT_STATUS_OK
;
4054 status
= SMB_VFS_CREATE_FILE(
4058 smb_fname
, /* fname */
4059 FILE_WRITE_DATA
, /* access_mask */
4060 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
4062 FILE_OPEN
, /* create_disposition*/
4063 0, /* create_options */
4064 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
4065 0, /* oplock_request */
4067 0, /* allocation_size */
4068 0, /* private_flags */
4071 &new_fsp
, /* result */
4073 NULL
, NULL
); /* create context */
4075 if (!NT_STATUS_IS_OK(status
)) {
4076 /* NB. We check for open_was_deferred in the caller. */
4080 /* See RAW-SFILEINFO-END-OF-FILE */
4081 if (fail_after_createfile
) {
4082 close_file_free(req
, &new_fsp
, NORMAL_CLOSE
);
4083 return NT_STATUS_INVALID_LEVEL
;
4086 if (vfs_set_filelen(new_fsp
, size
) == -1) {
4087 status
= map_nt_error_from_unix(errno
);
4088 close_file_free(req
, &new_fsp
, NORMAL_CLOSE
);
4092 trigger_write_time_update_immediate(new_fsp
);
4093 close_file_free(req
, &new_fsp
, NORMAL_CLOSE
);
4094 return NT_STATUS_OK
;
4097 /****************************************************************************
4098 Deal with SMB_INFO_SET_EA.
4099 ****************************************************************************/
4101 static NTSTATUS
smb_info_set_ea(connection_struct
*conn
,
4105 struct smb_filename
*smb_fname
)
4107 struct ea_list
*ea_list
= NULL
;
4108 TALLOC_CTX
*ctx
= NULL
;
4109 NTSTATUS status
= NT_STATUS_OK
;
4111 if (total_data
< 10) {
4113 /* OS/2 workplace shell seems to send SET_EA requests of "null"
4114 length. They seem to have no effect. Bug #3212. JRA */
4116 if ((total_data
== 4) && (IVAL(pdata
,0) == 4)) {
4117 /* We're done. We only get EA info in this call. */
4118 return NT_STATUS_OK
;
4121 return NT_STATUS_INVALID_PARAMETER
;
4124 if (IVAL(pdata
,0) > total_data
) {
4125 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
4126 IVAL(pdata
,0), (unsigned int)total_data
));
4127 return NT_STATUS_INVALID_PARAMETER
;
4131 ea_list
= read_ea_list(ctx
, pdata
+ 4, total_data
- 4);
4133 return NT_STATUS_INVALID_PARAMETER
;
4138 * The only way fsp can be NULL here is if
4139 * smb_fname points at a symlink and
4140 * and we're in POSIX context.
4141 * Ensure this is the case.
4143 * In this case we cannot set the EA.
4145 SMB_ASSERT(smb_fname
->flags
& SMB_FILENAME_POSIX_PATH
);
4146 return NT_STATUS_ACCESS_DENIED
;
4149 status
= set_ea(conn
, fsp
, ea_list
);
4154 /****************************************************************************
4155 Deal with SMB_FILE_FULL_EA_INFORMATION set.
4156 ****************************************************************************/
4158 static NTSTATUS
smb_set_file_full_ea_info(connection_struct
*conn
,
4163 struct ea_list
*ea_list
= NULL
;
4167 return NT_STATUS_INVALID_HANDLE
;
4170 if (!lp_ea_support(SNUM(conn
))) {
4171 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
4172 "EA's not supported.\n",
4173 (unsigned int)total_data
));
4174 return NT_STATUS_EAS_NOT_SUPPORTED
;
4177 if (total_data
< 10) {
4178 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
4180 (unsigned int)total_data
));
4181 return NT_STATUS_INVALID_PARAMETER
;
4184 ea_list
= read_nttrans_ea_list(talloc_tos(),
4189 return NT_STATUS_INVALID_PARAMETER
;
4192 status
= set_ea(conn
, fsp
, ea_list
);
4194 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
4195 smb_fname_str_dbg(fsp
->fsp_name
),
4196 nt_errstr(status
) ));
4202 /****************************************************************************
4203 Deal with SMB_SET_FILE_DISPOSITION_INFO.
4204 ****************************************************************************/
4206 NTSTATUS
smb_set_file_disposition_info(connection_struct
*conn
,
4210 struct smb_filename
*smb_fname
)
4212 NTSTATUS status
= NT_STATUS_OK
;
4213 bool delete_on_close
;
4214 uint32_t dosmode
= 0;
4216 if (total_data
< 1) {
4217 return NT_STATUS_INVALID_PARAMETER
;
4221 return NT_STATUS_INVALID_HANDLE
;
4224 delete_on_close
= (CVAL(pdata
,0) ? True
: False
);
4225 dosmode
= fdos_mode(fsp
);
4227 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
4228 "delete_on_close = %u\n",
4229 smb_fname_str_dbg(smb_fname
),
4230 (unsigned int)dosmode
,
4231 (unsigned int)delete_on_close
));
4233 if (delete_on_close
) {
4234 status
= can_set_delete_on_close(fsp
, dosmode
);
4235 if (!NT_STATUS_IS_OK(status
)) {
4240 /* The set is across all open files on this dev/inode pair. */
4241 if (!set_delete_on_close(fsp
, delete_on_close
,
4242 conn
->session_info
->security_token
,
4243 conn
->session_info
->unix_token
)) {
4244 return NT_STATUS_ACCESS_DENIED
;
4246 return NT_STATUS_OK
;
4249 /****************************************************************************
4250 Deal with SMB_FILE_POSITION_INFORMATION.
4251 ****************************************************************************/
4253 static NTSTATUS
smb_file_position_information(connection_struct
*conn
,
4258 uint64_t position_information
;
4260 if (total_data
< 8) {
4261 return NT_STATUS_INVALID_PARAMETER
;
4265 /* Ignore on pathname based set. */
4266 return NT_STATUS_OK
;
4269 position_information
= (uint64_t)IVAL(pdata
,0);
4270 position_information
|= (((uint64_t)IVAL(pdata
,4)) << 32);
4272 DEBUG(10,("smb_file_position_information: Set file position "
4273 "information for file %s to %.0f\n", fsp_str_dbg(fsp
),
4274 (double)position_information
));
4275 fh_set_position_information(fsp
->fh
, position_information
);
4276 return NT_STATUS_OK
;
4279 /****************************************************************************
4280 Deal with SMB_FILE_MODE_INFORMATION.
4281 ****************************************************************************/
4283 static NTSTATUS
smb_file_mode_information(connection_struct
*conn
,
4289 if (total_data
< 4) {
4290 return NT_STATUS_INVALID_PARAMETER
;
4292 mode
= IVAL(pdata
,0);
4293 if (mode
!= 0 && mode
!= 2 && mode
!= 4 && mode
!= 6) {
4294 return NT_STATUS_INVALID_PARAMETER
;
4296 return NT_STATUS_OK
;
4299 /****************************************************************************
4300 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
4301 ****************************************************************************/
4303 static NTSTATUS
smb2_file_rename_information(connection_struct
*conn
,
4304 struct smb_request
*req
,
4308 struct smb_filename
*smb_fname_src
)
4312 char *newname
= NULL
;
4313 struct files_struct
*dst_dirfsp
= NULL
;
4314 struct smb_filename
*smb_fname_dst
= NULL
;
4315 const char *dst_original_lcomp
= NULL
;
4316 uint32_t ucf_flags
= ucf_flags_from_smb_request(req
);
4317 NTSTATUS status
= NT_STATUS_OK
;
4318 TALLOC_CTX
*ctx
= talloc_tos();
4321 return NT_STATUS_INVALID_HANDLE
;
4324 if (total_data
< 20) {
4325 return NT_STATUS_INVALID_PARAMETER
;
4328 overwrite
= (CVAL(pdata
,0) ? True
: False
);
4329 len
= IVAL(pdata
,16);
4331 if (len
> (total_data
- 20) || (len
== 0)) {
4332 return NT_STATUS_INVALID_PARAMETER
;
4335 (void)srvstr_pull_talloc(ctx
,
4343 if (newname
== NULL
) {
4344 return NT_STATUS_INVALID_PARAMETER
;
4347 /* SMB2 rename paths are never DFS. */
4348 req
->flags2
&= ~FLAGS2_DFS_PATHNAMES
;
4349 ucf_flags
&= ~UCF_DFS_PATHNAME
;
4351 status
= check_path_syntax(newname
,
4352 fsp
->fsp_name
->flags
& SMB_FILENAME_POSIX_PATH
);
4353 if (!NT_STATUS_IS_OK(status
)) {
4357 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
4360 if (newname
[0] == ':') {
4361 /* Create an smb_fname to call rename_internals_fsp() with. */
4362 smb_fname_dst
= synthetic_smb_fname(talloc_tos(),
4363 fsp
->base_fsp
->fsp_name
->base_name
,
4366 fsp
->base_fsp
->fsp_name
->twrp
,
4367 fsp
->base_fsp
->fsp_name
->flags
);
4368 if (smb_fname_dst
== NULL
) {
4369 status
= NT_STATUS_NO_MEMORY
;
4373 status
= filename_convert_dirfsp(ctx
,
4377 0, /* Never a TWRP. */
4380 if (!NT_STATUS_IS_OK(status
)) {
4386 * Set the original last component, since
4387 * rename_internals_fsp() requires it.
4389 dst_original_lcomp
= get_original_lcomp(smb_fname_dst
,
4393 if (dst_original_lcomp
== NULL
) {
4394 status
= NT_STATUS_NO_MEMORY
;
4398 DEBUG(10,("smb2_file_rename_information: "
4399 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
4400 fsp_fnum_dbg(fsp
), fsp_str_dbg(fsp
),
4401 smb_fname_str_dbg(smb_fname_dst
)));
4402 status
= rename_internals_fsp(conn
,
4406 (FILE_ATTRIBUTE_HIDDEN
|FILE_ATTRIBUTE_SYSTEM
),
4410 TALLOC_FREE(smb_fname_dst
);
4414 static NTSTATUS
smb2_file_link_information(connection_struct
*conn
,
4415 struct smb_request
*req
,
4419 struct smb_filename
*smb_fname_src
)
4423 char *newname
= NULL
;
4424 struct files_struct
*dst_dirfsp
= NULL
;
4425 struct smb_filename
*smb_fname_dst
= NULL
;
4426 NTSTATUS status
= NT_STATUS_OK
;
4427 uint32_t ucf_flags
= ucf_flags_from_smb_request(req
);
4429 TALLOC_CTX
*ctx
= talloc_tos();
4432 return NT_STATUS_INVALID_HANDLE
;
4435 if (total_data
< 20) {
4436 return NT_STATUS_INVALID_PARAMETER
;
4439 overwrite
= (CVAL(pdata
,0) ? true : false);
4440 len
= IVAL(pdata
,16);
4442 if (len
> (total_data
- 20) || (len
== 0)) {
4443 return NT_STATUS_INVALID_PARAMETER
;
4446 ret
= srvstr_pull_talloc(ctx
,
4454 if (ret
== (size_t)-1 || newname
== NULL
) {
4455 return NT_STATUS_INVALID_PARAMETER
;
4458 /* SMB2 hardlink paths are never DFS. */
4459 req
->flags2
&= ~FLAGS2_DFS_PATHNAMES
;
4460 ucf_flags
&= ~UCF_DFS_PATHNAME
;
4462 status
= check_path_syntax(newname
,
4463 fsp
->fsp_name
->flags
& SMB_FILENAME_POSIX_PATH
);
4464 if (!NT_STATUS_IS_OK(status
)) {
4468 DBG_DEBUG("got name |%s|\n", newname
);
4470 status
= filename_convert_dirfsp(ctx
,
4477 if (!NT_STATUS_IS_OK(status
)) {
4481 if (fsp
->base_fsp
) {
4482 /* No stream names. */
4483 return NT_STATUS_NOT_SUPPORTED
;
4486 DBG_DEBUG("SMB_FILE_LINK_INFORMATION (%s) %s -> %s\n",
4487 fsp_fnum_dbg(fsp
), fsp_str_dbg(fsp
),
4488 smb_fname_str_dbg(smb_fname_dst
));
4489 status
= hardlink_internals(ctx
,
4496 TALLOC_FREE(smb_fname_dst
);
4500 static NTSTATUS
smb_file_link_information(connection_struct
*conn
,
4501 struct smb_request
*req
,
4505 struct smb_filename
*smb_fname_src
)
4509 char *newname
= NULL
;
4510 struct files_struct
*dst_dirfsp
= NULL
;
4511 struct smb_filename
*smb_fname_dst
= NULL
;
4512 NTSTATUS status
= NT_STATUS_OK
;
4513 uint32_t ucf_flags
= ucf_flags_from_smb_request(req
);
4514 NTTIME dst_twrp
= 0;
4515 TALLOC_CTX
*ctx
= talloc_tos();
4518 return NT_STATUS_INVALID_HANDLE
;
4521 if (total_data
< 20) {
4522 return NT_STATUS_INVALID_PARAMETER
;
4525 overwrite
= (CVAL(pdata
,0) ? true : false);
4526 len
= IVAL(pdata
,16);
4528 if (len
> (total_data
- 20) || (len
== 0)) {
4529 return NT_STATUS_INVALID_PARAMETER
;
4532 if (smb_fname_src
->flags
& SMB_FILENAME_POSIX_PATH
) {
4533 srvstr_get_path_posix(ctx
,
4541 ucf_flags
|= UCF_POSIX_PATHNAMES
;
4543 srvstr_get_path(ctx
,
4552 if (!NT_STATUS_IS_OK(status
)) {
4556 DEBUG(10,("smb_file_link_information: got name |%s|\n",
4559 if (ucf_flags
& UCF_GMT_PATHNAME
) {
4560 extract_snapshot_token(newname
, &dst_twrp
);
4562 /* hardlink paths are never DFS. */
4563 ucf_flags
&= ~UCF_DFS_PATHNAME
;
4565 status
= filename_convert_dirfsp(ctx
,
4572 if (!NT_STATUS_IS_OK(status
)) {
4576 if (fsp
->base_fsp
) {
4577 /* No stream names. */
4578 return NT_STATUS_NOT_SUPPORTED
;
4581 DEBUG(10,("smb_file_link_information: "
4582 "SMB_FILE_LINK_INFORMATION (%s) %s -> %s\n",
4583 fsp_fnum_dbg(fsp
), fsp_str_dbg(fsp
),
4584 smb_fname_str_dbg(smb_fname_dst
)));
4585 status
= hardlink_internals(ctx
,
4592 TALLOC_FREE(smb_fname_dst
);
4597 /****************************************************************************
4598 Deal with SMB_FILE_RENAME_INFORMATION.
4599 ****************************************************************************/
4601 static NTSTATUS
smb_file_rename_information(connection_struct
*conn
,
4602 struct smb_request
*req
,
4606 struct smb_filename
*smb_fname_src
)
4611 char *newname
= NULL
;
4612 struct files_struct
*dst_dirfsp
= NULL
;
4613 struct smb_filename
*smb_fname_dst
= NULL
;
4614 const char *dst_original_lcomp
= NULL
;
4615 NTSTATUS status
= NT_STATUS_OK
;
4617 TALLOC_CTX
*ctx
= talloc_tos();
4619 if (total_data
< 13) {
4620 return NT_STATUS_INVALID_PARAMETER
;
4623 overwrite
= (CVAL(pdata
,0) != 0);
4624 root_fid
= IVAL(pdata
,4);
4625 len
= IVAL(pdata
,8);
4627 if (len
> (total_data
- 12) || (len
== 0) || (root_fid
!= 0)) {
4628 return NT_STATUS_INVALID_PARAMETER
;
4631 if (req
->posix_pathnames
) {
4632 srvstr_get_path_posix(ctx
,
4641 srvstr_get_path(ctx
,
4650 if (!NT_STATUS_IS_OK(status
)) {
4654 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
4657 /* Check the new name has no '/' characters. */
4658 if (strchr_m(newname
, '/')) {
4659 return NT_STATUS_NOT_SUPPORTED
;
4662 if (fsp
&& fsp
->base_fsp
) {
4663 /* newname must be a stream name. */
4664 if (newname
[0] != ':') {
4665 return NT_STATUS_NOT_SUPPORTED
;
4668 /* Create an smb_fname to call rename_internals_fsp() with. */
4669 smb_fname_dst
= synthetic_smb_fname(talloc_tos(),
4670 fsp
->base_fsp
->fsp_name
->base_name
,
4673 fsp
->base_fsp
->fsp_name
->twrp
,
4674 fsp
->base_fsp
->fsp_name
->flags
);
4675 if (smb_fname_dst
== NULL
) {
4676 status
= NT_STATUS_NO_MEMORY
;
4681 * Get the original last component, since
4682 * rename_internals_fsp() requires it.
4684 dst_original_lcomp
= get_original_lcomp(smb_fname_dst
,
4688 if (dst_original_lcomp
== NULL
) {
4689 status
= NT_STATUS_NO_MEMORY
;
4695 * Build up an smb_fname_dst based on the filename passed in.
4696 * We basically just strip off the last component, and put on
4697 * the newname instead.
4699 char *base_name
= NULL
;
4700 uint32_t ucf_flags
= ucf_flags_from_smb_request(req
);
4701 NTTIME dst_twrp
= 0;
4703 /* newname must *not* be a stream name. */
4704 if (newname
[0] == ':') {
4705 return NT_STATUS_NOT_SUPPORTED
;
4709 * Strip off the last component (filename) of the path passed
4712 base_name
= talloc_strdup(ctx
, smb_fname_src
->base_name
);
4714 return NT_STATUS_NO_MEMORY
;
4716 p
= strrchr_m(base_name
, '/');
4720 base_name
= talloc_strdup(ctx
, "");
4722 return NT_STATUS_NO_MEMORY
;
4725 /* Append the new name. */
4726 base_name
= talloc_asprintf_append(base_name
,
4730 return NT_STATUS_NO_MEMORY
;
4733 if (ucf_flags
& UCF_GMT_PATHNAME
) {
4734 extract_snapshot_token(base_name
, &dst_twrp
);
4737 /* The newname is *not* a DFS path. */
4738 ucf_flags
&= ~UCF_DFS_PATHNAME
;
4740 status
= filename_convert_dirfsp(ctx
,
4748 if (!NT_STATUS_IS_OK(status
)) {
4751 dst_original_lcomp
= get_original_lcomp(smb_fname_dst
,
4755 if (dst_original_lcomp
== NULL
) {
4756 status
= NT_STATUS_NO_MEMORY
;
4761 if (fsp
!= NULL
&& fsp
->fsp_flags
.is_fsa
) {
4762 DEBUG(10,("smb_file_rename_information: "
4763 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
4764 fsp_fnum_dbg(fsp
), fsp_str_dbg(fsp
),
4765 smb_fname_str_dbg(smb_fname_dst
)));
4766 status
= rename_internals_fsp(conn
,
4773 DEBUG(10,("smb_file_rename_information: "
4774 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
4775 smb_fname_str_dbg(smb_fname_src
),
4776 smb_fname_str_dbg(smb_fname_dst
)));
4777 status
= rename_internals(ctx
,
4780 NULL
, /* src_dirfsp */
4786 FILE_WRITE_ATTRIBUTES
);
4789 TALLOC_FREE(smb_fname_dst
);
4793 /****************************************************************************
4794 Deal with SMB_SET_FILE_BASIC_INFO.
4795 ****************************************************************************/
4797 static NTSTATUS
smb_set_file_basic_info(connection_struct
*conn
,
4801 struct smb_filename
*smb_fname
)
4803 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
4804 struct smb_file_time ft
;
4805 uint32_t dosmode
= 0;
4806 NTSTATUS status
= NT_STATUS_OK
;
4808 init_smb_file_time(&ft
);
4810 if (total_data
< 36) {
4811 return NT_STATUS_INVALID_PARAMETER
;
4815 return NT_STATUS_INVALID_HANDLE
;
4818 status
= check_any_access_fsp(fsp
, FILE_WRITE_ATTRIBUTES
);
4819 if (!NT_STATUS_IS_OK(status
)) {
4823 /* Set the attributes */
4824 dosmode
= IVAL(pdata
,32);
4825 status
= smb_set_file_dosmode(conn
, fsp
, dosmode
);
4826 if (!NT_STATUS_IS_OK(status
)) {
4831 ft
.create_time
= pull_long_date_full_timespec(pdata
);
4834 ft
.atime
= pull_long_date_full_timespec(pdata
+8);
4837 ft
.mtime
= pull_long_date_full_timespec(pdata
+16);
4840 ft
.ctime
= pull_long_date_full_timespec(pdata
+24);
4842 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
4843 smb_fname_str_dbg(smb_fname
)));
4845 status
= smb_set_file_time(conn
, fsp
, smb_fname
, &ft
, true);
4846 if (!NT_STATUS_IS_OK(status
)) {
4850 if (fsp
->fsp_flags
.modified
) {
4851 trigger_write_time_update_immediate(fsp
);
4853 return NT_STATUS_OK
;
4856 /****************************************************************************
4857 Deal with SMB_INFO_STANDARD.
4858 ****************************************************************************/
4860 static NTSTATUS
smb_set_info_standard(connection_struct
*conn
,
4864 struct smb_filename
*smb_fname
)
4867 struct smb_file_time ft
;
4869 init_smb_file_time(&ft
);
4871 if (total_data
< 12) {
4872 return NT_STATUS_INVALID_PARAMETER
;
4876 return NT_STATUS_INVALID_HANDLE
;
4880 ft
.create_time
= time_t_to_full_timespec(srv_make_unix_date2(pdata
));
4882 ft
.atime
= time_t_to_full_timespec(srv_make_unix_date2(pdata
+4));
4884 ft
.mtime
= time_t_to_full_timespec(srv_make_unix_date2(pdata
+8));
4886 DEBUG(10,("smb_set_info_standard: file %s\n",
4887 smb_fname_str_dbg(smb_fname
)));
4889 status
= check_any_access_fsp(fsp
, FILE_WRITE_ATTRIBUTES
);
4890 if (!NT_STATUS_IS_OK(status
)) {
4894 status
= smb_set_file_time(conn
, fsp
, smb_fname
, &ft
, true);
4895 if (!NT_STATUS_IS_OK(status
)) {
4899 if (fsp
->fsp_flags
.modified
) {
4900 trigger_write_time_update_immediate(fsp
);
4902 return NT_STATUS_OK
;
4905 /****************************************************************************
4906 Deal with SMB_SET_FILE_ALLOCATION_INFO.
4907 ****************************************************************************/
4909 static NTSTATUS
smb_set_file_allocation_info(connection_struct
*conn
,
4910 struct smb_request
*req
,
4914 struct smb_filename
*smb_fname
)
4916 uint64_t allocation_size
= 0;
4917 NTSTATUS status
= NT_STATUS_OK
;
4918 files_struct
*new_fsp
= NULL
;
4920 if (!VALID_STAT(smb_fname
->st
)) {
4921 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
4924 if (total_data
< 8) {
4925 return NT_STATUS_INVALID_PARAMETER
;
4928 allocation_size
= (uint64_t)IVAL(pdata
,0);
4929 allocation_size
|= (((uint64_t)IVAL(pdata
,4)) << 32);
4930 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
4931 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname
),
4932 (double)allocation_size
));
4934 if (allocation_size
) {
4935 allocation_size
= smb_roundup(conn
, allocation_size
);
4938 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
4939 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname
),
4940 (double)allocation_size
));
4943 !fsp
->fsp_flags
.is_pathref
&&
4944 fsp_get_io_fd(fsp
) != -1)
4946 /* Open file handle. */
4947 status
= check_any_access_fsp(fsp
, FILE_WRITE_DATA
);
4948 if (!NT_STATUS_IS_OK(status
)) {
4952 /* Only change if needed. */
4953 if (allocation_size
!= get_file_size_stat(&smb_fname
->st
)) {
4954 if (vfs_allocate_file_space(fsp
, allocation_size
) == -1) {
4955 return map_nt_error_from_unix(errno
);
4958 /* But always update the time. */
4960 * This is equivalent to a write. Ensure it's seen immediately
4961 * if there are no pending writes.
4963 trigger_write_time_update_immediate(fsp
);
4964 return NT_STATUS_OK
;
4967 /* Pathname or stat or directory file. */
4968 status
= SMB_VFS_CREATE_FILE(
4972 smb_fname
, /* fname */
4973 FILE_WRITE_DATA
, /* access_mask */
4974 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
4976 FILE_OPEN
, /* create_disposition*/
4977 0, /* create_options */
4978 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
4979 0, /* oplock_request */
4981 0, /* allocation_size */
4982 0, /* private_flags */
4985 &new_fsp
, /* result */
4987 NULL
, NULL
); /* create context */
4989 if (!NT_STATUS_IS_OK(status
)) {
4990 /* NB. We check for open_was_deferred in the caller. */
4994 /* Only change if needed. */
4995 if (allocation_size
!= get_file_size_stat(&smb_fname
->st
)) {
4996 if (vfs_allocate_file_space(new_fsp
, allocation_size
) == -1) {
4997 status
= map_nt_error_from_unix(errno
);
4998 close_file_free(req
, &new_fsp
, NORMAL_CLOSE
);
5003 /* Changing the allocation size should set the last mod time. */
5005 * This is equivalent to a write. Ensure it's seen immediately
5006 * if there are no pending writes.
5008 trigger_write_time_update_immediate(new_fsp
);
5009 close_file_free(req
, &new_fsp
, NORMAL_CLOSE
);
5010 return NT_STATUS_OK
;
5013 /****************************************************************************
5014 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
5015 ****************************************************************************/
5017 static NTSTATUS
smb_set_file_end_of_file_info(connection_struct
*conn
,
5018 struct smb_request
*req
,
5022 struct smb_filename
*smb_fname
,
5023 bool fail_after_createfile
)
5027 if (total_data
< 8) {
5028 return NT_STATUS_INVALID_PARAMETER
;
5031 size
= IVAL(pdata
,0);
5032 size
|= (((off_t
)IVAL(pdata
,4)) << 32);
5033 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
5034 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname
),
5037 return smb_set_file_size(conn
, req
,
5042 fail_after_createfile
);
5045 NTSTATUS
smbd_do_setfilepathinfo(connection_struct
*conn
,
5046 struct smb_request
*req
,
5047 TALLOC_CTX
*mem_ctx
,
5048 uint16_t info_level
,
5050 struct smb_filename
*smb_fname
,
5051 char **ppdata
, int total_data
,
5054 char *pdata
= *ppdata
;
5055 NTSTATUS status
= NT_STATUS_OK
;
5056 int data_return_size
= 0;
5060 DEBUG(3,("smbd_do_setfilepathinfo: %s (%s) info_level=%d "
5061 "totdata=%d\n", smb_fname_str_dbg(smb_fname
),
5063 info_level
, total_data
));
5065 switch (info_level
) {
5067 case SMB_INFO_STANDARD
:
5069 status
= smb_set_info_standard(conn
,
5077 case SMB_INFO_SET_EA
:
5079 status
= smb_info_set_ea(conn
,
5087 case SMB_SET_FILE_BASIC_INFO
:
5088 case SMB_FILE_BASIC_INFORMATION
:
5090 status
= smb_set_file_basic_info(conn
,
5098 case SMB_FILE_ALLOCATION_INFORMATION
:
5099 case SMB_SET_FILE_ALLOCATION_INFO
:
5101 status
= smb_set_file_allocation_info(conn
, req
,
5109 case SMB_FILE_END_OF_FILE_INFORMATION
:
5110 case SMB_SET_FILE_END_OF_FILE_INFO
:
5113 * XP/Win7 both fail after the createfile with
5114 * SMB_SET_FILE_END_OF_FILE_INFO but not
5115 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
5116 * The level is known here, so pass it down
5120 (info_level
== SMB_SET_FILE_END_OF_FILE_INFO
);
5122 status
= smb_set_file_end_of_file_info(conn
, req
,
5131 case SMB_FILE_DISPOSITION_INFORMATION
:
5132 case SMB_SET_FILE_DISPOSITION_INFO
: /* Set delete on close for open file. */
5135 /* JRA - We used to just ignore this on a path ?
5136 * Shouldn't this be invalid level on a pathname
5139 if (tran_call
!= TRANSACT2_SETFILEINFO
) {
5140 return ERROR_NT(NT_STATUS_INVALID_LEVEL
);
5143 status
= smb_set_file_disposition_info(conn
,
5151 case SMB_FILE_POSITION_INFORMATION
:
5153 status
= smb_file_position_information(conn
,
5160 case SMB_FILE_FULL_EA_INFORMATION
:
5162 status
= smb_set_file_full_ea_info(conn
,
5169 /* From tridge Samba4 :
5170 * MODE_INFORMATION in setfileinfo (I have no
5171 * idea what "mode information" on a file is - it takes a value of 0,
5172 * 2, 4 or 6. What could it be?).
5175 case SMB_FILE_MODE_INFORMATION
:
5177 status
= smb_file_mode_information(conn
,
5183 /* [MS-SMB2] 3.3.5.21.1 states we MUST fail with STATUS_NOT_SUPPORTED. */
5184 case SMB_FILE_VALID_DATA_LENGTH_INFORMATION
:
5185 case SMB_FILE_SHORT_NAME_INFORMATION
:
5186 return NT_STATUS_NOT_SUPPORTED
;
5188 case SMB_FILE_RENAME_INFORMATION
:
5190 status
= smb_file_rename_information(conn
, req
,
5196 case SMB2_FILE_RENAME_INFORMATION_INTERNAL
:
5198 /* SMB2 rename information. */
5199 status
= smb2_file_rename_information(conn
, req
,
5205 case SMB_FILE_LINK_INFORMATION
:
5207 if (conn_using_smb2(conn
->sconn
)) {
5208 status
= smb2_file_link_information(conn
,
5215 status
= smb_file_link_information(conn
,
5226 return NT_STATUS_INVALID_LEVEL
;
5229 if (!NT_STATUS_IS_OK(status
)) {
5233 *ret_data_size
= data_return_size
;
5234 return NT_STATUS_OK
;
5237 static uint32_t generate_volume_serial_number(
5238 const struct loadparm_substitution
*lp_sub
,
5241 int serial
= lp_volume_serial_number(snum
);
5242 return serial
!= -1 ? serial
:
5243 str_checksum(lp_servicename(talloc_tos(), lp_sub
, snum
)) ^
5244 (str_checksum(get_local_machine_name())<<16);