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"
51 #define DIR_ENTRY_SAFETY_MARGIN 4096
53 static uint32_t generate_volume_serial_number(
54 const struct loadparm_substitution
*lp_sub
,
57 /****************************************************************************
58 Check if an open file handle is a symlink.
59 ****************************************************************************/
61 NTSTATUS
refuse_symlink_fsp(const files_struct
*fsp
)
64 if (!VALID_STAT(fsp
->fsp_name
->st
)) {
65 return NT_STATUS_ACCESS_DENIED
;
67 if (S_ISLNK(fsp
->fsp_name
->st
.st_ex_mode
)) {
68 return NT_STATUS_ACCESS_DENIED
;
70 if (fsp_get_pathref_fd(fsp
) == -1) {
71 return NT_STATUS_ACCESS_DENIED
;
76 NTSTATUS
check_access_fsp(struct files_struct
*fsp
,
79 if (!fsp
->fsp_flags
.is_fsa
) {
80 return smbd_check_access_rights_fsp(fsp
->conn
->cwd_fsp
,
85 if (!(fsp
->access_mask
& access_mask
)) {
86 return NT_STATUS_ACCESS_DENIED
;
91 /********************************************************************
92 Roundup a value to the nearest allocation roundup size boundary.
93 Only do this for Windows clients.
94 ********************************************************************/
96 uint64_t smb_roundup(connection_struct
*conn
, uint64_t val
)
98 uint64_t rval
= lp_allocation_roundup_size(SNUM(conn
));
100 /* Only roundup for Windows clients. */
101 enum remote_arch_types ra_type
= get_remote_arch();
102 if (rval
&& (ra_type
!= RA_SAMBA
) && (ra_type
!= RA_CIFSFS
)) {
103 val
= SMB_ROUNDUP(val
,rval
);
108 /****************************************************************************
109 Utility functions for dealing with extended attributes.
110 ****************************************************************************/
112 /****************************************************************************
113 Refuse to allow clients to overwrite our private xattrs.
114 ****************************************************************************/
116 bool samba_private_attr_name(const char *unix_ea_name
)
118 bool prohibited
= false;
120 prohibited
|= strequal(unix_ea_name
, SAMBA_POSIX_INHERITANCE_EA_NAME
);
121 prohibited
|= strequal(unix_ea_name
, SAMBA_XATTR_DOS_ATTRIB
);
122 prohibited
|= strequal(unix_ea_name
, SAMBA_XATTR_MARKER
);
123 prohibited
|= strequal(unix_ea_name
, XATTR_NTACL_NAME
);
124 prohibited
|= strequal(unix_ea_name
, AFPINFO_EA_NETATALK
);
130 if (strncasecmp_m(unix_ea_name
, SAMBA_XATTR_DOSSTREAM_PREFIX
,
131 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX
)) == 0) {
137 /****************************************************************************
138 Get one EA value. Fill in a struct ea_struct.
139 ****************************************************************************/
141 NTSTATUS
get_ea_value_fsp(TALLOC_CTX
*mem_ctx
,
144 struct ea_struct
*pea
)
146 /* Get the value of this xattr. Max size is 64k. */
147 size_t attr_size
= 256;
150 size_t max_xattr_size
= 0;
153 return NT_STATUS_INVALID_HANDLE
;
156 max_xattr_size
= lp_smbd_max_xattr_size(SNUM(fsp
->conn
));
160 val
= talloc_realloc(mem_ctx
, val
, char, attr_size
);
162 return NT_STATUS_NO_MEMORY
;
165 sizeret
= SMB_VFS_FGETXATTR(fsp
, ea_name
, val
, attr_size
);
166 if (sizeret
== -1 && errno
== ERANGE
&& attr_size
< max_xattr_size
) {
167 attr_size
= max_xattr_size
;
172 return map_nt_error_from_unix(errno
);
175 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name
, (unsigned int)sizeret
));
176 dump_data(10, (uint8_t *)val
, sizeret
);
179 if (strnequal(ea_name
, "user.", 5)) {
180 pea
->name
= talloc_strdup(mem_ctx
, &ea_name
[5]);
182 pea
->name
= talloc_strdup(mem_ctx
, ea_name
);
184 if (pea
->name
== NULL
) {
186 return NT_STATUS_NO_MEMORY
;
188 pea
->value
.data
= (unsigned char *)val
;
189 pea
->value
.length
= (size_t)sizeret
;
193 NTSTATUS
get_ea_names_from_fsp(TALLOC_CTX
*mem_ctx
,
199 /* Get a list of all xattrs. Max namesize is 64k. */
200 size_t ea_namelist_size
= 1024;
201 char *ea_namelist
= smallbuf
;
202 char *to_free
= NULL
;
207 ssize_t sizeret
= -1;
217 * Callers may pass fsp == NULL when passing smb_fname->fsp of a
218 * symlink. This is ok, handle it here, by just return no EA's
224 /* should be the case that fsp != NULL */
225 SMB_ASSERT(fsp
!= NULL
);
227 sizeret
= SMB_VFS_FLISTXATTR(fsp
, ea_namelist
,
230 if ((sizeret
== -1) && (errno
== ERANGE
)) {
231 ea_namelist_size
= 65536;
232 ea_namelist
= talloc_array(mem_ctx
, char, ea_namelist_size
);
233 if (ea_namelist
== NULL
) {
234 return NT_STATUS_NO_MEMORY
;
236 to_free
= ea_namelist
;
238 sizeret
= SMB_VFS_FLISTXATTR(fsp
, ea_namelist
,
243 status
= map_nt_error_from_unix(errno
);
244 TALLOC_FREE(to_free
);
248 DBG_DEBUG("ea_namelist size = %zd\n", sizeret
);
251 TALLOC_FREE(to_free
);
256 * Ensure the result is 0-terminated
259 if (ea_namelist
[sizeret
-1] != '\0') {
260 TALLOC_FREE(to_free
);
261 return NT_STATUS_INTERNAL_ERROR
;
269 for (p
= ea_namelist
; p
- ea_namelist
< sizeret
; p
+= strlen(p
)+1) {
273 *pnum_names
= num_names
;
275 if (pnames
== NULL
) {
276 TALLOC_FREE(to_free
);
280 names
= talloc_array(mem_ctx
, char *, num_names
);
282 DEBUG(0, ("talloc failed\n"));
283 TALLOC_FREE(to_free
);
284 return NT_STATUS_NO_MEMORY
;
287 if (ea_namelist
== smallbuf
) {
288 ea_namelist
= talloc_memdup(names
, smallbuf
, sizeret
);
289 if (ea_namelist
== NULL
) {
291 return NT_STATUS_NO_MEMORY
;
294 talloc_steal(names
, ea_namelist
);
296 ea_namelist
= talloc_realloc(names
, ea_namelist
, char,
298 if (ea_namelist
== NULL
) {
300 return NT_STATUS_NO_MEMORY
;
306 for (p
= ea_namelist
; p
- ea_namelist
< sizeret
; p
+= strlen(p
)+1) {
307 names
[num_names
++] = p
;
315 /****************************************************************************
316 Return a linked list of the total EA's. Plus the total size
317 ****************************************************************************/
319 static NTSTATUS
get_ea_list_from_fsp(TALLOC_CTX
*mem_ctx
,
321 size_t *pea_total_len
,
322 struct ea_list
**ea_list
)
324 /* Get a list of all xattrs. Max namesize is 64k. */
327 struct ea_list
*ea_list_head
= NULL
;
328 bool posix_pathnames
= false;
339 if (!lp_ea_support(SNUM(fsp
->conn
))) {
343 if (fsp_is_alternate_stream(fsp
)) {
344 return NT_STATUS_INVALID_PARAMETER
;
347 posix_pathnames
= (fsp
->fsp_name
->flags
& SMB_FILENAME_POSIX_PATH
);
349 status
= get_ea_names_from_fsp(talloc_tos(),
354 if (!NT_STATUS_IS_OK(status
)) {
358 if (num_names
== 0) {
362 for (i
=0; i
<num_names
; i
++) {
363 struct ea_list
*listp
;
367 * POSIX EA names are divided into several namespaces by
368 * means of string prefixes. Usually, the system controls
369 * semantics for each namespace, but the 'user' namespace is
370 * available for arbitrary use, which comes closest to
371 * Windows EA semantics. Hence, we map POSIX EAs from the
372 * 'user' namespace to Windows EAs, and just ignore all the
373 * other namespaces. Also, a few specific names in the 'user'
374 * namespace are used by Samba internally. Filter them out as
375 * well, and only present the EAs that are available for
378 if (!strnequal(names
[i
], "user.", 5)
379 || samba_private_attr_name(names
[i
]))
383 * Filter out any underlying POSIX EA names
384 * that a Windows client can't handle.
386 if (!posix_pathnames
&&
387 is_invalid_windows_ea_name(names
[i
])) {
391 listp
= talloc(mem_ctx
, struct ea_list
);
393 return NT_STATUS_NO_MEMORY
;
396 status
= get_ea_value_fsp(listp
,
401 if (!NT_STATUS_IS_OK(status
)) {
406 if (listp
->ea
.value
.length
== 0) {
408 * We can never return a zero length EA.
409 * Windows reports the EA's as corrupted.
413 } else if (listp
->ea
.value
.length
> 65536) {
415 * SMB clients may report error with file
416 * if large EA is presented to them.
418 DBG_ERR("EA [%s] on file [%s] exceeds "
419 "maximum permitted EA size of 64KiB: %zu\n.",
420 listp
->ea
.name
, fsp_str_dbg(fsp
),
421 listp
->ea
.value
.length
);
426 push_ascii_fstring(dos_ea_name
, listp
->ea
.name
);
429 4 + strlen(dos_ea_name
) + 1 + listp
->ea
.value
.length
;
431 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
432 "= %u\n", (unsigned int)*pea_total_len
, dos_ea_name
,
433 (unsigned int)listp
->ea
.value
.length
));
435 DLIST_ADD_END(ea_list_head
, listp
);
439 /* Add on 4 for total length. */
440 if (*pea_total_len
) {
444 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
445 (unsigned int)*pea_total_len
));
447 *ea_list
= ea_list_head
;
451 /****************************************************************************
452 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
454 ****************************************************************************/
456 static unsigned int fill_ea_buffer(TALLOC_CTX
*mem_ctx
, char *pdata
, unsigned int total_data_size
,
457 connection_struct
*conn
, struct ea_list
*ea_list
)
459 unsigned int ret_data_size
= 4;
462 SMB_ASSERT(total_data_size
>= 4);
464 if (!lp_ea_support(SNUM(conn
))) {
469 for (p
= pdata
+ 4; ea_list
; ea_list
= ea_list
->next
) {
472 push_ascii_fstring(dos_ea_name
, ea_list
->ea
.name
);
473 dos_namelen
= strlen(dos_ea_name
);
474 if (dos_namelen
> 255 || dos_namelen
== 0) {
477 if (ea_list
->ea
.value
.length
> 65535) {
480 if (4 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
> total_data_size
) {
484 /* We know we have room. */
485 SCVAL(p
,0,ea_list
->ea
.flags
);
486 SCVAL(p
,1,dos_namelen
);
487 SSVAL(p
,2,ea_list
->ea
.value
.length
);
488 strlcpy(p
+4, dos_ea_name
, dos_namelen
+1);
489 if (ea_list
->ea
.value
.length
> 0) {
490 memcpy(p
+ 4 + dos_namelen
+ 1,
491 ea_list
->ea
.value
.data
,
492 ea_list
->ea
.value
.length
);
495 total_data_size
-= 4 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
;
496 p
+= 4 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
;
499 ret_data_size
= PTR_DIFF(p
, pdata
);
500 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size
));
501 SIVAL(pdata
,0,ret_data_size
);
502 return ret_data_size
;
505 static NTSTATUS
fill_ea_chained_buffer(TALLOC_CTX
*mem_ctx
,
507 unsigned int total_data_size
,
508 unsigned int *ret_data_size
,
509 connection_struct
*conn
,
510 struct ea_list
*ea_list
)
512 uint8_t *p
= (uint8_t *)pdata
;
513 uint8_t *last_start
= NULL
;
514 bool do_store_data
= (pdata
!= NULL
);
518 if (!lp_ea_support(SNUM(conn
))) {
519 return NT_STATUS_NO_EAS_ON_FILE
;
522 for (; ea_list
; ea_list
= ea_list
->next
) {
528 if (last_start
!= NULL
&& do_store_data
) {
529 SIVAL(last_start
, 0, PTR_DIFF(p
, last_start
));
533 push_ascii_fstring(dos_ea_name
, ea_list
->ea
.name
);
534 dos_namelen
= strlen(dos_ea_name
);
535 if (dos_namelen
> 255 || dos_namelen
== 0) {
536 return NT_STATUS_INTERNAL_ERROR
;
538 if (ea_list
->ea
.value
.length
> 65535) {
539 return NT_STATUS_INTERNAL_ERROR
;
542 this_size
= 0x08 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
;
545 pad
= (4 - (this_size
% 4)) % 4;
550 if (this_size
> total_data_size
) {
551 return NT_STATUS_INFO_LENGTH_MISMATCH
;
554 /* We know we have room. */
555 SIVAL(p
, 0x00, 0); /* next offset */
556 SCVAL(p
, 0x04, ea_list
->ea
.flags
);
557 SCVAL(p
, 0x05, dos_namelen
);
558 SSVAL(p
, 0x06, ea_list
->ea
.value
.length
);
559 strlcpy((char *)(p
+0x08), dos_ea_name
, dos_namelen
+1);
560 memcpy(p
+ 0x08 + dos_namelen
+ 1, ea_list
->ea
.value
.data
, ea_list
->ea
.value
.length
);
562 memset(p
+ 0x08 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
,
566 total_data_size
-= this_size
;
572 *ret_data_size
= PTR_DIFF(p
, pdata
);
573 DEBUG(10,("fill_ea_chained_buffer: data_size = %u\n", *ret_data_size
));
577 unsigned int estimate_ea_size(files_struct
*fsp
)
579 size_t total_ea_len
= 0;
581 struct ea_list
*ea_list
= NULL
;
589 if (!lp_ea_support(SNUM(fsp
->conn
))) {
593 mem_ctx
= talloc_stackframe();
595 /* If this is a stream fsp, then we need to instead find the
596 * estimated ea len from the main file, not the stream
597 * (streams cannot have EAs), but the estimate isn't just 0 in
599 fsp
= metadata_fsp(fsp
);
600 (void)get_ea_list_from_fsp(mem_ctx
,
605 if(fsp
->conn
->sconn
->using_smb2
) {
606 unsigned int ret_data_size
;
608 * We're going to be using fill_ea_chained_buffer() to
609 * marshall EA's - this size is significantly larger
610 * than the SMB1 buffer. Re-calculate the size without
613 status
= fill_ea_chained_buffer(mem_ctx
,
619 if (!NT_STATUS_IS_OK(status
)) {
622 total_ea_len
= ret_data_size
;
624 TALLOC_FREE(mem_ctx
);
628 /****************************************************************************
629 Ensure the EA name is case insensitive by matching any existing EA name.
630 ****************************************************************************/
632 static void canonicalize_ea_name(files_struct
*fsp
,
633 fstring unix_ea_name
)
636 TALLOC_CTX
*mem_ctx
= talloc_tos();
637 struct ea_list
*ea_list
;
638 NTSTATUS status
= get_ea_list_from_fsp(mem_ctx
,
642 if (!NT_STATUS_IS_OK(status
)) {
646 for (; ea_list
; ea_list
= ea_list
->next
) {
647 if (strequal(&unix_ea_name
[5], ea_list
->ea
.name
)) {
648 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
649 &unix_ea_name
[5], ea_list
->ea
.name
));
650 strlcpy(&unix_ea_name
[5], ea_list
->ea
.name
, sizeof(fstring
)-5);
656 /****************************************************************************
657 Set or delete an extended attribute.
658 ****************************************************************************/
660 NTSTATUS
set_ea(connection_struct
*conn
, files_struct
*fsp
,
661 struct ea_list
*ea_list
)
664 bool posix_pathnames
= false;
666 if (!lp_ea_support(SNUM(conn
))) {
667 return NT_STATUS_EAS_NOT_SUPPORTED
;
671 return NT_STATUS_INVALID_HANDLE
;
674 posix_pathnames
= (fsp
->fsp_name
->flags
& SMB_FILENAME_POSIX_PATH
);
676 status
= refuse_symlink_fsp(fsp
);
677 if (!NT_STATUS_IS_OK(status
)) {
681 status
= check_access_fsp(fsp
, FILE_WRITE_EA
);
682 if (!NT_STATUS_IS_OK(status
)) {
686 /* Setting EAs on streams isn't supported. */
687 if (fsp_is_alternate_stream(fsp
)) {
688 return NT_STATUS_INVALID_PARAMETER
;
692 * Filter out invalid Windows EA names - before
693 * we set *any* of them.
696 if (!posix_pathnames
&& ea_list_has_invalid_name(ea_list
)) {
697 return STATUS_INVALID_EA_NAME
;
700 for (;ea_list
; ea_list
= ea_list
->next
) {
702 fstring unix_ea_name
;
705 * Complementing the forward mapping from POSIX EAs to
706 * Windows EAs in get_ea_list_from_fsp(), here we map in the
707 * opposite direction from Windows EAs to the 'user' namespace
708 * of POSIX EAs. Hence, all POSIX EA names the we set here must
709 * start with a 'user.' prefix.
711 fstrcpy(unix_ea_name
, "user.");
712 fstrcat(unix_ea_name
, ea_list
->ea
.name
);
714 canonicalize_ea_name(fsp
, unix_ea_name
);
716 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name
, (unsigned int)ea_list
->ea
.value
.length
));
718 if (samba_private_attr_name(unix_ea_name
)) {
719 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name
));
720 return NT_STATUS_ACCESS_DENIED
;
723 if (ea_list
->ea
.value
.length
== 0) {
724 /* Remove the attribute. */
725 DBG_DEBUG("deleting ea name %s on "
726 "file %s by file descriptor.\n",
727 unix_ea_name
, fsp_str_dbg(fsp
));
728 ret
= SMB_VFS_FREMOVEXATTR(fsp
, unix_ea_name
);
730 /* Removing a non existent attribute always succeeds. */
731 if (ret
== -1 && errno
== ENOATTR
) {
732 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
738 DEBUG(10,("set_ea: setting ea name %s on file "
739 "%s by file descriptor.\n",
740 unix_ea_name
, fsp_str_dbg(fsp
)));
741 ret
= SMB_VFS_FSETXATTR(fsp
, unix_ea_name
,
742 ea_list
->ea
.value
.data
, ea_list
->ea
.value
.length
, 0);
747 if (errno
== ENOTSUP
) {
748 return NT_STATUS_EAS_NOT_SUPPORTED
;
751 return map_nt_error_from_unix(errno
);
758 /****************************************************************************
759 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
760 ****************************************************************************/
762 struct ea_list
*read_ea_list(TALLOC_CTX
*ctx
, const char *pdata
, size_t data_size
)
764 struct ea_list
*ea_list_head
= NULL
;
766 size_t bytes_used
= 0;
768 while (offset
< data_size
) {
769 struct ea_list
*eal
= read_ea_list_entry(ctx
, pdata
+ offset
, data_size
- offset
, &bytes_used
);
775 DLIST_ADD_END(ea_list_head
, eal
);
776 offset
+= bytes_used
;
782 /****************************************************************************
783 Count the total EA size needed.
784 ****************************************************************************/
786 static size_t ea_list_size(struct ea_list
*ealist
)
789 struct ea_list
*listp
;
792 for (listp
= ealist
; listp
; listp
= listp
->next
) {
793 push_ascii_fstring(dos_ea_name
, listp
->ea
.name
);
794 ret
+= 4 + strlen(dos_ea_name
) + 1 + listp
->ea
.value
.length
;
796 /* Add on 4 for total length. */
804 /****************************************************************************
805 Return a union of EA's from a file list and a list of names.
806 The TALLOC context for the two lists *MUST* be identical as we steal
807 memory from one list to add to another. JRA.
808 ****************************************************************************/
810 static struct ea_list
*ea_list_union(struct ea_list
*name_list
, struct ea_list
*file_list
, size_t *total_ea_len
)
812 struct ea_list
*nlistp
, *flistp
;
814 for (nlistp
= name_list
; nlistp
; nlistp
= nlistp
->next
) {
815 for (flistp
= file_list
; flistp
; flistp
= flistp
->next
) {
816 if (strequal(nlistp
->ea
.name
, flistp
->ea
.name
)) {
822 /* Copy the data from this entry. */
823 nlistp
->ea
.flags
= flistp
->ea
.flags
;
824 nlistp
->ea
.value
= flistp
->ea
.value
;
827 nlistp
->ea
.flags
= 0;
828 ZERO_STRUCT(nlistp
->ea
.value
);
832 *total_ea_len
= ea_list_size(name_list
);
836 /****************************************************************************
837 Return the filetype for UNIX extensions.
838 ****************************************************************************/
840 static uint32_t unix_filetype(mode_t mode
)
843 return UNIX_TYPE_FILE
;
844 else if(S_ISDIR(mode
))
845 return UNIX_TYPE_DIR
;
847 else if(S_ISLNK(mode
))
848 return UNIX_TYPE_SYMLINK
;
851 else if(S_ISCHR(mode
))
852 return UNIX_TYPE_CHARDEV
;
855 else if(S_ISBLK(mode
))
856 return UNIX_TYPE_BLKDEV
;
859 else if(S_ISFIFO(mode
))
860 return UNIX_TYPE_FIFO
;
863 else if(S_ISSOCK(mode
))
864 return UNIX_TYPE_SOCKET
;
867 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode
));
868 return UNIX_TYPE_UNKNOWN
;
871 /****************************************************************************
872 Map wire perms onto standard UNIX permissions. Obey share restrictions.
873 ****************************************************************************/
875 NTSTATUS
unix_perms_from_wire(connection_struct
*conn
,
876 const SMB_STRUCT_STAT
*psbuf
,
878 enum perm_type ptype
,
883 if (perms
== SMB_MODE_NO_CHANGE
) {
884 if (!VALID_STAT(*psbuf
)) {
885 return NT_STATUS_INVALID_PARAMETER
;
887 *ret_perms
= psbuf
->st_ex_mode
;
892 ret
= wire_perms_to_unix(perms
);
894 if (ptype
== PERM_NEW_FILE
) {
896 * "create mask"/"force create mode" are
897 * only applied to new files, not existing ones.
899 ret
&= lp_create_mask(SNUM(conn
));
900 /* Add in force bits */
901 ret
|= lp_force_create_mode(SNUM(conn
));
902 } else if (ptype
== PERM_NEW_DIR
) {
904 * "directory mask"/"force directory mode" are
905 * only applied to new directories, not existing ones.
907 ret
&= lp_directory_mask(SNUM(conn
));
908 /* Add in force bits */
909 ret
|= lp_force_directory_mode(SNUM(conn
));
916 /****************************************************************************
917 Get a level dependent lanman2 dir entry.
918 ****************************************************************************/
920 struct smbd_dirptr_lanman2_state
{
921 connection_struct
*conn
;
923 bool check_mangled_names
;
927 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX
*ctx
,
933 struct smbd_dirptr_lanman2_state
*state
=
934 (struct smbd_dirptr_lanman2_state
*)private_data
;
936 char mangled_name
[13]; /* mangled 8.3 name. */
940 /* Mangle fname if it's an illegal name. */
941 if (mangle_must_mangle(dname
, state
->conn
->params
)) {
943 * Slow path - ensure we can push the original name as UCS2. If
944 * not, then just don't return this name.
948 size_t len
= (strlen(dname
) + 2) * 4; /* Allow enough space. */
949 uint8_t *tmp
= talloc_array(talloc_tos(),
953 status
= srvstr_push(NULL
,
954 FLAGS2_UNICODE_STRINGS
,
963 if (!NT_STATUS_IS_OK(status
)) {
967 ok
= name_to_8_3(dname
, mangled_name
,
968 true, state
->conn
->params
);
972 fname
= mangled_name
;
977 got_match
= mask_match(fname
, mask
,
978 state
->case_sensitive
);
980 if(!got_match
&& state
->check_mangled_names
&&
981 !mangle_is_8_3(fname
, false, state
->conn
->params
)) {
983 * It turns out that NT matches wildcards against
984 * both long *and* short names. This may explain some
985 * of the wildcard weirdness from old DOS clients
986 * that some people have been seeing.... JRA.
988 /* Force the mangling into 8.3. */
989 ok
= name_to_8_3(fname
, mangled_name
,
990 false, state
->conn
->params
);
995 got_match
= mask_match(mangled_name
, mask
,
996 state
->case_sensitive
);
1003 *_fname
= talloc_strdup(ctx
, fname
);
1004 if (*_fname
== NULL
) {
1011 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX
*ctx
,
1013 struct files_struct
*dirfsp
,
1014 struct smb_filename
*smb_fname
,
1019 SMB_ASSERT(smb_fname
!= NULL
);
1020 *_mode
= fdos_mode(smb_fname
->fsp
);
1021 if (smb_fname
->fsp
!= NULL
) {
1022 smb_fname
->st
= smb_fname
->fsp
->fsp_name
->st
;
1028 static uint32_t get_dirent_ea_size(uint32_t mode
, files_struct
*fsp
)
1030 if (!(mode
& FILE_ATTRIBUTE_REPARSE_POINT
)) {
1031 unsigned ea_size
= estimate_ea_size(fsp
);
1034 return IO_REPARSE_TAG_DFS
;
1037 static NTSTATUS
smbd_marshall_dir_entry(TALLOC_CTX
*ctx
,
1038 connection_struct
*conn
,
1040 uint32_t info_level
,
1041 struct ea_list
*name_list
,
1042 bool check_mangled_names
,
1043 bool requires_resume_key
,
1046 const struct smb_filename
*smb_fname
,
1047 int space_remaining
,
1053 uint64_t *last_entry_off
)
1055 char *p
, *q
, *pdata
= *ppdata
;
1057 uint64_t file_size
= 0;
1058 uint64_t allocation_size
= 0;
1059 uint64_t file_id
= 0;
1061 struct timespec mdate_ts
= {0};
1062 struct timespec adate_ts
= {0};
1063 struct timespec cdate_ts
= {0};
1064 struct timespec create_date_ts
= {0};
1065 time_t mdate
= (time_t)0, adate
= (time_t)0, create_date
= (time_t)0;
1067 char *last_entry_ptr
;
1072 struct readdir_attr_data
*readdir_attr_data
= NULL
;
1075 if (!(mode
& FILE_ATTRIBUTE_DIRECTORY
)) {
1076 file_size
= get_file_size_stat(&smb_fname
->st
);
1078 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
, NULL
, &smb_fname
->st
);
1081 * Skip SMB_VFS_FREADDIR_ATTR if the directory entry is a symlink or
1084 if (smb_fname
->fsp
!= NULL
&&
1085 !(mode
& FILE_ATTRIBUTE_REPARSE_POINT
)) {
1086 status
= SMB_VFS_FREADDIR_ATTR(smb_fname
->fsp
,
1088 &readdir_attr_data
);
1089 if (!NT_STATUS_IS_OK(status
)) {
1090 if (!NT_STATUS_EQUAL(NT_STATUS_NOT_SUPPORTED
,
1097 file_id
= SMB_VFS_FS_FILE_ID(conn
, &smb_fname
->st
);
1099 mdate_ts
= smb_fname
->st
.st_ex_mtime
;
1100 adate_ts
= smb_fname
->st
.st_ex_atime
;
1101 create_date_ts
= get_create_timespec(conn
, NULL
, smb_fname
);
1102 cdate_ts
= get_change_timespec(conn
, NULL
, smb_fname
);
1104 if (lp_dos_filetime_resolution(SNUM(conn
))) {
1105 dos_filetime_timespec(&create_date_ts
);
1106 dos_filetime_timespec(&mdate_ts
);
1107 dos_filetime_timespec(&adate_ts
);
1108 dos_filetime_timespec(&cdate_ts
);
1111 create_date
= convert_timespec_to_time_t(create_date_ts
);
1112 mdate
= convert_timespec_to_time_t(mdate_ts
);
1113 adate
= convert_timespec_to_time_t(adate_ts
);
1115 /* align the record */
1116 SMB_ASSERT(align
>= 1);
1118 off
= (int)PTR_DIFF(pdata
, base_data
);
1119 pad
= (off
+ (align
-1)) & ~(align
-1);
1122 if (pad
&& pad
> space_remaining
) {
1123 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1124 "for padding (wanted %u, had %d)\n",
1127 return STATUS_MORE_ENTRIES
; /* Not finished - just out of space */
1131 /* initialize padding to 0 */
1133 memset(pdata
, 0, pad
);
1135 space_remaining
-= pad
;
1137 DEBUG(10,("smbd_marshall_dir_entry: space_remaining = %d\n",
1147 switch (info_level
) {
1148 case SMB_FIND_INFO_STANDARD
:
1149 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1150 if(requires_resume_key
) {
1154 srv_put_dos_date2(p
,0,create_date
);
1155 srv_put_dos_date2(p
,4,adate
);
1156 srv_put_dos_date2(p
,8,mdate
);
1157 SIVAL(p
,12,(uint32_t)file_size
);
1158 SIVAL(p
,16,(uint32_t)allocation_size
);
1162 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1163 p
+= ucs2_align(base_data
, p
, 0);
1165 status
= srvstr_push(base_data
, flags2
, p
,
1166 fname
, PTR_DIFF(end_data
, p
),
1167 STR_TERMINATE
, &len
);
1168 if (!NT_STATUS_IS_OK(status
)) {
1171 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1173 SCVAL(nameptr
, -1, len
- 2);
1175 SCVAL(nameptr
, -1, 0);
1179 SCVAL(nameptr
, -1, len
- 1);
1181 SCVAL(nameptr
, -1, 0);
1187 case SMB_FIND_EA_SIZE
:
1188 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
1189 if (requires_resume_key
) {
1193 srv_put_dos_date2(p
,0,create_date
);
1194 srv_put_dos_date2(p
,4,adate
);
1195 srv_put_dos_date2(p
,8,mdate
);
1196 SIVAL(p
,12,(uint32_t)file_size
);
1197 SIVAL(p
,16,(uint32_t)allocation_size
);
1200 ea_size
= estimate_ea_size(smb_fname
->fsp
);
1201 SIVAL(p
,22,ea_size
); /* Extended attributes */
1205 status
= srvstr_push(base_data
, flags2
,
1206 p
, fname
, PTR_DIFF(end_data
, p
),
1207 STR_TERMINATE
| STR_NOALIGN
, &len
);
1208 if (!NT_STATUS_IS_OK(status
)) {
1211 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1224 SCVAL(nameptr
,0,len
);
1226 SCVAL(p
,0,0); p
+= 1; /* Extra zero byte ? - why.. */
1229 case SMB_FIND_EA_LIST
:
1231 struct ea_list
*file_list
= NULL
;
1234 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
1236 return NT_STATUS_INVALID_PARAMETER
;
1238 if (requires_resume_key
) {
1242 srv_put_dos_date2(p
,0,create_date
);
1243 srv_put_dos_date2(p
,4,adate
);
1244 srv_put_dos_date2(p
,8,mdate
);
1245 SIVAL(p
,12,(uint32_t)file_size
);
1246 SIVAL(p
,16,(uint32_t)allocation_size
);
1248 p
+= 22; /* p now points to the EA area. */
1250 status
= get_ea_list_from_fsp(ctx
,
1252 &ea_len
, &file_list
);
1253 if (!NT_STATUS_IS_OK(status
)) {
1256 name_list
= ea_list_union(name_list
, file_list
, &ea_len
);
1258 /* We need to determine if this entry will fit in the space available. */
1259 /* Max string size is 255 bytes. */
1260 if (PTR_DIFF(p
+ 255 + ea_len
,pdata
) > space_remaining
) {
1261 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1262 "(wanted %u, had %d)\n",
1263 (unsigned int)PTR_DIFF(p
+ 255 + ea_len
,pdata
),
1265 return STATUS_MORE_ENTRIES
; /* Not finished - just out of space */
1268 /* Push the ea_data followed by the name. */
1269 p
+= fill_ea_buffer(ctx
, p
, space_remaining
, conn
, name_list
);
1271 status
= srvstr_push(base_data
, flags2
,
1272 p
+ 1, fname
, PTR_DIFF(end_data
, p
+1),
1273 STR_TERMINATE
| STR_NOALIGN
, &len
);
1274 if (!NT_STATUS_IS_OK(status
)) {
1277 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1290 SCVAL(nameptr
,0,len
);
1292 SCVAL(p
,0,0); p
+= 1; /* Extra zero byte ? - why.. */
1296 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
1297 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1298 was_8_3
= mangle_is_8_3(fname
, True
, conn
->params
);
1300 SIVAL(p
,0,reskey
); p
+= 4;
1301 put_long_date_full_timespec(conn
->ts_res
,p
,&create_date_ts
); p
+= 8;
1302 put_long_date_full_timespec(conn
->ts_res
,p
,&adate_ts
); p
+= 8;
1303 put_long_date_full_timespec(conn
->ts_res
,p
,&mdate_ts
); p
+= 8;
1304 put_long_date_full_timespec(conn
->ts_res
,p
,&cdate_ts
); p
+= 8;
1305 SOFF_T(p
,0,file_size
); p
+= 8;
1306 SOFF_T(p
,0,allocation_size
); p
+= 8;
1307 SIVAL(p
,0,mode
); p
+= 4;
1308 q
= p
; p
+= 4; /* q is placeholder for name length. */
1309 ea_size
= get_dirent_ea_size(mode
, smb_fname
->fsp
);
1310 SIVAL(p
, 0, ea_size
);
1312 /* Clear the short name buffer. This is
1313 * IMPORTANT as not doing so will trigger
1314 * a Win2k client bug. JRA.
1316 if (!was_8_3
&& check_mangled_names
) {
1317 char mangled_name
[13]; /* mangled 8.3 name. */
1318 if (!name_to_8_3(fname
,mangled_name
,True
,
1320 /* Error - mangle failed ! */
1321 memset(mangled_name
,'\0',12);
1323 mangled_name
[12] = 0;
1324 status
= srvstr_push(base_data
, flags2
,
1325 p
+2, mangled_name
, 24,
1326 STR_UPPER
|STR_UNICODE
, &len
);
1327 if (!NT_STATUS_IS_OK(status
)) {
1331 memset(p
+ 2 + len
,'\0',24 - len
);
1338 status
= srvstr_push(base_data
, flags2
, p
,
1339 fname
, PTR_DIFF(end_data
, p
),
1340 STR_TERMINATE_ASCII
, &len
);
1341 if (!NT_STATUS_IS_OK(status
)) {
1347 len
= PTR_DIFF(p
, pdata
);
1348 pad
= (len
+ (align
-1)) & ~(align
-1);
1350 * offset to the next entry, the caller
1351 * will overwrite it for the last entry
1352 * that's why we always include the padding
1356 * set padding to zero
1359 memset(p
, 0, pad
- len
);
1366 case SMB_FIND_FILE_DIRECTORY_INFO
:
1367 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1369 SIVAL(p
,0,reskey
); p
+= 4;
1370 put_long_date_full_timespec(conn
->ts_res
,p
,&create_date_ts
); p
+= 8;
1371 put_long_date_full_timespec(conn
->ts_res
,p
,&adate_ts
); p
+= 8;
1372 put_long_date_full_timespec(conn
->ts_res
,p
,&mdate_ts
); p
+= 8;
1373 put_long_date_full_timespec(conn
->ts_res
,p
,&cdate_ts
); p
+= 8;
1374 SOFF_T(p
,0,file_size
); p
+= 8;
1375 SOFF_T(p
,0,allocation_size
); p
+= 8;
1376 SIVAL(p
,0,mode
); p
+= 4;
1377 status
= srvstr_push(base_data
, flags2
,
1378 p
+ 4, fname
, PTR_DIFF(end_data
, p
+4),
1379 STR_TERMINATE_ASCII
, &len
);
1380 if (!NT_STATUS_IS_OK(status
)) {
1386 len
= PTR_DIFF(p
, pdata
);
1387 pad
= (len
+ (align
-1)) & ~(align
-1);
1389 * offset to the next entry, the caller
1390 * will overwrite it for the last entry
1391 * that's why we always include the padding
1395 * set padding to zero
1398 memset(p
, 0, pad
- len
);
1405 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
1406 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1408 SIVAL(p
,0,reskey
); p
+= 4;
1409 put_long_date_full_timespec(conn
->ts_res
,p
,&create_date_ts
); p
+= 8;
1410 put_long_date_full_timespec(conn
->ts_res
,p
,&adate_ts
); p
+= 8;
1411 put_long_date_full_timespec(conn
->ts_res
,p
,&mdate_ts
); p
+= 8;
1412 put_long_date_full_timespec(conn
->ts_res
,p
,&cdate_ts
); p
+= 8;
1413 SOFF_T(p
,0,file_size
); p
+= 8;
1414 SOFF_T(p
,0,allocation_size
); p
+= 8;
1415 SIVAL(p
,0,mode
); p
+= 4;
1416 q
= p
; p
+= 4; /* q is placeholder for name length. */
1417 ea_size
= get_dirent_ea_size(mode
, smb_fname
->fsp
);
1418 SIVAL(p
, 0, ea_size
);
1420 status
= srvstr_push(base_data
, flags2
, p
,
1421 fname
, PTR_DIFF(end_data
, p
),
1422 STR_TERMINATE_ASCII
, &len
);
1423 if (!NT_STATUS_IS_OK(status
)) {
1429 len
= PTR_DIFF(p
, pdata
);
1430 pad
= (len
+ (align
-1)) & ~(align
-1);
1432 * offset to the next entry, the caller
1433 * will overwrite it for the last entry
1434 * that's why we always include the padding
1438 * set padding to zero
1441 memset(p
, 0, pad
- len
);
1448 case SMB_FIND_FILE_NAMES_INFO
:
1449 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1451 SIVAL(p
,0,reskey
); p
+= 4;
1453 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1454 acl on a dir (tridge) */
1455 status
= srvstr_push(base_data
, flags2
, p
,
1456 fname
, PTR_DIFF(end_data
, p
),
1457 STR_TERMINATE_ASCII
, &len
);
1458 if (!NT_STATUS_IS_OK(status
)) {
1464 len
= PTR_DIFF(p
, pdata
);
1465 pad
= (len
+ (align
-1)) & ~(align
-1);
1467 * offset to the next entry, the caller
1468 * will overwrite it for the last entry
1469 * that's why we always include the padding
1473 * set padding to zero
1476 memset(p
, 0, pad
- len
);
1483 case SMB_FIND_ID_FULL_DIRECTORY_INFO
:
1484 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1486 SIVAL(p
,0,reskey
); p
+= 4;
1487 put_long_date_full_timespec(conn
->ts_res
,p
,&create_date_ts
); p
+= 8;
1488 put_long_date_full_timespec(conn
->ts_res
,p
,&adate_ts
); p
+= 8;
1489 put_long_date_full_timespec(conn
->ts_res
,p
,&mdate_ts
); p
+= 8;
1490 put_long_date_full_timespec(conn
->ts_res
,p
,&cdate_ts
); p
+= 8;
1491 SOFF_T(p
,0,file_size
); p
+= 8;
1492 SOFF_T(p
,0,allocation_size
); p
+= 8;
1493 SIVAL(p
,0,mode
); p
+= 4;
1494 q
= p
; p
+= 4; /* q is placeholder for name length. */
1495 ea_size
= get_dirent_ea_size(mode
, smb_fname
->fsp
);
1496 SIVAL(p
, 0, ea_size
);
1498 SIVAL(p
,0,0); p
+= 4; /* Unknown - reserved ? */
1499 SBVAL(p
,0,file_id
); p
+= 8;
1500 status
= srvstr_push(base_data
, flags2
, p
,
1501 fname
, PTR_DIFF(end_data
, p
),
1502 STR_TERMINATE_ASCII
, &len
);
1503 if (!NT_STATUS_IS_OK(status
)) {
1509 len
= PTR_DIFF(p
, pdata
);
1510 pad
= (len
+ (align
-1)) & ~(align
-1);
1512 * offset to the next entry, the caller
1513 * will overwrite it for the last entry
1514 * that's why we always include the padding
1518 * set padding to zero
1521 memset(p
, 0, pad
- len
);
1528 case SMB_FIND_ID_BOTH_DIRECTORY_INFO
:
1529 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1530 was_8_3
= mangle_is_8_3(fname
, True
, conn
->params
);
1532 SIVAL(p
,0,reskey
); p
+= 4;
1533 put_long_date_full_timespec(conn
->ts_res
,p
,&create_date_ts
); p
+= 8;
1534 put_long_date_full_timespec(conn
->ts_res
,p
,&adate_ts
); p
+= 8;
1535 put_long_date_full_timespec(conn
->ts_res
,p
,&mdate_ts
); p
+= 8;
1536 put_long_date_full_timespec(conn
->ts_res
,p
,&cdate_ts
); p
+= 8;
1537 SOFF_T(p
,0,file_size
); p
+= 8;
1538 SOFF_T(p
,0,allocation_size
); p
+= 8;
1539 SIVAL(p
,0,mode
); p
+= 4;
1540 q
= p
; p
+= 4; /* q is placeholder for name length */
1541 if (readdir_attr_data
&&
1542 readdir_attr_data
->type
== RDATTR_AAPL
) {
1544 * OS X specific SMB2 extension negotiated via
1545 * AAPL create context: return max_access in
1548 ea_size
= readdir_attr_data
->attr_data
.aapl
.max_access
;
1550 ea_size
= get_dirent_ea_size(mode
, smb_fname
->fsp
);
1552 SIVAL(p
,0,ea_size
); /* Extended attributes */
1555 if (readdir_attr_data
&&
1556 readdir_attr_data
->type
== RDATTR_AAPL
) {
1558 * OS X specific SMB2 extension negotiated via
1559 * AAPL create context: return resource fork
1560 * length and compressed FinderInfo in
1563 * According to documentation short_name_len
1564 * should be 0, but on the wire behaviour
1565 * shows its set to 24 by clients.
1569 /* Resourefork length */
1570 SBVAL(p
, 2, readdir_attr_data
->attr_data
.aapl
.rfork_size
);
1572 /* Compressed FinderInfo */
1573 memcpy(p
+ 10, &readdir_attr_data
->attr_data
.aapl
.finder_info
, 16);
1574 } else if (!was_8_3
&& check_mangled_names
) {
1575 char mangled_name
[13]; /* mangled 8.3 name. */
1576 if (!name_to_8_3(fname
,mangled_name
,True
,
1578 /* Error - mangle failed ! */
1579 memset(mangled_name
,'\0',12);
1581 mangled_name
[12] = 0;
1582 status
= srvstr_push(base_data
, flags2
,
1583 p
+2, mangled_name
, 24,
1584 STR_UPPER
|STR_UNICODE
, &len
);
1585 if (!NT_STATUS_IS_OK(status
)) {
1590 memset(p
+ 2 + len
,'\0',24 - len
);
1594 /* Clear the short name buffer. This is
1595 * IMPORTANT as not doing so will trigger
1596 * a Win2k client bug. JRA.
1603 if (readdir_attr_data
&&
1604 readdir_attr_data
->type
== RDATTR_AAPL
) {
1606 * OS X specific SMB2 extension negotiated via
1607 * AAPL create context: return UNIX mode in
1610 uint16_t aapl_mode
= (uint16_t)readdir_attr_data
->attr_data
.aapl
.unix_mode
;
1611 SSVAL(p
, 0, aapl_mode
);
1617 SBVAL(p
,0,file_id
); p
+= 8;
1618 status
= srvstr_push(base_data
, flags2
, p
,
1619 fname
, PTR_DIFF(end_data
, p
),
1620 STR_TERMINATE_ASCII
, &len
);
1621 if (!NT_STATUS_IS_OK(status
)) {
1627 len
= PTR_DIFF(p
, pdata
);
1628 pad
= (len
+ (align
-1)) & ~(align
-1);
1630 * offset to the next entry, the caller
1631 * will overwrite it for the last entry
1632 * that's why we always include the padding
1636 * set padding to zero
1639 memset(p
, 0, pad
- len
);
1646 /* CIFS UNIX Extension. */
1648 case SMB_FIND_FILE_UNIX
:
1649 case SMB_FIND_FILE_UNIX_INFO2
:
1651 SIVAL(p
,0,reskey
); p
+= 4; /* Used for continuing search. */
1653 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1655 if (info_level
== SMB_FIND_FILE_UNIX
) {
1656 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
1657 p
= store_file_unix_basic(conn
, p
,
1658 NULL
, &smb_fname
->st
);
1659 status
= srvstr_push(base_data
, flags2
, p
,
1660 fname
, PTR_DIFF(end_data
, p
),
1661 STR_TERMINATE
, &len
);
1662 if (!NT_STATUS_IS_OK(status
)) {
1666 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
1667 p
= store_file_unix_basic_info2(conn
, p
,
1668 NULL
, &smb_fname
->st
);
1671 status
= srvstr_push(base_data
, flags2
, p
, fname
,
1672 PTR_DIFF(end_data
, p
), 0, &len
);
1673 if (!NT_STATUS_IS_OK(status
)) {
1676 SIVAL(nameptr
, 0, len
);
1681 len
= PTR_DIFF(p
, pdata
);
1682 pad
= (len
+ (align
-1)) & ~(align
-1);
1684 * offset to the next entry, the caller
1685 * will overwrite it for the last entry
1686 * that's why we always include the padding
1690 * set padding to zero
1693 memset(p
, 0, pad
- len
);
1698 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1702 /* SMB2 UNIX Extension. */
1704 case SMB2_FILE_POSIX_INFORMATION
:
1706 struct smb3_file_posix_information info
= {};
1707 uint8_t buf
[sizeof(info
)];
1708 struct ndr_push ndr
= {
1710 .alloc_size
= sizeof(buf
),
1711 .fixed_buf_size
= true,
1713 enum ndr_err_code ndr_err
;
1716 SIVAL(p
,0,reskey
); p
+= 4;
1718 DBG_DEBUG("SMB2_FILE_POSIX_INFORMATION\n");
1720 if (!(conn
->sconn
->using_smb2
)) {
1721 return NT_STATUS_INVALID_LEVEL
;
1724 smb3_file_posix_information_init(
1725 conn
, &smb_fname
->st
, 0, mode
, &info
);
1727 ndr_err
= ndr_push_smb3_file_posix_information(
1728 &ndr
, NDR_SCALARS
|NDR_BUFFERS
, &info
);
1729 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
1730 return NT_STATUS_INSUFFICIENT_RESOURCES
;
1733 memcpy(p
, buf
, ndr
.offset
);
1738 status
= srvstr_push(base_data
, flags2
, p
, fname
,
1739 PTR_DIFF(end_data
, p
), 0, &len
);
1740 if (!NT_STATUS_IS_OK(status
)) {
1743 SIVAL(nameptr
, 0, len
);
1747 len
= PTR_DIFF(p
, pdata
);
1748 pad
= (len
+ (align
-1)) & ~(align
-1);
1750 * offset to the next entry, the caller
1751 * will overwrite it for the last entry
1752 * that's why we always include the padding
1759 return NT_STATUS_INVALID_LEVEL
;
1762 if (PTR_DIFF(p
,pdata
) > space_remaining
) {
1763 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1764 "(wanted %u, had %d)\n",
1765 (unsigned int)PTR_DIFF(p
,pdata
),
1767 return STATUS_MORE_ENTRIES
; /* Not finished - just out of space */
1770 /* Setup the last entry pointer, as an offset from base_data */
1771 *last_entry_off
= PTR_DIFF(last_entry_ptr
,base_data
);
1772 /* Advance the data pointer to the next slot */
1775 return NT_STATUS_OK
;
1778 NTSTATUS
smbd_dirptr_lanman2_entry(TALLOC_CTX
*ctx
,
1779 connection_struct
*conn
,
1780 struct dptr_struct
*dirptr
,
1782 const char *path_mask
,
1785 int requires_resume_key
,
1794 int space_remaining
,
1795 struct smb_filename
**_smb_fname
,
1796 int *_last_entry_off
,
1797 struct ea_list
*name_list
,
1798 struct file_id
*file_id
)
1801 const char *mask
= NULL
;
1804 struct smb_filename
*smb_fname
= NULL
;
1805 struct smbd_dirptr_lanman2_state state
;
1807 uint64_t last_entry_off
= 0;
1809 enum mangled_names_options mangled_names
;
1810 bool marshall_with_83_names
;
1812 mangled_names
= lp_mangled_names(conn
->params
);
1816 state
.info_level
= info_level
;
1817 if (mangled_names
!= MANGLED_NAMES_NO
) {
1818 state
.check_mangled_names
= true;
1820 state
.case_sensitive
= dptr_case_sensitive(dirptr
);
1822 p
= strrchr_m(path_mask
,'/');
1833 ok
= smbd_dirptr_get_entry(ctx
,
1840 smbd_dirptr_lanman2_match_fn
,
1841 smbd_dirptr_lanman2_mode_fn
,
1847 return NT_STATUS_END_OF_FILE
;
1850 marshall_with_83_names
= (mangled_names
== MANGLED_NAMES_YES
);
1852 status
= smbd_marshall_dir_entry(ctx
,
1857 marshall_with_83_names
,
1858 requires_resume_key
,
1869 if (NT_STATUS_EQUAL(status
, NT_STATUS_ILLEGAL_CHARACTER
)) {
1870 DEBUG(1,("Conversion error: illegal character: %s\n",
1871 smb_fname_str_dbg(smb_fname
)));
1874 if (file_id
!= NULL
) {
1875 *file_id
= vfs_file_id_from_sbuf(conn
, &smb_fname
->st
);
1878 if (NT_STATUS_EQUAL(status
, STATUS_MORE_ENTRIES
)) {
1879 smbd_dirptr_push_overflow(dirptr
, &fname
, &smb_fname
, mode
);
1882 if (!NT_STATUS_IS_OK(status
)) {
1883 TALLOC_FREE(smb_fname
);
1888 smbd_dirptr_set_last_name_sent(dirptr
, &smb_fname
->base_name
);
1890 if (_smb_fname
!= NULL
) {
1892 * smb_fname is already talloc'ed off ctx.
1893 * We just need to make sure we don't return
1894 * any stream_name, and replace base_name
1895 * with fname in case base_name got mangled.
1896 * This allows us to preserve any smb_fname->fsp
1897 * for asynchronous handle lookups.
1899 TALLOC_FREE(smb_fname
->stream_name
);
1902 * smbd_dirptr_set_last_name_sent() above consumed
1905 smb_fname
->base_name
= talloc_strdup(smb_fname
, fname
);
1907 if (smb_fname
->base_name
== NULL
) {
1908 TALLOC_FREE(smb_fname
);
1910 return NT_STATUS_NO_MEMORY
;
1912 *_smb_fname
= smb_fname
;
1914 TALLOC_FREE(smb_fname
);
1918 *_last_entry_off
= last_entry_off
;
1919 return NT_STATUS_OK
;
1922 unsigned char *create_volume_objectid(connection_struct
*conn
, unsigned char objid
[16])
1924 const struct loadparm_substitution
*lp_sub
=
1925 loadparm_s3_global_substitution();
1927 E_md4hash(lp_servicename(talloc_tos(), lp_sub
, SNUM(conn
)),objid
);
1931 static void samba_extended_info_version(struct smb_extended_info
*extended_info
)
1933 SMB_ASSERT(extended_info
!= NULL
);
1935 extended_info
->samba_magic
= SAMBA_EXTENDED_INFO_MAGIC
;
1936 extended_info
->samba_version
= ((SAMBA_VERSION_MAJOR
& 0xff) << 24)
1937 | ((SAMBA_VERSION_MINOR
& 0xff) << 16)
1938 | ((SAMBA_VERSION_RELEASE
& 0xff) << 8);
1939 #ifdef SAMBA_VERSION_REVISION
1940 extended_info
->samba_version
|= (tolower(*SAMBA_VERSION_REVISION
) - 'a' + 1) & 0xff;
1942 extended_info
->samba_subversion
= 0;
1943 #ifdef SAMBA_VERSION_RC_RELEASE
1944 extended_info
->samba_subversion
|= (SAMBA_VERSION_RC_RELEASE
& 0xff) << 24;
1946 #ifdef SAMBA_VERSION_PRE_RELEASE
1947 extended_info
->samba_subversion
|= (SAMBA_VERSION_PRE_RELEASE
& 0xff) << 16;
1950 #ifdef SAMBA_VERSION_VENDOR_PATCH
1951 extended_info
->samba_subversion
|= (SAMBA_VERSION_VENDOR_PATCH
& 0xffff);
1953 extended_info
->samba_gitcommitdate
= 0;
1954 #ifdef SAMBA_VERSION_COMMIT_TIME
1955 unix_to_nt_time(&extended_info
->samba_gitcommitdate
, SAMBA_VERSION_COMMIT_TIME
);
1958 memset(extended_info
->samba_version_string
, 0,
1959 sizeof(extended_info
->samba_version_string
));
1961 snprintf (extended_info
->samba_version_string
,
1962 sizeof(extended_info
->samba_version_string
),
1963 "%s", samba_version_string());
1966 static bool fsinfo_unix_valid_level(connection_struct
*conn
,
1967 uint16_t info_level
)
1969 if (conn
->sconn
->using_smb2
&&
1970 info_level
== SMB2_FS_POSIX_INFORMATION_INTERNAL
) {
1973 #if defined(SMB1SERVER)
1974 if (lp_smb1_unix_extensions() &&
1975 info_level
== SMB_QUERY_POSIX_FS_INFO
) {
1982 NTSTATUS
smbd_do_qfsinfo(struct smbXsrv_connection
*xconn
,
1983 connection_struct
*conn
,
1984 TALLOC_CTX
*mem_ctx
,
1985 uint16_t info_level
,
1987 unsigned int max_data_bytes
,
1988 size_t *fixed_portion
,
1989 struct smb_filename
*fname
,
1993 const struct loadparm_substitution
*lp_sub
=
1994 loadparm_s3_global_substitution();
1995 char *pdata
, *end_data
;
1998 const char *vname
= volume_label(talloc_tos(), SNUM(conn
));
1999 int snum
= SNUM(conn
);
2000 const char *fstype
= lp_fstype(SNUM(conn
));
2001 const char *filename
= NULL
;
2002 const uint64_t bytes_per_sector
= 512;
2003 uint32_t additional_flags
= 0;
2004 struct smb_filename smb_fname
;
2006 NTSTATUS status
= NT_STATUS_OK
;
2010 if (fname
== NULL
|| fname
->base_name
== NULL
) {
2013 filename
= fname
->base_name
;
2017 if (info_level
!= SMB_QUERY_CIFS_UNIX_INFO
) {
2018 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
2019 "info level (0x%x) on IPC$.\n",
2020 (unsigned int)info_level
));
2021 return NT_STATUS_ACCESS_DENIED
;
2025 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level
));
2027 smb_fname
= (struct smb_filename
) {
2028 .base_name
= discard_const_p(char, filename
),
2029 .flags
= fname
? fname
->flags
: 0,
2030 .twrp
= fname
? fname
->twrp
: 0,
2033 if(info_level
!= SMB_FS_QUOTA_INFORMATION
2034 && SMB_VFS_STAT(conn
, &smb_fname
) != 0) {
2035 DEBUG(2,("stat of . failed (%s)\n", strerror(errno
)));
2036 return map_nt_error_from_unix(errno
);
2041 if (max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
< max_data_bytes
) {
2042 return NT_STATUS_INVALID_PARAMETER
;
2045 *ppdata
= (char *)SMB_REALLOC(
2046 *ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
2047 if (*ppdata
== NULL
) {
2048 return NT_STATUS_NO_MEMORY
;
2052 memset((char *)pdata
,'\0',max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
2053 end_data
= pdata
+ max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
- 1;
2057 switch (info_level
) {
2058 case SMB_INFO_ALLOCATION
:
2060 uint64_t dfree
,dsize
,bsize
,block_size
,sectors_per_unit
;
2062 df_ret
= get_dfree_info(conn
, &smb_fname
, &bsize
,
2064 if (df_ret
== (uint64_t)-1) {
2065 return map_nt_error_from_unix(errno
);
2068 block_size
= lp_block_size(snum
);
2069 if (bsize
< block_size
) {
2070 uint64_t factor
= block_size
/bsize
;
2075 if (bsize
> block_size
) {
2076 uint64_t factor
= bsize
/block_size
;
2081 sectors_per_unit
= bsize
/bytes_per_sector
;
2083 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2084 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st
.st_ex_dev
, (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
2085 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
2088 * For large drives, return max values and not modulo.
2090 dsize
= MIN(dsize
, UINT32_MAX
);
2091 dfree
= MIN(dfree
, UINT32_MAX
);
2093 SIVAL(pdata
,l1_idFileSystem
,st
.st_ex_dev
);
2094 SIVAL(pdata
,l1_cSectorUnit
,sectors_per_unit
);
2095 SIVAL(pdata
,l1_cUnit
,dsize
);
2096 SIVAL(pdata
,l1_cUnitAvail
,dfree
);
2097 SSVAL(pdata
,l1_cbSector
,bytes_per_sector
);
2101 case SMB_INFO_VOLUME
:
2102 /* Return volume name */
2104 * Add volume serial number - hash of a combination of
2105 * the called hostname and the service name.
2107 serial
= generate_volume_serial_number(lp_sub
, snum
);
2108 SIVAL(pdata
,0,serial
);
2110 * Win2k3 and previous mess this up by sending a name length
2111 * one byte short. I believe only older clients (OS/2 Win9x) use
2112 * this call so try fixing this by adding a terminating null to
2113 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2115 status
= srvstr_push(
2117 pdata
+l2_vol_szVolLabel
, vname
,
2118 PTR_DIFF(end_data
, pdata
+l2_vol_szVolLabel
),
2119 STR_NOALIGN
|STR_TERMINATE
, &len
);
2120 if (!NT_STATUS_IS_OK(status
)) {
2123 SCVAL(pdata
,l2_vol_cch
,len
);
2124 data_len
= l2_vol_szVolLabel
+ len
;
2125 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %u, "
2126 "name = %s serial = 0x%04"PRIx32
"\n",
2127 (unsigned)convert_timespec_to_time_t(st
.st_ex_ctime
),
2128 (unsigned)len
, vname
, serial
));
2131 case SMB_QUERY_FS_ATTRIBUTE_INFO
:
2132 case SMB_FS_ATTRIBUTE_INFORMATION
:
2134 additional_flags
= 0;
2135 #if defined(HAVE_SYS_QUOTAS)
2136 additional_flags
|= FILE_VOLUME_QUOTAS
;
2139 if(lp_nt_acl_support(SNUM(conn
))) {
2140 additional_flags
|= FILE_PERSISTENT_ACLS
;
2143 /* Capabilities are filled in at connection time through STATVFS call */
2144 additional_flags
|= conn
->fs_capabilities
;
2145 additional_flags
|= lp_parm_int(conn
->params
->service
,
2146 "share", "fake_fscaps",
2149 SIVAL(pdata
,0,FILE_CASE_PRESERVED_NAMES
|FILE_CASE_SENSITIVE_SEARCH
|
2150 FILE_SUPPORTS_OBJECT_IDS
|FILE_UNICODE_ON_DISK
|
2151 additional_flags
); /* FS ATTRIBUTES */
2153 SIVAL(pdata
,4,255); /* Max filename component length */
2154 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2155 and will think we can't do long filenames */
2156 status
= srvstr_push(pdata
, flags2
, pdata
+12, fstype
,
2157 PTR_DIFF(end_data
, pdata
+12),
2159 if (!NT_STATUS_IS_OK(status
)) {
2163 data_len
= 12 + len
;
2164 if (max_data_bytes
>= 16 && data_len
> max_data_bytes
) {
2165 /* the client only requested a portion of the
2167 data_len
= max_data_bytes
;
2168 status
= STATUS_BUFFER_OVERFLOW
;
2170 *fixed_portion
= 16;
2173 case SMB_QUERY_FS_LABEL_INFO
:
2174 case SMB_FS_LABEL_INFORMATION
:
2175 status
= srvstr_push(pdata
, flags2
, pdata
+4, vname
,
2176 PTR_DIFF(end_data
, pdata
+4), 0, &len
);
2177 if (!NT_STATUS_IS_OK(status
)) {
2184 case SMB_QUERY_FS_VOLUME_INFO
:
2185 case SMB_FS_VOLUME_INFORMATION
:
2186 put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER
,
2187 pdata
, &st
.st_ex_btime
);
2189 * Add volume serial number - hash of a combination of
2190 * the called hostname and the service name.
2192 serial
= generate_volume_serial_number(lp_sub
, snum
);
2193 SIVAL(pdata
,8,serial
);
2195 /* Max label len is 32 characters. */
2196 status
= srvstr_push(pdata
, flags2
, pdata
+18, vname
,
2197 PTR_DIFF(end_data
, pdata
+18),
2199 if (!NT_STATUS_IS_OK(status
)) {
2202 SIVAL(pdata
,12,len
);
2205 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO "
2206 "namelen = %d, vol=%s serv=%s "
2207 "serial=0x%04"PRIx32
"\n",
2208 (int)strlen(vname
),vname
,
2209 lp_servicename(talloc_tos(), lp_sub
, snum
),
2211 if (max_data_bytes
>= 24 && data_len
> max_data_bytes
) {
2212 /* the client only requested a portion of the
2214 data_len
= max_data_bytes
;
2215 status
= STATUS_BUFFER_OVERFLOW
;
2217 *fixed_portion
= 24;
2220 case SMB_QUERY_FS_SIZE_INFO
:
2221 case SMB_FS_SIZE_INFORMATION
:
2223 uint64_t dfree
,dsize
,bsize
,block_size
,sectors_per_unit
;
2225 df_ret
= get_dfree_info(conn
, &smb_fname
, &bsize
,
2227 if (df_ret
== (uint64_t)-1) {
2228 return map_nt_error_from_unix(errno
);
2230 block_size
= lp_block_size(snum
);
2231 if (bsize
< block_size
) {
2232 uint64_t factor
= block_size
/bsize
;
2237 if (bsize
> block_size
) {
2238 uint64_t factor
= bsize
/block_size
;
2243 sectors_per_unit
= bsize
/bytes_per_sector
;
2244 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2245 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
2246 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
2247 SBIG_UINT(pdata
,0,dsize
);
2248 SBIG_UINT(pdata
,8,dfree
);
2249 SIVAL(pdata
,16,sectors_per_unit
);
2250 SIVAL(pdata
,20,bytes_per_sector
);
2251 *fixed_portion
= 24;
2255 case SMB_FS_FULL_SIZE_INFORMATION
:
2257 uint64_t dfree
,dsize
,bsize
,block_size
,sectors_per_unit
;
2259 df_ret
= get_dfree_info(conn
, &smb_fname
, &bsize
,
2261 if (df_ret
== (uint64_t)-1) {
2262 return map_nt_error_from_unix(errno
);
2264 block_size
= lp_block_size(snum
);
2265 if (bsize
< block_size
) {
2266 uint64_t factor
= block_size
/bsize
;
2271 if (bsize
> block_size
) {
2272 uint64_t factor
= bsize
/block_size
;
2277 sectors_per_unit
= bsize
/bytes_per_sector
;
2278 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2279 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
2280 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
2281 SBIG_UINT(pdata
,0,dsize
); /* Total Allocation units. */
2282 SBIG_UINT(pdata
,8,dfree
); /* Caller available allocation units. */
2283 SBIG_UINT(pdata
,16,dfree
); /* Actual available allocation units. */
2284 SIVAL(pdata
,24,sectors_per_unit
); /* Sectors per allocation unit. */
2285 SIVAL(pdata
,28,bytes_per_sector
); /* Bytes per sector. */
2286 *fixed_portion
= 32;
2290 case SMB_QUERY_FS_DEVICE_INFO
:
2291 case SMB_FS_DEVICE_INFORMATION
:
2293 uint32_t characteristics
= FILE_DEVICE_IS_MOUNTED
;
2295 if (!CAN_WRITE(conn
)) {
2296 characteristics
|= FILE_READ_ONLY_DEVICE
;
2299 SIVAL(pdata
,0,FILE_DEVICE_DISK
); /* dev type */
2300 SIVAL(pdata
,4,characteristics
);
2305 #ifdef HAVE_SYS_QUOTAS
2306 case SMB_FS_QUOTA_INFORMATION
:
2308 * what we have to send --metze:
2310 * Unknown1: 24 NULL bytes
2311 * Soft Quota Threshold: 8 bytes seems like uint64_t or so
2312 * Hard Quota Limit: 8 bytes seems like uint64_t or so
2313 * Quota Flags: 2 byte :
2314 * Unknown3: 6 NULL bytes
2318 * details for Quota Flags:
2320 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2321 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2322 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2323 * 0x0001 Enable Quotas: enable quota for this fs
2327 /* we need to fake up a fsp here,
2328 * because its not send in this call
2331 SMB_NTQUOTA_STRUCT quotas
;
2334 ZERO_STRUCT(quotas
);
2337 fsp
.fnum
= FNUM_FIELD_INVALID
;
2340 if (get_current_uid(conn
) != 0) {
2341 DEBUG(0,("get_user_quota: access_denied "
2342 "service [%s] user [%s]\n",
2343 lp_servicename(talloc_tos(), lp_sub
, SNUM(conn
)),
2344 conn
->session_info
->unix_info
->unix_name
));
2345 return NT_STATUS_ACCESS_DENIED
;
2348 status
= vfs_get_ntquota(&fsp
, SMB_USER_FS_QUOTA_TYPE
,
2350 if (!NT_STATUS_IS_OK(status
)) {
2351 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), lp_sub
, SNUM(conn
))));
2357 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
2358 lp_servicename(talloc_tos(), lp_sub
, SNUM(conn
))));
2360 /* Unknown1 24 NULL bytes*/
2361 SBIG_UINT(pdata
,0,(uint64_t)0);
2362 SBIG_UINT(pdata
,8,(uint64_t)0);
2363 SBIG_UINT(pdata
,16,(uint64_t)0);
2365 /* Default Soft Quota 8 bytes */
2366 SBIG_UINT(pdata
,24,quotas
.softlim
);
2368 /* Default Hard Quota 8 bytes */
2369 SBIG_UINT(pdata
,32,quotas
.hardlim
);
2371 /* Quota flag 2 bytes */
2372 SSVAL(pdata
,40,quotas
.qflags
);
2374 /* Unknown3 6 NULL bytes */
2380 #endif /* HAVE_SYS_QUOTAS */
2381 case SMB_FS_OBJECTID_INFORMATION
:
2383 unsigned char objid
[16];
2384 struct smb_extended_info extended_info
;
2385 memcpy(pdata
,create_volume_objectid(conn
, objid
),16);
2386 samba_extended_info_version (&extended_info
);
2387 SIVAL(pdata
,16,extended_info
.samba_magic
);
2388 SIVAL(pdata
,20,extended_info
.samba_version
);
2389 SIVAL(pdata
,24,extended_info
.samba_subversion
);
2390 SBIG_UINT(pdata
,28,extended_info
.samba_gitcommitdate
);
2391 memcpy(pdata
+36,extended_info
.samba_version_string
,28);
2396 case SMB_FS_SECTOR_SIZE_INFORMATION
:
2400 * These values match a physical Windows Server 2012
2401 * share backed by NTFS atop spinning rust.
2403 DEBUG(5, ("SMB_FS_SECTOR_SIZE_INFORMATION:"));
2404 /* logical_bytes_per_sector */
2405 SIVAL(pdata
, 0, bytes_per_sector
);
2406 /* phys_bytes_per_sector_atomic */
2407 SIVAL(pdata
, 4, bytes_per_sector
);
2408 /* phys_bytes_per_sector_perf */
2409 SIVAL(pdata
, 8, bytes_per_sector
);
2410 /* fs_effective_phys_bytes_per_sector_atomic */
2411 SIVAL(pdata
, 12, bytes_per_sector
);
2413 SIVAL(pdata
, 16, SSINFO_FLAGS_ALIGNED_DEVICE
2414 | SSINFO_FLAGS_PARTITION_ALIGNED_ON_DEVICE
);
2415 /* byte_off_sector_align */
2416 SIVAL(pdata
, 20, 0);
2417 /* byte_off_partition_align */
2418 SIVAL(pdata
, 24, 0);
2419 *fixed_portion
= 28;
2424 #if defined(WITH_SMB1SERVER)
2426 * Query the version and capabilities of the CIFS UNIX extensions
2430 case SMB_QUERY_CIFS_UNIX_INFO
:
2432 bool large_write
= lp_min_receive_file_size() &&
2433 !smb1_srv_is_signing_active(xconn
);
2434 bool large_read
= !smb1_srv_is_signing_active(xconn
);
2435 int encrypt_caps
= 0;
2437 if (!lp_smb1_unix_extensions()) {
2438 return NT_STATUS_INVALID_LEVEL
;
2441 switch (conn
->encrypt_level
) {
2442 case SMB_SIGNING_OFF
:
2445 case SMB_SIGNING_DESIRED
:
2446 case SMB_SIGNING_IF_REQUIRED
:
2447 case SMB_SIGNING_DEFAULT
:
2448 encrypt_caps
= CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP
;
2450 case SMB_SIGNING_REQUIRED
:
2451 encrypt_caps
= CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP
|
2452 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP
;
2453 large_write
= false;
2459 SSVAL(pdata
,0,CIFS_UNIX_MAJOR_VERSION
);
2460 SSVAL(pdata
,2,CIFS_UNIX_MINOR_VERSION
);
2462 /* We have POSIX ACLs, pathname, encryption,
2463 * large read/write, and locking capability. */
2465 SBIG_UINT(pdata
,4,((uint64_t)(
2466 CIFS_UNIX_POSIX_ACLS_CAP
|
2467 CIFS_UNIX_POSIX_PATHNAMES_CAP
|
2468 CIFS_UNIX_FCNTL_LOCKS_CAP
|
2469 CIFS_UNIX_EXTATTR_CAP
|
2470 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP
|
2472 (large_read
? CIFS_UNIX_LARGE_READ_CAP
: 0) |
2474 CIFS_UNIX_LARGE_WRITE_CAP
: 0))));
2479 case SMB_QUERY_POSIX_FS_INFO
:
2480 case SMB2_FS_POSIX_INFORMATION_INTERNAL
:
2483 struct vfs_statvfs_struct svfs
;
2485 if (!fsinfo_unix_valid_level(conn
, info_level
)) {
2486 return NT_STATUS_INVALID_LEVEL
;
2489 rc
= SMB_VFS_STATVFS(conn
, &smb_fname
, &svfs
);
2493 SIVAL(pdata
,0,svfs
.OptimalTransferSize
);
2494 SIVAL(pdata
,4,svfs
.BlockSize
);
2495 SBIG_UINT(pdata
,8,svfs
.TotalBlocks
);
2496 SBIG_UINT(pdata
,16,svfs
.BlocksAvail
);
2497 SBIG_UINT(pdata
,24,svfs
.UserBlocksAvail
);
2498 SBIG_UINT(pdata
,32,svfs
.TotalFileNodes
);
2499 SBIG_UINT(pdata
,40,svfs
.FreeFileNodes
);
2500 SBIG_UINT(pdata
,48,svfs
.FsIdentifier
);
2501 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO successful\n"));
2503 } else if (rc
== EOPNOTSUPP
) {
2504 return NT_STATUS_INVALID_LEVEL
;
2505 #endif /* EOPNOTSUPP */
2507 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(talloc_tos(), lp_sub
, SNUM(conn
))));
2508 return NT_STATUS_DOS(ERRSRV
, ERRerror
);
2513 case SMB_QUERY_POSIX_WHOAMI
:
2519 if (!lp_smb1_unix_extensions()) {
2520 return NT_STATUS_INVALID_LEVEL
;
2523 if (max_data_bytes
< 40) {
2524 return NT_STATUS_BUFFER_TOO_SMALL
;
2527 if (security_session_user_level(conn
->session_info
, NULL
) < SECURITY_USER
) {
2528 flags
|= SMB_WHOAMI_GUEST
;
2531 /* NOTE: 8 bytes for UID/GID, irrespective of native
2532 * platform size. This matches
2533 * SMB_QUERY_FILE_UNIX_BASIC and friends.
2535 data_len
= 4 /* flags */
2542 + 4 /* pad/reserved */
2543 + (conn
->session_info
->unix_token
->ngroups
* 8)
2545 + (conn
->session_info
->security_token
->num_sids
*
2549 SIVAL(pdata
, 0, flags
);
2550 SIVAL(pdata
, 4, SMB_WHOAMI_MASK
);
2552 (uint64_t)conn
->session_info
->unix_token
->uid
);
2553 SBIG_UINT(pdata
, 16,
2554 (uint64_t)conn
->session_info
->unix_token
->gid
);
2557 if (data_len
>= max_data_bytes
) {
2558 /* Potential overflow, skip the GIDs and SIDs. */
2560 SIVAL(pdata
, 24, 0); /* num_groups */
2561 SIVAL(pdata
, 28, 0); /* num_sids */
2562 SIVAL(pdata
, 32, 0); /* num_sid_bytes */
2563 SIVAL(pdata
, 36, 0); /* reserved */
2569 SIVAL(pdata
, 24, conn
->session_info
->unix_token
->ngroups
);
2570 SIVAL(pdata
, 28, conn
->session_info
->security_token
->num_sids
);
2572 /* We walk the SID list twice, but this call is fairly
2573 * infrequent, and I don't expect that it's performance
2574 * sensitive -- jpeach
2576 for (i
= 0, sid_bytes
= 0;
2577 i
< conn
->session_info
->security_token
->num_sids
; ++i
) {
2578 sid_bytes
+= ndr_size_dom_sid(
2579 &conn
->session_info
->security_token
->sids
[i
],
2583 /* SID list byte count */
2584 SIVAL(pdata
, 32, sid_bytes
);
2586 /* 4 bytes pad/reserved - must be zero */
2587 SIVAL(pdata
, 36, 0);
2591 for (i
= 0; i
< conn
->session_info
->unix_token
->ngroups
; ++i
) {
2592 SBIG_UINT(pdata
, data_len
,
2593 (uint64_t)conn
->session_info
->unix_token
->groups
[i
]);
2599 i
< conn
->session_info
->security_token
->num_sids
; ++i
) {
2600 int sid_len
= ndr_size_dom_sid(
2601 &conn
->session_info
->security_token
->sids
[i
],
2604 sid_linearize((uint8_t *)(pdata
+ data_len
),
2606 &conn
->session_info
->security_token
->sids
[i
]);
2607 data_len
+= sid_len
;
2613 case SMB_MAC_QUERY_FS_INFO
:
2615 * Thursby MAC extension... ONLY on NTFS filesystems
2616 * once we do streams then we don't need this
2618 if (strequal(lp_fstype(SNUM(conn
)),"NTFS")) {
2620 SIVAL(pdata
,84,0x100); /* Don't support mac... */
2626 return NT_STATUS_INVALID_LEVEL
;
2629 *ret_data_len
= data_len
;
2633 NTSTATUS
smb_set_fsquota(connection_struct
*conn
,
2634 struct smb_request
*req
,
2636 const DATA_BLOB
*qdata
)
2638 const struct loadparm_substitution
*lp_sub
=
2639 loadparm_s3_global_substitution();
2641 SMB_NTQUOTA_STRUCT quotas
;
2643 ZERO_STRUCT(quotas
);
2646 if ((get_current_uid(conn
) != 0) || !CAN_WRITE(conn
)) {
2647 DBG_NOTICE("access_denied service [%s] user [%s]\n",
2648 lp_servicename(talloc_tos(), lp_sub
, SNUM(conn
)),
2649 conn
->session_info
->unix_info
->unix_name
);
2650 return NT_STATUS_ACCESS_DENIED
;
2653 if (!check_fsp_ntquota_handle(conn
, req
,
2655 DBG_WARNING("no valid QUOTA HANDLE\n");
2656 return NT_STATUS_INVALID_HANDLE
;
2659 /* note: normally there're 48 bytes,
2660 * but we didn't use the last 6 bytes for now
2663 if (qdata
->length
< 42) {
2664 DBG_ERR("requires total_data(%zu) >= 42 bytes!\n",
2666 return NT_STATUS_INVALID_PARAMETER
;
2669 /* unknown_1 24 NULL bytes in pdata*/
2671 /* the soft quotas 8 bytes (uint64_t)*/
2672 quotas
.softlim
= BVAL(qdata
->data
,24);
2674 /* the hard quotas 8 bytes (uint64_t)*/
2675 quotas
.hardlim
= BVAL(qdata
->data
,32);
2677 /* quota_flags 2 bytes **/
2678 quotas
.qflags
= SVAL(qdata
->data
,40);
2680 /* unknown_2 6 NULL bytes follow*/
2682 /* now set the quotas */
2683 if (vfs_set_ntquota(fsp
, SMB_USER_FS_QUOTA_TYPE
, NULL
, "as
)!=0) {
2684 DBG_WARNING("vfs_set_ntquota() failed for service [%s]\n",
2685 lp_servicename(talloc_tos(), lp_sub
, SNUM(conn
)));
2686 status
= map_nt_error_from_unix(errno
);
2688 status
= NT_STATUS_OK
;
2693 NTSTATUS
smbd_do_setfsinfo(connection_struct
*conn
,
2694 struct smb_request
*req
,
2695 TALLOC_CTX
*mem_ctx
,
2696 uint16_t info_level
,
2698 const DATA_BLOB
*pdata
)
2700 switch (info_level
) {
2701 case SMB_FS_QUOTA_INFORMATION
:
2703 return smb_set_fsquota(conn
,
2712 return NT_STATUS_INVALID_LEVEL
;
2715 /****************************************************************************
2716 Store the FILE_UNIX_BASIC info.
2717 ****************************************************************************/
2719 char *store_file_unix_basic(connection_struct
*conn
,
2722 const SMB_STRUCT_STAT
*psbuf
)
2726 DBG_DEBUG("SMB_QUERY_FILE_UNIX_BASIC\n");
2727 DBG_NOTICE("st_mode=%o\n", (int)psbuf
->st_ex_mode
);
2729 SOFF_T(pdata
,0,get_file_size_stat(psbuf
)); /* File size 64 Bit */
2732 SOFF_T(pdata
,0,SMB_VFS_GET_ALLOC_SIZE(conn
,fsp
,psbuf
)); /* Number of bytes used on disk - 64 Bit */
2735 put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER
, pdata
, &psbuf
->st_ex_ctime
); /* Change Time 64 Bit */
2736 put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER
,pdata
+8, &psbuf
->st_ex_atime
); /* Last access time 64 Bit */
2737 put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER
, pdata
+16, &psbuf
->st_ex_mtime
); /* Last modification time 64 Bit */
2740 SIVAL(pdata
,0,psbuf
->st_ex_uid
); /* user id for the owner */
2744 SIVAL(pdata
,0,psbuf
->st_ex_gid
); /* group id of owner */
2748 SIVAL(pdata
,0,unix_filetype(psbuf
->st_ex_mode
));
2751 if (S_ISBLK(psbuf
->st_ex_mode
) || S_ISCHR(psbuf
->st_ex_mode
)) {
2752 devno
= psbuf
->st_ex_rdev
;
2754 devno
= psbuf
->st_ex_dev
;
2757 SIVAL(pdata
,0,unix_dev_major(devno
)); /* Major device number if type is device */
2761 SIVAL(pdata
,0,unix_dev_minor(devno
)); /* Minor device number if type is device */
2765 SINO_T_VAL(pdata
, 0, psbuf
->st_ex_ino
); /* inode number */
2768 SIVAL(pdata
,0, unix_perms_to_wire(psbuf
->st_ex_mode
)); /* Standard UNIX file permissions */
2772 SIVAL(pdata
,0,psbuf
->st_ex_nlink
); /* number of hard links */
2779 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
2780 * the chflags(2) (or equivalent) flags.
2782 * XXX: this really should be behind the VFS interface. To do this, we would
2783 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
2784 * Each VFS module could then implement its own mapping as appropriate for the
2785 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
2787 static const struct {unsigned stat_fflag
; unsigned smb_fflag
;}
2791 { UF_NODUMP
, EXT_DO_NOT_BACKUP
},
2795 { UF_IMMUTABLE
, EXT_IMMUTABLE
},
2799 { UF_APPEND
, EXT_OPEN_APPEND_ONLY
},
2803 { UF_HIDDEN
, EXT_HIDDEN
},
2806 /* Do not remove. We need to guarantee that this array has at least one
2807 * entry to build on HP-UX.
2813 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT
*psbuf
,
2814 uint32_t *smb_fflags
, uint32_t *smb_fmask
)
2818 for (i
= 0; i
< ARRAY_SIZE(info2_flags_map
); ++i
) {
2819 *smb_fmask
|= info2_flags_map
[i
].smb_fflag
;
2820 if (psbuf
->st_ex_flags
& info2_flags_map
[i
].stat_fflag
) {
2821 *smb_fflags
|= info2_flags_map
[i
].smb_fflag
;
2826 bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT
*psbuf
,
2827 const uint32_t smb_fflags
,
2828 const uint32_t smb_fmask
,
2831 uint32_t max_fmask
= 0;
2834 *stat_fflags
= psbuf
->st_ex_flags
;
2836 /* For each flags requested in smb_fmask, check the state of the
2837 * corresponding flag in smb_fflags and set or clear the matching
2841 for (i
= 0; i
< ARRAY_SIZE(info2_flags_map
); ++i
) {
2842 max_fmask
|= info2_flags_map
[i
].smb_fflag
;
2843 if (smb_fmask
& info2_flags_map
[i
].smb_fflag
) {
2844 if (smb_fflags
& info2_flags_map
[i
].smb_fflag
) {
2845 *stat_fflags
|= info2_flags_map
[i
].stat_fflag
;
2847 *stat_fflags
&= ~info2_flags_map
[i
].stat_fflag
;
2852 /* If smb_fmask is asking to set any bits that are not supported by
2853 * our flag mappings, we should fail.
2855 if ((smb_fmask
& max_fmask
) != smb_fmask
) {
2863 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
2864 * of file flags and birth (create) time.
2866 char *store_file_unix_basic_info2(connection_struct
*conn
,
2869 const SMB_STRUCT_STAT
*psbuf
)
2871 uint32_t file_flags
= 0;
2872 uint32_t flags_mask
= 0;
2874 pdata
= store_file_unix_basic(conn
, pdata
, fsp
, psbuf
);
2876 /* Create (birth) time 64 bit */
2877 put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER
,pdata
, &psbuf
->st_ex_btime
);
2880 map_info2_flags_from_sbuf(psbuf
, &file_flags
, &flags_mask
);
2881 SIVAL(pdata
, 0, file_flags
); /* flags */
2882 SIVAL(pdata
, 4, flags_mask
); /* mask */
2888 static NTSTATUS
marshall_stream_info(unsigned int num_streams
,
2889 const struct stream_struct
*streams
,
2891 unsigned int max_data_bytes
,
2892 unsigned int *data_size
)
2895 unsigned int ofs
= 0;
2897 if (max_data_bytes
< 32) {
2898 return NT_STATUS_INFO_LENGTH_MISMATCH
;
2901 for (i
= 0; i
< num_streams
; i
++) {
2902 unsigned int next_offset
;
2904 smb_ucs2_t
*namebuf
;
2906 if (!push_ucs2_talloc(talloc_tos(), &namebuf
,
2907 streams
[i
].name
, &namelen
) ||
2910 return NT_STATUS_INVALID_PARAMETER
;
2914 * name_buf is now null-terminated, we need to marshall as not
2921 * We cannot overflow ...
2923 if ((ofs
+ 24 + namelen
) > max_data_bytes
) {
2924 DEBUG(10, ("refusing to overflow reply at stream %u\n",
2926 TALLOC_FREE(namebuf
);
2927 return STATUS_BUFFER_OVERFLOW
;
2930 SIVAL(data
, ofs
+4, namelen
);
2931 SOFF_T(data
, ofs
+8, streams
[i
].size
);
2932 SOFF_T(data
, ofs
+16, streams
[i
].alloc_size
);
2933 memcpy(data
+ofs
+24, namebuf
, namelen
);
2934 TALLOC_FREE(namebuf
);
2936 next_offset
= ofs
+ 24 + namelen
;
2938 if (i
== num_streams
-1) {
2939 SIVAL(data
, ofs
, 0);
2942 unsigned int align
= ndr_align_size(next_offset
, 8);
2944 if ((next_offset
+ align
) > max_data_bytes
) {
2945 DEBUG(10, ("refusing to overflow align "
2946 "reply at stream %u\n",
2948 TALLOC_FREE(namebuf
);
2949 return STATUS_BUFFER_OVERFLOW
;
2952 memset(data
+next_offset
, 0, align
);
2953 next_offset
+= align
;
2955 SIVAL(data
, ofs
, next_offset
- ofs
);
2962 DEBUG(10, ("max_data: %u, data_size: %u\n", max_data_bytes
, ofs
));
2966 return NT_STATUS_OK
;
2969 NTSTATUS
smbd_do_qfilepathinfo(connection_struct
*conn
,
2970 TALLOC_CTX
*mem_ctx
,
2971 struct smb_request
*req
,
2972 uint16_t info_level
,
2974 struct smb_filename
*smb_fname
,
2975 bool delete_pending
,
2976 struct timespec write_time_ts
,
2977 struct ea_list
*ea_list
,
2979 unsigned int max_data_bytes
,
2980 size_t *fixed_portion
,
2982 unsigned int *pdata_size
)
2984 char *pdata
= *ppdata
;
2985 char *dstart
, *dend
;
2986 unsigned int data_size
;
2987 struct timespec create_time_ts
, mtime_ts
, atime_ts
, ctime_ts
;
2988 time_t create_time
, mtime
, atime
, c_time
;
2989 SMB_STRUCT_STAT
*psbuf
= NULL
;
2990 SMB_STRUCT_STAT
*base_sp
= NULL
;
2997 uint64_t file_size
= 0;
2999 uint64_t allocation_size
= 0;
3000 uint64_t file_id
= 0;
3001 uint32_t access_mask
= 0;
3004 if (INFO_LEVEL_IS_UNIX(info_level
)) {
3007 if (lp_smb1_unix_extensions() && req
->posix_pathnames
) {
3008 DBG_DEBUG("SMB1 unix extensions activated\n");
3012 if ((fsp
!= NULL
) &&
3013 (fsp
->posix_flags
& FSP_POSIX_FLAGS_OPEN
)) {
3014 DBG_DEBUG("SMB2 posix open\n");
3019 return NT_STATUS_INVALID_LEVEL
;
3023 DEBUG(5,("smbd_do_qfilepathinfo: %s (%s) level=%d max_data=%u\n",
3024 smb_fname_str_dbg(smb_fname
),
3026 info_level
, max_data_bytes
));
3029 * In case of querying a symlink in POSIX context,
3030 * fsp will be NULL. fdos_mode() deals with it.
3033 smb_fname
= fsp
->fsp_name
;
3035 mode
= fdos_mode(fsp
);
3036 psbuf
= &smb_fname
->st
;
3039 base_sp
= fsp
->base_fsp
?
3040 &fsp
->base_fsp
->fsp_name
->st
:
3043 base_sp
= &smb_fname
->st
;
3046 nlink
= psbuf
->st_ex_nlink
;
3048 if (nlink
&& (mode
&FILE_ATTRIBUTE_DIRECTORY
)) {
3052 if ((nlink
> 0) && delete_pending
) {
3056 if (max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
< max_data_bytes
) {
3057 return NT_STATUS_INVALID_PARAMETER
;
3060 data_size
= max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
;
3061 *ppdata
= (char *)SMB_REALLOC(*ppdata
, data_size
);
3062 if (*ppdata
== NULL
) {
3063 return NT_STATUS_NO_MEMORY
;
3067 dend
= dstart
+ data_size
- 1;
3069 if (!is_omit_timespec(&write_time_ts
) &&
3070 !INFO_LEVEL_IS_UNIX(info_level
))
3072 update_stat_ex_mtime(psbuf
, write_time_ts
);
3075 create_time_ts
= get_create_timespec(conn
, fsp
, smb_fname
);
3076 mtime_ts
= psbuf
->st_ex_mtime
;
3077 atime_ts
= psbuf
->st_ex_atime
;
3078 ctime_ts
= get_change_timespec(conn
, fsp
, smb_fname
);
3080 if (lp_dos_filetime_resolution(SNUM(conn
))) {
3081 dos_filetime_timespec(&create_time_ts
);
3082 dos_filetime_timespec(&mtime_ts
);
3083 dos_filetime_timespec(&atime_ts
);
3084 dos_filetime_timespec(&ctime_ts
);
3087 create_time
= convert_timespec_to_time_t(create_time_ts
);
3088 mtime
= convert_timespec_to_time_t(mtime_ts
);
3089 atime
= convert_timespec_to_time_t(atime_ts
);
3090 c_time
= convert_timespec_to_time_t(ctime_ts
);
3092 p
= strrchr_m(smb_fname
->base_name
,'/');
3094 base_name
= smb_fname
->base_name
;
3098 /* NT expects the name to be in an exact form of the *full*
3099 filename. See the trans2 torture test */
3100 if (ISDOT(base_name
)) {
3101 dos_fname
= talloc_strdup(mem_ctx
, "\\");
3103 return NT_STATUS_NO_MEMORY
;
3106 dos_fname
= talloc_asprintf(mem_ctx
,
3108 smb_fname
->base_name
);
3110 return NT_STATUS_NO_MEMORY
;
3112 if (is_named_stream(smb_fname
)) {
3113 dos_fname
= talloc_asprintf(dos_fname
, "%s",
3114 smb_fname
->stream_name
);
3116 return NT_STATUS_NO_MEMORY
;
3120 string_replace(dos_fname
, '/', '\\');
3123 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
, fsp
, psbuf
);
3125 if (fsp
== NULL
|| !fsp
->fsp_flags
.is_fsa
) {
3126 /* Do we have this path open ? */
3127 struct file_id fileid
= vfs_file_id_from_sbuf(conn
, psbuf
);
3128 files_struct
*fsp1
= file_find_di_first(
3129 conn
->sconn
, fileid
, true);
3130 if (fsp1
&& fsp1
->initial_allocation_size
) {
3131 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
, fsp1
, psbuf
);
3135 if (!(mode
& FILE_ATTRIBUTE_DIRECTORY
)) {
3136 file_size
= get_file_size_stat(psbuf
);
3140 pos
= fh_get_position_information(fsp
->fh
);
3144 access_mask
= fsp
->access_mask
;
3146 /* GENERIC_EXECUTE mapping from Windows */
3147 access_mask
= 0x12019F;
3150 /* This should be an index number - looks like
3153 I think this causes us to fail the IFSKIT
3154 BasicFileInformationTest. -tpot */
3155 file_id
= SMB_VFS_FS_FILE_ID(conn
, base_sp
);
3159 switch (info_level
) {
3160 case SMB_INFO_STANDARD
:
3161 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
3163 srv_put_dos_date2(pdata
,l1_fdateCreation
,create_time
);
3164 srv_put_dos_date2(pdata
,l1_fdateLastAccess
,atime
);
3165 srv_put_dos_date2(pdata
,l1_fdateLastWrite
,mtime
); /* write time */
3166 SIVAL(pdata
,l1_cbFile
,(uint32_t)file_size
);
3167 SIVAL(pdata
,l1_cbFileAlloc
,(uint32_t)allocation_size
);
3168 SSVAL(pdata
,l1_attrFile
,mode
);
3171 case SMB_INFO_QUERY_EA_SIZE
:
3173 unsigned int ea_size
=
3174 estimate_ea_size(smb_fname
->fsp
);
3175 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
3177 srv_put_dos_date2(pdata
,0,create_time
);
3178 srv_put_dos_date2(pdata
,4,atime
);
3179 srv_put_dos_date2(pdata
,8,mtime
); /* write time */
3180 SIVAL(pdata
,12,(uint32_t)file_size
);
3181 SIVAL(pdata
,16,(uint32_t)allocation_size
);
3182 SSVAL(pdata
,20,mode
);
3183 SIVAL(pdata
,22,ea_size
);
3187 case SMB_INFO_IS_NAME_VALID
:
3188 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
3190 /* os/2 needs this ? really ?*/
3191 return NT_STATUS_DOS(ERRDOS
, ERRbadfunc
);
3193 /* This is only reached for qpathinfo */
3197 case SMB_INFO_QUERY_EAS_FROM_LIST
:
3199 size_t total_ea_len
= 0;
3200 struct ea_list
*ea_file_list
= NULL
;
3201 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
3204 get_ea_list_from_fsp(mem_ctx
,
3206 &total_ea_len
, &ea_file_list
);
3207 if (!NT_STATUS_IS_OK(status
)) {
3211 ea_list
= ea_list_union(ea_list
, ea_file_list
, &total_ea_len
);
3213 if (!ea_list
|| (total_ea_len
> data_size
)) {
3215 SIVAL(pdata
,0,4); /* EA List Length must be set to 4 if no EA's. */
3219 data_size
= fill_ea_buffer(mem_ctx
, pdata
, data_size
, conn
, ea_list
);
3223 case SMB_INFO_QUERY_ALL_EAS
:
3225 /* We have data_size bytes to put EA's into. */
3226 size_t total_ea_len
= 0;
3227 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
3229 status
= get_ea_list_from_fsp(mem_ctx
,
3231 &total_ea_len
, &ea_list
);
3232 if (!NT_STATUS_IS_OK(status
)) {
3236 if (!ea_list
|| (total_ea_len
> data_size
)) {
3238 SIVAL(pdata
,0,4); /* EA List Length must be set to 4 if no EA's. */
3242 data_size
= fill_ea_buffer(mem_ctx
, pdata
, data_size
, conn
, ea_list
);
3246 case SMB2_FILE_FULL_EA_INFORMATION
:
3248 /* We have data_size bytes to put EA's into. */
3249 size_t total_ea_len
= 0;
3250 struct ea_list
*ea_file_list
= NULL
;
3252 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
3254 /*TODO: add filtering and index handling */
3257 get_ea_list_from_fsp(mem_ctx
,
3259 &total_ea_len
, &ea_file_list
);
3260 if (!NT_STATUS_IS_OK(status
)) {
3263 if (!ea_file_list
) {
3264 return NT_STATUS_NO_EAS_ON_FILE
;
3267 status
= fill_ea_chained_buffer(mem_ctx
,
3271 conn
, ea_file_list
);
3272 if (!NT_STATUS_IS_OK(status
)) {
3278 case SMB_FILE_BASIC_INFORMATION
:
3279 case SMB_QUERY_FILE_BASIC_INFO
:
3281 if (info_level
== SMB_QUERY_FILE_BASIC_INFO
) {
3282 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
3283 data_size
= 36; /* w95 returns 40 bytes not 36 - why ?. */
3285 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
3289 put_long_date_full_timespec(conn
->ts_res
,pdata
,&create_time_ts
);
3290 put_long_date_full_timespec(conn
->ts_res
,pdata
+8,&atime_ts
);
3291 put_long_date_full_timespec(conn
->ts_res
,pdata
+16,&mtime_ts
); /* write time */
3292 put_long_date_full_timespec(conn
->ts_res
,pdata
+24,&ctime_ts
); /* change time */
3293 SIVAL(pdata
,32,mode
);
3295 DEBUG(5,("SMB_QFBI - "));
3296 DEBUG(5,("create: %s ", ctime(&create_time
)));
3297 DEBUG(5,("access: %s ", ctime(&atime
)));
3298 DEBUG(5,("write: %s ", ctime(&mtime
)));
3299 DEBUG(5,("change: %s ", ctime(&c_time
)));
3300 DEBUG(5,("mode: %x\n", mode
));
3301 *fixed_portion
= data_size
;
3304 case SMB_FILE_STANDARD_INFORMATION
:
3305 case SMB_QUERY_FILE_STANDARD_INFO
:
3307 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
3309 SOFF_T(pdata
,0,allocation_size
);
3310 SOFF_T(pdata
,8,file_size
);
3311 SIVAL(pdata
,16,nlink
);
3312 SCVAL(pdata
,20,delete_pending
?1:0);
3313 SCVAL(pdata
,21,(mode
&FILE_ATTRIBUTE_DIRECTORY
)?1:0);
3314 SSVAL(pdata
,22,0); /* Padding. */
3315 *fixed_portion
= 24;
3318 case SMB_FILE_EA_INFORMATION
:
3319 case SMB_QUERY_FILE_EA_INFO
:
3321 unsigned int ea_size
=
3322 estimate_ea_size(smb_fname
->fsp
);
3323 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
3326 SIVAL(pdata
,0,ea_size
);
3330 /* Get the 8.3 name - used if NT SMB was negotiated. */
3331 case SMB_QUERY_FILE_ALT_NAME_INFO
:
3332 case SMB_FILE_ALTERNATE_NAME_INFORMATION
:
3334 char mangled_name
[13];
3335 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
3336 if (!name_to_8_3(base_name
,mangled_name
,
3337 True
,conn
->params
)) {
3338 return NT_STATUS_NO_MEMORY
;
3340 status
= srvstr_push(dstart
, flags2
,
3341 pdata
+4, mangled_name
,
3342 PTR_DIFF(dend
, pdata
+4),
3344 if (!NT_STATUS_IS_OK(status
)) {
3347 data_size
= 4 + len
;
3353 case SMB_QUERY_FILE_NAME_INFO
:
3356 this must be *exactly* right for ACLs on mapped drives to work
3358 status
= srvstr_push(dstart
, flags2
,
3360 PTR_DIFF(dend
, pdata
+4),
3362 if (!NT_STATUS_IS_OK(status
)) {
3365 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
3366 data_size
= 4 + len
;
3371 case SMB_FILE_NORMALIZED_NAME_INFORMATION
:
3373 char *nfname
= NULL
;
3375 if (fsp
== NULL
|| !fsp
->conn
->sconn
->using_smb2
) {
3376 return NT_STATUS_INVALID_LEVEL
;
3379 nfname
= talloc_strdup(mem_ctx
, smb_fname
->base_name
);
3380 if (nfname
== NULL
) {
3381 return NT_STATUS_NO_MEMORY
;
3384 if (ISDOT(nfname
)) {
3387 string_replace(nfname
, '/', '\\');
3389 if (fsp_is_alternate_stream(fsp
)) {
3390 const char *s
= smb_fname
->stream_name
;
3391 const char *e
= NULL
;
3394 SMB_ASSERT(s
[0] != '\0');
3397 * smb_fname->stream_name is in form
3398 * of ':StrEam:$DATA', but we should only
3399 * append ':StrEam' here.
3402 e
= strchr(&s
[1], ':');
3408 nfname
= talloc_strndup_append(nfname
, s
, n
);
3409 if (nfname
== NULL
) {
3410 return NT_STATUS_NO_MEMORY
;
3414 status
= srvstr_push(dstart
, flags2
,
3416 PTR_DIFF(dend
, pdata
+4),
3418 if (!NT_STATUS_IS_OK(status
)) {
3421 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NORMALIZED_NAME_INFORMATION\n"));
3422 data_size
= 4 + len
;
3428 case SMB_FILE_ALLOCATION_INFORMATION
:
3429 case SMB_QUERY_FILE_ALLOCATION_INFO
:
3430 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
3432 SOFF_T(pdata
,0,allocation_size
);
3435 case SMB_FILE_END_OF_FILE_INFORMATION
:
3436 case SMB_QUERY_FILE_END_OF_FILEINFO
:
3437 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
3439 SOFF_T(pdata
,0,file_size
);
3442 case SMB_QUERY_FILE_ALL_INFO
:
3443 case SMB_FILE_ALL_INFORMATION
:
3445 unsigned int ea_size
=
3446 estimate_ea_size(smb_fname
->fsp
);
3447 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
3448 put_long_date_full_timespec(conn
->ts_res
,pdata
,&create_time_ts
);
3449 put_long_date_full_timespec(conn
->ts_res
,pdata
+8,&atime_ts
);
3450 put_long_date_full_timespec(conn
->ts_res
,pdata
+16,&mtime_ts
); /* write time */
3451 put_long_date_full_timespec(conn
->ts_res
,pdata
+24,&ctime_ts
); /* change time */
3452 SIVAL(pdata
,32,mode
);
3453 SIVAL(pdata
,36,0); /* padding. */
3455 SOFF_T(pdata
,0,allocation_size
);
3456 SOFF_T(pdata
,8,file_size
);
3457 SIVAL(pdata
,16,nlink
);
3458 SCVAL(pdata
,20,delete_pending
);
3459 SCVAL(pdata
,21,(mode
&FILE_ATTRIBUTE_DIRECTORY
)?1:0);
3462 SIVAL(pdata
,0,ea_size
);
3463 pdata
+= 4; /* EA info */
3464 status
= srvstr_push(dstart
, flags2
,
3466 PTR_DIFF(dend
, pdata
+4),
3468 if (!NT_STATUS_IS_OK(status
)) {
3473 data_size
= PTR_DIFF(pdata
,(*ppdata
));
3474 *fixed_portion
= 10;
3478 case SMB2_FILE_ALL_INFORMATION
:
3480 unsigned int ea_size
=
3481 estimate_ea_size(smb_fname
->fsp
);
3482 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
3483 put_long_date_full_timespec(conn
->ts_res
,pdata
+0x00,&create_time_ts
);
3484 put_long_date_full_timespec(conn
->ts_res
,pdata
+0x08,&atime_ts
);
3485 put_long_date_full_timespec(conn
->ts_res
,pdata
+0x10,&mtime_ts
); /* write time */
3486 put_long_date_full_timespec(conn
->ts_res
,pdata
+0x18,&ctime_ts
); /* change time */
3487 SIVAL(pdata
, 0x20, mode
);
3488 SIVAL(pdata
, 0x24, 0); /* padding. */
3489 SBVAL(pdata
, 0x28, allocation_size
);
3490 SBVAL(pdata
, 0x30, file_size
);
3491 SIVAL(pdata
, 0x38, nlink
);
3492 SCVAL(pdata
, 0x3C, delete_pending
);
3493 SCVAL(pdata
, 0x3D, (mode
&FILE_ATTRIBUTE_DIRECTORY
)?1:0);
3494 SSVAL(pdata
, 0x3E, 0); /* padding */
3495 SBVAL(pdata
, 0x40, file_id
);
3496 SIVAL(pdata
, 0x48, ea_size
);
3497 SIVAL(pdata
, 0x4C, access_mask
);
3498 SBVAL(pdata
, 0x50, pos
);
3499 SIVAL(pdata
, 0x58, mode
); /*TODO: mode != mode fix this!!! */
3500 SIVAL(pdata
, 0x5C, 0); /* No alignment needed. */
3504 status
= srvstr_push(dstart
, flags2
,
3506 PTR_DIFF(dend
, pdata
+4),
3508 if (!NT_STATUS_IS_OK(status
)) {
3513 data_size
= PTR_DIFF(pdata
,(*ppdata
));
3514 *fixed_portion
= 104;
3517 case SMB_FILE_INTERNAL_INFORMATION
:
3519 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
3520 SBVAL(pdata
, 0, file_id
);
3525 case SMB_FILE_ACCESS_INFORMATION
:
3526 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
3527 SIVAL(pdata
, 0, access_mask
);
3532 case SMB_FILE_NAME_INFORMATION
:
3533 /* Pathname with leading '\'. */
3536 byte_len
= dos_PutUniCode(pdata
+4,dos_fname
,(size_t)max_data_bytes
,False
);
3537 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
3538 SIVAL(pdata
,0,byte_len
);
3539 data_size
= 4 + byte_len
;
3543 case SMB_FILE_DISPOSITION_INFORMATION
:
3544 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
3546 SCVAL(pdata
,0,delete_pending
);
3550 case SMB_FILE_POSITION_INFORMATION
:
3551 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
3553 SOFF_T(pdata
,0,pos
);
3557 case SMB_FILE_MODE_INFORMATION
:
3558 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
3559 SIVAL(pdata
,0,mode
);
3564 case SMB_FILE_ALIGNMENT_INFORMATION
:
3565 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
3566 SIVAL(pdata
,0,0); /* No alignment needed. */
3572 * NT4 server just returns "invalid query" to this - if we try
3573 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
3576 /* The first statement above is false - verified using Thursby
3577 * client against NT4 -- gcolley.
3579 case SMB_QUERY_FILE_STREAM_INFO
:
3580 case SMB_FILE_STREAM_INFORMATION
: {
3581 unsigned int num_streams
= 0;
3582 struct stream_struct
*streams
= NULL
;
3584 DEBUG(10,("smbd_do_qfilepathinfo: "
3585 "SMB_FILE_STREAM_INFORMATION\n"));
3587 if (is_ntfs_stream_smb_fname(smb_fname
)) {
3588 return NT_STATUS_INVALID_PARAMETER
;
3591 status
= vfs_fstreaminfo(fsp
,
3596 if (!NT_STATUS_IS_OK(status
)) {
3597 DEBUG(10, ("could not get stream info: %s\n",
3598 nt_errstr(status
)));
3602 status
= marshall_stream_info(num_streams
, streams
,
3603 pdata
, max_data_bytes
,
3606 if (!NT_STATUS_IS_OK(status
)) {
3607 DEBUG(10, ("marshall_stream_info failed: %s\n",
3608 nt_errstr(status
)));
3609 TALLOC_FREE(streams
);
3613 TALLOC_FREE(streams
);
3615 *fixed_portion
= 32;
3619 case SMB_QUERY_COMPRESSION_INFO
:
3620 case SMB_FILE_COMPRESSION_INFORMATION
:
3621 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
3622 SOFF_T(pdata
,0,file_size
);
3623 SIVAL(pdata
,8,0); /* ??? */
3624 SIVAL(pdata
,12,0); /* ??? */
3626 *fixed_portion
= 16;
3629 case SMB_FILE_NETWORK_OPEN_INFORMATION
:
3630 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
3631 put_long_date_full_timespec(conn
->ts_res
,pdata
,&create_time_ts
);
3632 put_long_date_full_timespec(conn
->ts_res
,pdata
+8,&atime_ts
);
3633 put_long_date_full_timespec(conn
->ts_res
,pdata
+16,&mtime_ts
); /* write time */
3634 put_long_date_full_timespec(conn
->ts_res
,pdata
+24,&ctime_ts
); /* change time */
3635 SOFF_T(pdata
,32,allocation_size
);
3636 SOFF_T(pdata
,40,file_size
);
3637 SIVAL(pdata
,48,mode
);
3638 SIVAL(pdata
,52,0); /* ??? */
3640 *fixed_portion
= 56;
3643 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION
:
3644 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
3645 SIVAL(pdata
,0,mode
);
3652 * SMB2 UNIX Extensions.
3654 case SMB2_FILE_POSIX_INFORMATION_INTERNAL
:
3656 uint8_t *buf
= NULL
;
3659 if (!(conn
->sconn
->using_smb2
)) {
3660 return NT_STATUS_INVALID_LEVEL
;
3663 return NT_STATUS_INVALID_HANDLE
;
3665 if (!(fsp
->posix_flags
& FSP_POSIX_FLAGS_OPEN
)) {
3666 return NT_STATUS_INVALID_LEVEL
;
3669 /* Determine the size of the posix info context */
3670 plen
= store_smb2_posix_info(conn
,
3676 if (plen
== -1 || data_size
< plen
) {
3677 return NT_STATUS_INVALID_PARAMETER
;
3679 buf
= talloc_zero_size(mem_ctx
, plen
);
3681 return NT_STATUS_NO_MEMORY
;
3684 /* Store the context in buf */
3685 store_smb2_posix_info(conn
,
3691 memcpy(pdata
, buf
, plen
);
3697 return NT_STATUS_INVALID_LEVEL
;
3700 *pdata_size
= data_size
;
3701 return NT_STATUS_OK
;
3704 /****************************************************************************
3705 Set a hard link (called by UNIX extensions and by NT rename with HARD link
3707 ****************************************************************************/
3709 NTSTATUS
hardlink_internals(TALLOC_CTX
*ctx
,
3710 connection_struct
*conn
,
3711 struct smb_request
*req
,
3712 bool overwrite_if_exists
,
3713 const struct smb_filename
*smb_fname_old
,
3714 struct smb_filename
*smb_fname_new
)
3716 NTSTATUS status
= NT_STATUS_OK
;
3719 struct smb_filename
*parent_fname_old
= NULL
;
3720 struct smb_filename
*base_name_old
= NULL
;
3721 struct smb_filename
*parent_fname_new
= NULL
;
3722 struct smb_filename
*base_name_new
= NULL
;
3724 /* source must already exist. */
3725 if (!VALID_STAT(smb_fname_old
->st
)) {
3726 status
= NT_STATUS_OBJECT_NAME_NOT_FOUND
;
3730 /* No links from a directory. */
3731 if (S_ISDIR(smb_fname_old
->st
.st_ex_mode
)) {
3732 status
= NT_STATUS_FILE_IS_A_DIRECTORY
;
3736 /* Setting a hardlink to/from a stream isn't currently supported. */
3737 ok
= is_ntfs_stream_smb_fname(smb_fname_old
);
3739 DBG_DEBUG("Old name has streams\n");
3740 status
= NT_STATUS_INVALID_PARAMETER
;
3743 ok
= is_ntfs_stream_smb_fname(smb_fname_new
);
3745 DBG_DEBUG("New name has streams\n");
3746 status
= NT_STATUS_INVALID_PARAMETER
;
3750 status
= parent_pathref(talloc_tos(),
3755 if (!NT_STATUS_IS_OK(status
)) {
3759 status
= parent_pathref(talloc_tos(),
3764 if (!NT_STATUS_IS_OK(status
)) {
3768 if (VALID_STAT(smb_fname_new
->st
)) {
3769 if (overwrite_if_exists
) {
3770 if (S_ISDIR(smb_fname_new
->st
.st_ex_mode
)) {
3771 status
= NT_STATUS_FILE_IS_A_DIRECTORY
;
3774 status
= unlink_internals(conn
,
3776 FILE_ATTRIBUTE_NORMAL
,
3777 NULL
, /* new_dirfsp */
3779 if (!NT_STATUS_IS_OK(status
)) {
3783 /* Disallow if newname already exists. */
3784 status
= NT_STATUS_OBJECT_NAME_COLLISION
;
3789 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
3790 smb_fname_old
->base_name
, smb_fname_new
->base_name
));
3792 ret
= SMB_VFS_LINKAT(conn
,
3793 parent_fname_old
->fsp
,
3795 parent_fname_new
->fsp
,
3800 status
= map_nt_error_from_unix(errno
);
3801 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
3802 nt_errstr(status
), smb_fname_old
->base_name
,
3803 smb_fname_new
->base_name
));
3808 TALLOC_FREE(parent_fname_old
);
3809 TALLOC_FREE(parent_fname_new
);
3813 /****************************************************************************
3814 Deal with setting the time from any of the setfilepathinfo functions.
3815 NOTE !!!! The check for FILE_WRITE_ATTRIBUTES access must be done *before*
3816 calling this function.
3817 ****************************************************************************/
3819 NTSTATUS
smb_set_file_time(connection_struct
*conn
,
3821 struct smb_filename
*smb_fname
,
3822 struct smb_file_time
*ft
,
3823 bool setting_write_time
)
3825 struct files_struct
*set_fsp
= NULL
;
3826 struct timeval_buf tbuf
[4];
3828 FILE_NOTIFY_CHANGE_LAST_ACCESS
3829 |FILE_NOTIFY_CHANGE_LAST_WRITE
3830 |FILE_NOTIFY_CHANGE_CREATION
;
3833 if (!VALID_STAT(smb_fname
->st
)) {
3834 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
3839 return NT_STATUS_OK
;
3842 set_fsp
= metadata_fsp(fsp
);
3844 /* get some defaults (no modifications) if any info is zero or -1. */
3845 if (is_omit_timespec(&ft
->create_time
)) {
3846 action
&= ~FILE_NOTIFY_CHANGE_CREATION
;
3849 if (is_omit_timespec(&ft
->atime
)) {
3850 action
&= ~FILE_NOTIFY_CHANGE_LAST_ACCESS
;
3853 if (is_omit_timespec(&ft
->mtime
)) {
3854 action
&= ~FILE_NOTIFY_CHANGE_LAST_WRITE
;
3857 if (!setting_write_time
) {
3858 /* ft->mtime comes from change time, not write time. */
3859 action
&= ~FILE_NOTIFY_CHANGE_LAST_WRITE
;
3862 /* Ensure the resolution is the correct for
3863 * what we can store on this filesystem. */
3865 round_timespec(conn
->ts_res
, &ft
->create_time
);
3866 round_timespec(conn
->ts_res
, &ft
->ctime
);
3867 round_timespec(conn
->ts_res
, &ft
->atime
);
3868 round_timespec(conn
->ts_res
, &ft
->mtime
);
3870 DBG_DEBUG("smb_set_filetime: actime: %s\n ",
3871 timespec_string_buf(&ft
->atime
, true, &tbuf
[0]));
3872 DBG_DEBUG("smb_set_filetime: modtime: %s\n ",
3873 timespec_string_buf(&ft
->mtime
, true, &tbuf
[1]));
3874 DBG_DEBUG("smb_set_filetime: ctime: %s\n ",
3875 timespec_string_buf(&ft
->ctime
, true, &tbuf
[2]));
3876 DBG_DEBUG("smb_set_file_time: createtime: %s\n ",
3877 timespec_string_buf(&ft
->create_time
, true, &tbuf
[3]));
3879 if (setting_write_time
) {
3881 * This was a Windows setfileinfo on an open file.
3882 * NT does this a lot. We also need to
3883 * set the time here, as it can be read by
3884 * FindFirst/FindNext and with the patch for bug #2045
3885 * in smbd/fileio.c it ensures that this timestamp is
3886 * kept sticky even after a write. We save the request
3887 * away and will set it on file close and after a write. JRA.
3890 DBG_DEBUG("setting pending modtime to %s\n",
3891 timespec_string_buf(&ft
->mtime
, true, &tbuf
[0]));
3893 if (set_fsp
!= NULL
) {
3894 set_sticky_write_time_fsp(set_fsp
, ft
->mtime
);
3896 set_sticky_write_time_path(
3897 vfs_file_id_from_sbuf(conn
, &smb_fname
->st
),
3902 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
3904 ret
= file_ntimes(conn
, set_fsp
, ft
);
3906 return map_nt_error_from_unix(errno
);
3909 notify_fname(conn
, NOTIFY_ACTION_MODIFIED
, action
,
3910 smb_fname
->base_name
);
3911 return NT_STATUS_OK
;
3914 /****************************************************************************
3915 Deal with setting the dosmode from any of the setfilepathinfo functions.
3916 NB. The check for FILE_WRITE_ATTRIBUTES access on this path must have been
3917 done before calling this function.
3918 ****************************************************************************/
3920 static NTSTATUS
smb_set_file_dosmode(connection_struct
*conn
,
3921 struct files_struct
*fsp
,
3924 struct files_struct
*dos_fsp
= NULL
;
3925 uint32_t current_dosmode
;
3928 if (!VALID_STAT(fsp
->fsp_name
->st
)) {
3929 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
3932 dos_fsp
= metadata_fsp(fsp
);
3935 if (S_ISDIR(fsp
->fsp_name
->st
.st_ex_mode
)) {
3936 dosmode
|= FILE_ATTRIBUTE_DIRECTORY
;
3938 dosmode
&= ~FILE_ATTRIBUTE_DIRECTORY
;
3942 DBG_DEBUG("dosmode: 0x%" PRIx32
"\n", dosmode
);
3944 /* check the mode isn't different, before changing it */
3946 return NT_STATUS_OK
;
3948 current_dosmode
= fdos_mode(dos_fsp
);
3949 if (dosmode
== current_dosmode
) {
3950 return NT_STATUS_OK
;
3953 DBG_DEBUG("file %s : setting dos mode 0x%" PRIx32
"\n",
3954 fsp_str_dbg(dos_fsp
), dosmode
);
3956 ret
= file_set_dosmode(conn
, dos_fsp
->fsp_name
, dosmode
, NULL
, false);
3958 DBG_WARNING("file_set_dosmode of %s failed: %s\n",
3959 fsp_str_dbg(dos_fsp
), strerror(errno
));
3960 return map_nt_error_from_unix(errno
);
3963 return NT_STATUS_OK
;
3966 /****************************************************************************
3967 Deal with setting the size from any of the setfilepathinfo functions.
3968 ****************************************************************************/
3970 NTSTATUS
smb_set_file_size(connection_struct
*conn
,
3971 struct smb_request
*req
,
3973 struct smb_filename
*smb_fname
,
3974 const SMB_STRUCT_STAT
*psbuf
,
3976 bool fail_after_createfile
)
3978 NTSTATUS status
= NT_STATUS_OK
;
3979 files_struct
*new_fsp
= NULL
;
3981 if (!VALID_STAT(*psbuf
)) {
3982 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
3985 DBG_INFO("size: %"PRIu64
", file_size_stat=%"PRIu64
"\n",
3987 get_file_size_stat(psbuf
));
3989 if (size
== get_file_size_stat(psbuf
)) {
3991 return NT_STATUS_OK
;
3993 if (!fsp
->fsp_flags
.modified
) {
3994 return NT_STATUS_OK
;
3996 trigger_write_time_update_immediate(fsp
);
3997 return NT_STATUS_OK
;
4000 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
4001 smb_fname_str_dbg(smb_fname
), (double)size
));
4004 !fsp
->fsp_flags
.is_pathref
&&
4005 fsp_get_io_fd(fsp
) != -1)
4007 /* Handle based call. */
4008 if (!(fsp
->access_mask
& FILE_WRITE_DATA
)) {
4009 return NT_STATUS_ACCESS_DENIED
;
4012 if (vfs_set_filelen(fsp
, size
) == -1) {
4013 return map_nt_error_from_unix(errno
);
4015 trigger_write_time_update_immediate(fsp
);
4016 return NT_STATUS_OK
;
4019 status
= SMB_VFS_CREATE_FILE(
4023 smb_fname
, /* fname */
4024 FILE_WRITE_DATA
, /* access_mask */
4025 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
4027 FILE_OPEN
, /* create_disposition*/
4028 0, /* create_options */
4029 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
4030 0, /* oplock_request */
4032 0, /* allocation_size */
4033 0, /* private_flags */
4036 &new_fsp
, /* result */
4038 NULL
, NULL
); /* create context */
4040 if (!NT_STATUS_IS_OK(status
)) {
4041 /* NB. We check for open_was_deferred in the caller. */
4045 /* See RAW-SFILEINFO-END-OF-FILE */
4046 if (fail_after_createfile
) {
4047 close_file_free(req
, &new_fsp
, NORMAL_CLOSE
);
4048 return NT_STATUS_INVALID_LEVEL
;
4051 if (vfs_set_filelen(new_fsp
, size
) == -1) {
4052 status
= map_nt_error_from_unix(errno
);
4053 close_file_free(req
, &new_fsp
, NORMAL_CLOSE
);
4057 trigger_write_time_update_immediate(new_fsp
);
4058 close_file_free(req
, &new_fsp
, NORMAL_CLOSE
);
4059 return NT_STATUS_OK
;
4062 /****************************************************************************
4063 Deal with SMB_INFO_SET_EA.
4064 ****************************************************************************/
4066 static NTSTATUS
smb_info_set_ea(connection_struct
*conn
,
4070 struct smb_filename
*smb_fname
)
4072 struct ea_list
*ea_list
= NULL
;
4073 TALLOC_CTX
*ctx
= NULL
;
4074 NTSTATUS status
= NT_STATUS_OK
;
4076 if (total_data
< 10) {
4078 /* OS/2 workplace shell seems to send SET_EA requests of "null"
4079 length. They seem to have no effect. Bug #3212. JRA */
4081 if ((total_data
== 4) && (IVAL(pdata
,0) == 4)) {
4082 /* We're done. We only get EA info in this call. */
4083 return NT_STATUS_OK
;
4086 return NT_STATUS_INVALID_PARAMETER
;
4089 if (IVAL(pdata
,0) > total_data
) {
4090 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
4091 IVAL(pdata
,0), (unsigned int)total_data
));
4092 return NT_STATUS_INVALID_PARAMETER
;
4096 ea_list
= read_ea_list(ctx
, pdata
+ 4, total_data
- 4);
4098 return NT_STATUS_INVALID_PARAMETER
;
4103 * The only way fsp can be NULL here is if
4104 * smb_fname points at a symlink and
4105 * and we're in POSIX context.
4106 * Ensure this is the case.
4108 * In this case we cannot set the EA.
4110 SMB_ASSERT(smb_fname
->flags
& SMB_FILENAME_POSIX_PATH
);
4111 return NT_STATUS_ACCESS_DENIED
;
4114 status
= set_ea(conn
, fsp
, ea_list
);
4119 /****************************************************************************
4120 Deal with SMB_FILE_FULL_EA_INFORMATION set.
4121 ****************************************************************************/
4123 static NTSTATUS
smb_set_file_full_ea_info(connection_struct
*conn
,
4128 struct ea_list
*ea_list
= NULL
;
4132 return NT_STATUS_INVALID_HANDLE
;
4135 if (!lp_ea_support(SNUM(conn
))) {
4136 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
4137 "EA's not supported.\n",
4138 (unsigned int)total_data
));
4139 return NT_STATUS_EAS_NOT_SUPPORTED
;
4142 if (total_data
< 10) {
4143 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
4145 (unsigned int)total_data
));
4146 return NT_STATUS_INVALID_PARAMETER
;
4149 ea_list
= read_nttrans_ea_list(talloc_tos(),
4154 return NT_STATUS_INVALID_PARAMETER
;
4157 status
= set_ea(conn
, fsp
, ea_list
);
4159 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
4160 smb_fname_str_dbg(fsp
->fsp_name
),
4161 nt_errstr(status
) ));
4167 /****************************************************************************
4168 Deal with SMB_SET_FILE_DISPOSITION_INFO.
4169 ****************************************************************************/
4171 NTSTATUS
smb_set_file_disposition_info(connection_struct
*conn
,
4175 struct smb_filename
*smb_fname
)
4177 NTSTATUS status
= NT_STATUS_OK
;
4178 bool delete_on_close
;
4179 uint32_t dosmode
= 0;
4181 if (total_data
< 1) {
4182 return NT_STATUS_INVALID_PARAMETER
;
4186 return NT_STATUS_INVALID_HANDLE
;
4189 delete_on_close
= (CVAL(pdata
,0) ? True
: False
);
4190 dosmode
= fdos_mode(fsp
);
4192 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
4193 "delete_on_close = %u\n",
4194 smb_fname_str_dbg(smb_fname
),
4195 (unsigned int)dosmode
,
4196 (unsigned int)delete_on_close
));
4198 if (delete_on_close
) {
4199 status
= can_set_delete_on_close(fsp
, dosmode
);
4200 if (!NT_STATUS_IS_OK(status
)) {
4205 /* The set is across all open files on this dev/inode pair. */
4206 if (!set_delete_on_close(fsp
, delete_on_close
,
4207 conn
->session_info
->security_token
,
4208 conn
->session_info
->unix_token
)) {
4209 return NT_STATUS_ACCESS_DENIED
;
4211 return NT_STATUS_OK
;
4214 /****************************************************************************
4215 Deal with SMB_FILE_POSITION_INFORMATION.
4216 ****************************************************************************/
4218 static NTSTATUS
smb_file_position_information(connection_struct
*conn
,
4223 uint64_t position_information
;
4225 if (total_data
< 8) {
4226 return NT_STATUS_INVALID_PARAMETER
;
4230 /* Ignore on pathname based set. */
4231 return NT_STATUS_OK
;
4234 position_information
= (uint64_t)IVAL(pdata
,0);
4235 position_information
|= (((uint64_t)IVAL(pdata
,4)) << 32);
4237 DEBUG(10,("smb_file_position_information: Set file position "
4238 "information for file %s to %.0f\n", fsp_str_dbg(fsp
),
4239 (double)position_information
));
4240 fh_set_position_information(fsp
->fh
, position_information
);
4241 return NT_STATUS_OK
;
4244 /****************************************************************************
4245 Deal with SMB_FILE_MODE_INFORMATION.
4246 ****************************************************************************/
4248 static NTSTATUS
smb_file_mode_information(connection_struct
*conn
,
4254 if (total_data
< 4) {
4255 return NT_STATUS_INVALID_PARAMETER
;
4257 mode
= IVAL(pdata
,0);
4258 if (mode
!= 0 && mode
!= 2 && mode
!= 4 && mode
!= 6) {
4259 return NT_STATUS_INVALID_PARAMETER
;
4261 return NT_STATUS_OK
;
4264 /****************************************************************************
4265 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
4266 ****************************************************************************/
4268 static NTSTATUS
smb2_file_rename_information(connection_struct
*conn
,
4269 struct smb_request
*req
,
4273 struct smb_filename
*smb_fname_src
)
4277 char *newname
= NULL
;
4278 struct files_struct
*dst_dirfsp
= NULL
;
4279 struct smb_filename
*smb_fname_dst
= NULL
;
4280 const char *dst_original_lcomp
= NULL
;
4281 uint32_t ucf_flags
= ucf_flags_from_smb_request(req
);
4282 NTSTATUS status
= NT_STATUS_OK
;
4283 TALLOC_CTX
*ctx
= talloc_tos();
4286 return NT_STATUS_INVALID_HANDLE
;
4289 if (total_data
< 20) {
4290 return NT_STATUS_INVALID_PARAMETER
;
4293 overwrite
= (CVAL(pdata
,0) ? True
: False
);
4294 len
= IVAL(pdata
,16);
4296 if (len
> (total_data
- 20) || (len
== 0)) {
4297 return NT_STATUS_INVALID_PARAMETER
;
4300 (void)srvstr_pull_talloc(ctx
,
4308 if (newname
== NULL
) {
4309 return NT_STATUS_INVALID_PARAMETER
;
4312 /* SMB2 rename paths are never DFS. */
4313 req
->flags2
&= ~FLAGS2_DFS_PATHNAMES
;
4314 ucf_flags
&= ~UCF_DFS_PATHNAME
;
4316 status
= check_path_syntax(newname
,
4317 fsp
->fsp_name
->flags
& SMB_FILENAME_POSIX_PATH
);
4318 if (!NT_STATUS_IS_OK(status
)) {
4322 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
4325 if (newname
[0] == ':') {
4326 /* Create an smb_fname to call rename_internals_fsp() with. */
4327 smb_fname_dst
= synthetic_smb_fname(talloc_tos(),
4328 fsp
->base_fsp
->fsp_name
->base_name
,
4331 fsp
->base_fsp
->fsp_name
->twrp
,
4332 fsp
->base_fsp
->fsp_name
->flags
);
4333 if (smb_fname_dst
== NULL
) {
4334 status
= NT_STATUS_NO_MEMORY
;
4338 status
= filename_convert_dirfsp(ctx
,
4342 0, /* Never a TWRP. */
4345 if (!NT_STATUS_IS_OK(status
)) {
4351 * Set the original last component, since
4352 * rename_internals_fsp() requires it.
4354 dst_original_lcomp
= get_original_lcomp(smb_fname_dst
,
4358 if (dst_original_lcomp
== NULL
) {
4359 status
= NT_STATUS_NO_MEMORY
;
4363 DEBUG(10,("smb2_file_rename_information: "
4364 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
4365 fsp_fnum_dbg(fsp
), fsp_str_dbg(fsp
),
4366 smb_fname_str_dbg(smb_fname_dst
)));
4367 status
= rename_internals_fsp(conn
,
4371 (FILE_ATTRIBUTE_HIDDEN
|FILE_ATTRIBUTE_SYSTEM
),
4375 TALLOC_FREE(smb_fname_dst
);
4379 static NTSTATUS
smb2_file_link_information(connection_struct
*conn
,
4380 struct smb_request
*req
,
4384 struct smb_filename
*smb_fname_src
)
4388 char *newname
= NULL
;
4389 struct files_struct
*dst_dirfsp
= NULL
;
4390 struct smb_filename
*smb_fname_dst
= NULL
;
4391 NTSTATUS status
= NT_STATUS_OK
;
4392 uint32_t ucf_flags
= ucf_flags_from_smb_request(req
);
4394 TALLOC_CTX
*ctx
= talloc_tos();
4397 return NT_STATUS_INVALID_HANDLE
;
4400 if (total_data
< 20) {
4401 return NT_STATUS_INVALID_PARAMETER
;
4404 overwrite
= (CVAL(pdata
,0) ? true : false);
4405 len
= IVAL(pdata
,16);
4407 if (len
> (total_data
- 20) || (len
== 0)) {
4408 return NT_STATUS_INVALID_PARAMETER
;
4411 ret
= srvstr_pull_talloc(ctx
,
4419 if (ret
== (size_t)-1 || newname
== NULL
) {
4420 return NT_STATUS_INVALID_PARAMETER
;
4423 /* SMB2 hardlink paths are never DFS. */
4424 req
->flags2
&= ~FLAGS2_DFS_PATHNAMES
;
4425 ucf_flags
&= ~UCF_DFS_PATHNAME
;
4427 status
= check_path_syntax(newname
,
4428 fsp
->fsp_name
->flags
& SMB_FILENAME_POSIX_PATH
);
4429 if (!NT_STATUS_IS_OK(status
)) {
4433 DBG_DEBUG("got name |%s|\n", newname
);
4435 status
= filename_convert_dirfsp(ctx
,
4442 if (!NT_STATUS_IS_OK(status
)) {
4446 if (fsp
->base_fsp
) {
4447 /* No stream names. */
4448 return NT_STATUS_NOT_SUPPORTED
;
4451 DBG_DEBUG("SMB_FILE_LINK_INFORMATION (%s) %s -> %s\n",
4452 fsp_fnum_dbg(fsp
), fsp_str_dbg(fsp
),
4453 smb_fname_str_dbg(smb_fname_dst
));
4454 status
= hardlink_internals(ctx
,
4461 TALLOC_FREE(smb_fname_dst
);
4465 static NTSTATUS
smb_file_link_information(connection_struct
*conn
,
4466 struct smb_request
*req
,
4470 struct smb_filename
*smb_fname_src
)
4474 char *newname
= NULL
;
4475 struct files_struct
*dst_dirfsp
= NULL
;
4476 struct smb_filename
*smb_fname_dst
= NULL
;
4477 NTSTATUS status
= NT_STATUS_OK
;
4478 uint32_t ucf_flags
= ucf_flags_from_smb_request(req
);
4479 NTTIME dst_twrp
= 0;
4480 TALLOC_CTX
*ctx
= talloc_tos();
4483 return NT_STATUS_INVALID_HANDLE
;
4486 if (total_data
< 20) {
4487 return NT_STATUS_INVALID_PARAMETER
;
4490 overwrite
= (CVAL(pdata
,0) ? true : false);
4491 len
= IVAL(pdata
,16);
4493 if (len
> (total_data
- 20) || (len
== 0)) {
4494 return NT_STATUS_INVALID_PARAMETER
;
4497 if (smb_fname_src
->flags
& SMB_FILENAME_POSIX_PATH
) {
4498 srvstr_get_path_posix(ctx
,
4506 ucf_flags
|= UCF_POSIX_PATHNAMES
;
4508 srvstr_get_path(ctx
,
4517 if (!NT_STATUS_IS_OK(status
)) {
4521 DEBUG(10,("smb_file_link_information: got name |%s|\n",
4524 if (ucf_flags
& UCF_GMT_PATHNAME
) {
4525 extract_snapshot_token(newname
, &dst_twrp
);
4527 /* hardlink paths are never DFS. */
4528 ucf_flags
&= ~UCF_DFS_PATHNAME
;
4530 status
= filename_convert_dirfsp(ctx
,
4537 if (!NT_STATUS_IS_OK(status
)) {
4541 if (fsp
->base_fsp
) {
4542 /* No stream names. */
4543 return NT_STATUS_NOT_SUPPORTED
;
4546 DEBUG(10,("smb_file_link_information: "
4547 "SMB_FILE_LINK_INFORMATION (%s) %s -> %s\n",
4548 fsp_fnum_dbg(fsp
), fsp_str_dbg(fsp
),
4549 smb_fname_str_dbg(smb_fname_dst
)));
4550 status
= hardlink_internals(ctx
,
4557 TALLOC_FREE(smb_fname_dst
);
4562 /****************************************************************************
4563 Deal with SMB_FILE_RENAME_INFORMATION.
4564 ****************************************************************************/
4566 static NTSTATUS
smb_file_rename_information(connection_struct
*conn
,
4567 struct smb_request
*req
,
4571 struct smb_filename
*smb_fname_src
)
4576 char *newname
= NULL
;
4577 struct files_struct
*dst_dirfsp
= NULL
;
4578 struct smb_filename
*smb_fname_dst
= NULL
;
4579 const char *dst_original_lcomp
= NULL
;
4580 NTSTATUS status
= NT_STATUS_OK
;
4582 TALLOC_CTX
*ctx
= talloc_tos();
4584 if (total_data
< 13) {
4585 return NT_STATUS_INVALID_PARAMETER
;
4588 overwrite
= (CVAL(pdata
,0) != 0);
4589 root_fid
= IVAL(pdata
,4);
4590 len
= IVAL(pdata
,8);
4592 if (len
> (total_data
- 12) || (len
== 0) || (root_fid
!= 0)) {
4593 return NT_STATUS_INVALID_PARAMETER
;
4596 if (req
->posix_pathnames
) {
4597 srvstr_get_path_posix(ctx
,
4606 srvstr_get_path(ctx
,
4615 if (!NT_STATUS_IS_OK(status
)) {
4619 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
4622 /* Check the new name has no '/' characters. */
4623 if (strchr_m(newname
, '/')) {
4624 return NT_STATUS_NOT_SUPPORTED
;
4627 if (fsp
&& fsp
->base_fsp
) {
4628 /* newname must be a stream name. */
4629 if (newname
[0] != ':') {
4630 return NT_STATUS_NOT_SUPPORTED
;
4633 /* Create an smb_fname to call rename_internals_fsp() with. */
4634 smb_fname_dst
= synthetic_smb_fname(talloc_tos(),
4635 fsp
->base_fsp
->fsp_name
->base_name
,
4638 fsp
->base_fsp
->fsp_name
->twrp
,
4639 fsp
->base_fsp
->fsp_name
->flags
);
4640 if (smb_fname_dst
== NULL
) {
4641 status
= NT_STATUS_NO_MEMORY
;
4646 * Get the original last component, since
4647 * rename_internals_fsp() requires it.
4649 dst_original_lcomp
= get_original_lcomp(smb_fname_dst
,
4653 if (dst_original_lcomp
== NULL
) {
4654 status
= NT_STATUS_NO_MEMORY
;
4660 * Build up an smb_fname_dst based on the filename passed in.
4661 * We basically just strip off the last component, and put on
4662 * the newname instead.
4664 char *base_name
= NULL
;
4665 uint32_t ucf_flags
= ucf_flags_from_smb_request(req
);
4666 NTTIME dst_twrp
= 0;
4668 /* newname must *not* be a stream name. */
4669 if (newname
[0] == ':') {
4670 return NT_STATUS_NOT_SUPPORTED
;
4674 * Strip off the last component (filename) of the path passed
4677 base_name
= talloc_strdup(ctx
, smb_fname_src
->base_name
);
4679 return NT_STATUS_NO_MEMORY
;
4681 p
= strrchr_m(base_name
, '/');
4685 base_name
= talloc_strdup(ctx
, "");
4687 return NT_STATUS_NO_MEMORY
;
4690 /* Append the new name. */
4691 base_name
= talloc_asprintf_append(base_name
,
4695 return NT_STATUS_NO_MEMORY
;
4698 if (ucf_flags
& UCF_GMT_PATHNAME
) {
4699 extract_snapshot_token(base_name
, &dst_twrp
);
4702 /* The newname is *not* a DFS path. */
4703 ucf_flags
&= ~UCF_DFS_PATHNAME
;
4705 status
= filename_convert_dirfsp(ctx
,
4713 if (!NT_STATUS_IS_OK(status
)) {
4716 dst_original_lcomp
= get_original_lcomp(smb_fname_dst
,
4720 if (dst_original_lcomp
== NULL
) {
4721 status
= NT_STATUS_NO_MEMORY
;
4726 if (fsp
!= NULL
&& fsp
->fsp_flags
.is_fsa
) {
4727 DEBUG(10,("smb_file_rename_information: "
4728 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
4729 fsp_fnum_dbg(fsp
), fsp_str_dbg(fsp
),
4730 smb_fname_str_dbg(smb_fname_dst
)));
4731 status
= rename_internals_fsp(conn
,
4738 DEBUG(10,("smb_file_rename_information: "
4739 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
4740 smb_fname_str_dbg(smb_fname_src
),
4741 smb_fname_str_dbg(smb_fname_dst
)));
4742 status
= rename_internals(ctx
,
4745 NULL
, /* src_dirfsp */
4751 FILE_WRITE_ATTRIBUTES
);
4754 TALLOC_FREE(smb_fname_dst
);
4758 /****************************************************************************
4759 Deal with SMB_SET_FILE_BASIC_INFO.
4760 ****************************************************************************/
4762 static NTSTATUS
smb_set_file_basic_info(connection_struct
*conn
,
4766 struct smb_filename
*smb_fname
)
4768 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
4769 struct smb_file_time ft
;
4770 uint32_t dosmode
= 0;
4771 NTSTATUS status
= NT_STATUS_OK
;
4773 init_smb_file_time(&ft
);
4775 if (total_data
< 36) {
4776 return NT_STATUS_INVALID_PARAMETER
;
4780 return NT_STATUS_INVALID_HANDLE
;
4783 status
= check_access_fsp(fsp
, FILE_WRITE_ATTRIBUTES
);
4784 if (!NT_STATUS_IS_OK(status
)) {
4788 /* Set the attributes */
4789 dosmode
= IVAL(pdata
,32);
4790 status
= smb_set_file_dosmode(conn
, fsp
, dosmode
);
4791 if (!NT_STATUS_IS_OK(status
)) {
4796 ft
.create_time
= pull_long_date_full_timespec(pdata
);
4799 ft
.atime
= pull_long_date_full_timespec(pdata
+8);
4802 ft
.mtime
= pull_long_date_full_timespec(pdata
+16);
4805 ft
.ctime
= pull_long_date_full_timespec(pdata
+24);
4807 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
4808 smb_fname_str_dbg(smb_fname
)));
4810 status
= smb_set_file_time(conn
, fsp
, smb_fname
, &ft
, true);
4811 if (!NT_STATUS_IS_OK(status
)) {
4815 if (fsp
->fsp_flags
.modified
) {
4816 trigger_write_time_update_immediate(fsp
);
4818 return NT_STATUS_OK
;
4821 /****************************************************************************
4822 Deal with SMB_INFO_STANDARD.
4823 ****************************************************************************/
4825 static NTSTATUS
smb_set_info_standard(connection_struct
*conn
,
4829 struct smb_filename
*smb_fname
)
4832 struct smb_file_time ft
;
4834 init_smb_file_time(&ft
);
4836 if (total_data
< 12) {
4837 return NT_STATUS_INVALID_PARAMETER
;
4841 return NT_STATUS_INVALID_HANDLE
;
4845 ft
.create_time
= time_t_to_full_timespec(srv_make_unix_date2(pdata
));
4847 ft
.atime
= time_t_to_full_timespec(srv_make_unix_date2(pdata
+4));
4849 ft
.mtime
= time_t_to_full_timespec(srv_make_unix_date2(pdata
+8));
4851 DEBUG(10,("smb_set_info_standard: file %s\n",
4852 smb_fname_str_dbg(smb_fname
)));
4854 status
= check_access_fsp(fsp
, FILE_WRITE_ATTRIBUTES
);
4855 if (!NT_STATUS_IS_OK(status
)) {
4859 status
= smb_set_file_time(conn
, fsp
, smb_fname
, &ft
, true);
4860 if (!NT_STATUS_IS_OK(status
)) {
4864 if (fsp
->fsp_flags
.modified
) {
4865 trigger_write_time_update_immediate(fsp
);
4867 return NT_STATUS_OK
;
4870 /****************************************************************************
4871 Deal with SMB_SET_FILE_ALLOCATION_INFO.
4872 ****************************************************************************/
4874 static NTSTATUS
smb_set_file_allocation_info(connection_struct
*conn
,
4875 struct smb_request
*req
,
4879 struct smb_filename
*smb_fname
)
4881 uint64_t allocation_size
= 0;
4882 NTSTATUS status
= NT_STATUS_OK
;
4883 files_struct
*new_fsp
= NULL
;
4885 if (!VALID_STAT(smb_fname
->st
)) {
4886 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
4889 if (total_data
< 8) {
4890 return NT_STATUS_INVALID_PARAMETER
;
4893 allocation_size
= (uint64_t)IVAL(pdata
,0);
4894 allocation_size
|= (((uint64_t)IVAL(pdata
,4)) << 32);
4895 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
4896 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname
),
4897 (double)allocation_size
));
4899 if (allocation_size
) {
4900 allocation_size
= smb_roundup(conn
, allocation_size
);
4903 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
4904 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname
),
4905 (double)allocation_size
));
4908 !fsp
->fsp_flags
.is_pathref
&&
4909 fsp_get_io_fd(fsp
) != -1)
4911 /* Open file handle. */
4912 if (!(fsp
->access_mask
& FILE_WRITE_DATA
)) {
4913 return NT_STATUS_ACCESS_DENIED
;
4916 /* Only change if needed. */
4917 if (allocation_size
!= get_file_size_stat(&smb_fname
->st
)) {
4918 if (vfs_allocate_file_space(fsp
, allocation_size
) == -1) {
4919 return map_nt_error_from_unix(errno
);
4922 /* But always update the time. */
4924 * This is equivalent to a write. Ensure it's seen immediately
4925 * if there are no pending writes.
4927 trigger_write_time_update_immediate(fsp
);
4928 return NT_STATUS_OK
;
4931 /* Pathname or stat or directory file. */
4932 status
= SMB_VFS_CREATE_FILE(
4936 smb_fname
, /* fname */
4937 FILE_WRITE_DATA
, /* access_mask */
4938 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
4940 FILE_OPEN
, /* create_disposition*/
4941 0, /* create_options */
4942 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
4943 0, /* oplock_request */
4945 0, /* allocation_size */
4946 0, /* private_flags */
4949 &new_fsp
, /* result */
4951 NULL
, NULL
); /* create context */
4953 if (!NT_STATUS_IS_OK(status
)) {
4954 /* NB. We check for open_was_deferred in the caller. */
4958 /* Only change if needed. */
4959 if (allocation_size
!= get_file_size_stat(&smb_fname
->st
)) {
4960 if (vfs_allocate_file_space(new_fsp
, allocation_size
) == -1) {
4961 status
= map_nt_error_from_unix(errno
);
4962 close_file_free(req
, &new_fsp
, NORMAL_CLOSE
);
4967 /* Changing the allocation size should set the last mod time. */
4969 * This is equivalent to a write. Ensure it's seen immediately
4970 * if there are no pending writes.
4972 trigger_write_time_update_immediate(new_fsp
);
4973 close_file_free(req
, &new_fsp
, NORMAL_CLOSE
);
4974 return NT_STATUS_OK
;
4977 /****************************************************************************
4978 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
4979 ****************************************************************************/
4981 static NTSTATUS
smb_set_file_end_of_file_info(connection_struct
*conn
,
4982 struct smb_request
*req
,
4986 struct smb_filename
*smb_fname
,
4987 bool fail_after_createfile
)
4991 if (total_data
< 8) {
4992 return NT_STATUS_INVALID_PARAMETER
;
4995 size
= IVAL(pdata
,0);
4996 size
|= (((off_t
)IVAL(pdata
,4)) << 32);
4997 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
4998 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname
),
5001 return smb_set_file_size(conn
, req
,
5006 fail_after_createfile
);
5009 NTSTATUS
smbd_do_setfilepathinfo(connection_struct
*conn
,
5010 struct smb_request
*req
,
5011 TALLOC_CTX
*mem_ctx
,
5012 uint16_t info_level
,
5014 struct smb_filename
*smb_fname
,
5015 char **ppdata
, int total_data
,
5018 char *pdata
= *ppdata
;
5019 NTSTATUS status
= NT_STATUS_OK
;
5020 int data_return_size
= 0;
5024 DEBUG(3,("smbd_do_setfilepathinfo: %s (%s) info_level=%d "
5025 "totdata=%d\n", smb_fname_str_dbg(smb_fname
),
5027 info_level
, total_data
));
5029 switch (info_level
) {
5031 case SMB_INFO_STANDARD
:
5033 status
= smb_set_info_standard(conn
,
5041 case SMB_INFO_SET_EA
:
5043 status
= smb_info_set_ea(conn
,
5051 case SMB_SET_FILE_BASIC_INFO
:
5052 case SMB_FILE_BASIC_INFORMATION
:
5054 status
= smb_set_file_basic_info(conn
,
5062 case SMB_FILE_ALLOCATION_INFORMATION
:
5063 case SMB_SET_FILE_ALLOCATION_INFO
:
5065 status
= smb_set_file_allocation_info(conn
, req
,
5073 case SMB_FILE_END_OF_FILE_INFORMATION
:
5074 case SMB_SET_FILE_END_OF_FILE_INFO
:
5077 * XP/Win7 both fail after the createfile with
5078 * SMB_SET_FILE_END_OF_FILE_INFO but not
5079 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
5080 * The level is known here, so pass it down
5084 (info_level
== SMB_SET_FILE_END_OF_FILE_INFO
);
5086 status
= smb_set_file_end_of_file_info(conn
, req
,
5095 case SMB_FILE_DISPOSITION_INFORMATION
:
5096 case SMB_SET_FILE_DISPOSITION_INFO
: /* Set delete on close for open file. */
5099 /* JRA - We used to just ignore this on a path ?
5100 * Shouldn't this be invalid level on a pathname
5103 if (tran_call
!= TRANSACT2_SETFILEINFO
) {
5104 return ERROR_NT(NT_STATUS_INVALID_LEVEL
);
5107 status
= smb_set_file_disposition_info(conn
,
5115 case SMB_FILE_POSITION_INFORMATION
:
5117 status
= smb_file_position_information(conn
,
5124 case SMB_FILE_FULL_EA_INFORMATION
:
5126 status
= smb_set_file_full_ea_info(conn
,
5133 /* From tridge Samba4 :
5134 * MODE_INFORMATION in setfileinfo (I have no
5135 * idea what "mode information" on a file is - it takes a value of 0,
5136 * 2, 4 or 6. What could it be?).
5139 case SMB_FILE_MODE_INFORMATION
:
5141 status
= smb_file_mode_information(conn
,
5147 /* [MS-SMB2] 3.3.5.21.1 states we MUST fail with STATUS_NOT_SUPPORTED. */
5148 case SMB_FILE_VALID_DATA_LENGTH_INFORMATION
:
5149 case SMB_FILE_SHORT_NAME_INFORMATION
:
5150 return NT_STATUS_NOT_SUPPORTED
;
5152 case SMB_FILE_RENAME_INFORMATION
:
5154 status
= smb_file_rename_information(conn
, req
,
5160 case SMB2_FILE_RENAME_INFORMATION_INTERNAL
:
5162 /* SMB2 rename information. */
5163 status
= smb2_file_rename_information(conn
, req
,
5169 case SMB_FILE_LINK_INFORMATION
:
5171 if (conn
->sconn
->using_smb2
) {
5172 status
= smb2_file_link_information(conn
,
5179 status
= smb_file_link_information(conn
,
5190 return NT_STATUS_INVALID_LEVEL
;
5193 if (!NT_STATUS_IS_OK(status
)) {
5197 *ret_data_size
= data_return_size
;
5198 return NT_STATUS_OK
;
5201 static uint32_t generate_volume_serial_number(
5202 const struct loadparm_substitution
*lp_sub
,
5205 int serial
= lp_volume_serial_number(snum
);
5206 return serial
!= -1 ? serial
:
5207 str_checksum(lp_servicename(talloc_tos(), lp_sub
, snum
)) ^
5208 (str_checksum(get_local_machine_name())<<16);