2 Unix SMB/CIFS implementation.
3 SMB transaction2 handling
4 Copyright (C) Jeremy Allison 1994-2007
5 Copyright (C) Stefan (metze) Metzmacher 2003
6 Copyright (C) Volker Lendecke 2005-2007
7 Copyright (C) Steve French 2005
8 Copyright (C) James Peach 2006-2007
10 Extensively modified by Andrew Tridgell, 1995
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 3 of the License, or
15 (at your option) any later version.
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with this program. If not, see <http://www.gnu.org/licenses/>.
28 #include "system/filesys.h"
29 #include "lib/util/time_basic.h"
31 #include "smbd/smbd.h"
32 #include "smbd/globals.h"
33 #include "../libcli/auth/libcli_auth.h"
34 #include "../librpc/gen_ndr/xattr.h"
35 #include "../librpc/gen_ndr/ndr_security.h"
36 #include "../librpc/gen_ndr/ndr_smb3posix.h"
37 #include "libcli/security/security.h"
40 #include "smbprofile.h"
41 #include "rpc_server/srv_pipe_hnd.h"
43 #include "lib/util_ea.h"
44 #include "lib/readdir_attr.h"
46 #include "libcli/smb/smb2_posix.h"
47 #include "lib/util/string_wrappers.h"
48 #include "source3/lib/substitute.h"
49 #include "source3/lib/adouble.h"
50 #include "source3/smbd/dir.h"
52 #define DIR_ENTRY_SAFETY_MARGIN 4096
54 static uint32_t generate_volume_serial_number(
55 const struct loadparm_substitution
*lp_sub
,
58 /****************************************************************************
59 Check if an open file handle is a symlink.
60 ****************************************************************************/
62 NTSTATUS
refuse_symlink_fsp(const files_struct
*fsp
)
65 if (!VALID_STAT(fsp
->fsp_name
->st
)) {
66 return NT_STATUS_ACCESS_DENIED
;
68 if (S_ISLNK(fsp
->fsp_name
->st
.st_ex_mode
)) {
69 return NT_STATUS_ACCESS_DENIED
;
71 if (fsp_get_pathref_fd(fsp
) == -1) {
72 return NT_STATUS_ACCESS_DENIED
;
78 * Check that one or more of the rights in access mask are
79 * allowed. Iow, access_requested can contain more then one right and
80 * it is sufficient having only one of those granted to pass.
82 NTSTATUS
check_any_access_fsp(struct files_struct
*fsp
,
83 uint32_t access_requested
)
85 uint32_t access_granted
= 0;
88 if (fsp
->fsp_flags
.is_fsa
) {
89 access_granted
= fsp
->access_mask
;
94 if (!(mask
& access_requested
)) {
99 status
= smbd_check_access_rights_fsp(
104 if (NT_STATUS_IS_OK(status
)) {
109 access_granted
= mask
;
111 if ((access_granted
& access_requested
) == 0) {
112 return NT_STATUS_ACCESS_DENIED
;
117 /********************************************************************
118 Roundup a value to the nearest allocation roundup size boundary.
119 Only do this for Windows clients.
120 ********************************************************************/
122 uint64_t smb_roundup(connection_struct
*conn
, uint64_t val
)
124 uint64_t rval
= lp_allocation_roundup_size(SNUM(conn
));
126 /* Only roundup for Windows clients. */
127 enum remote_arch_types ra_type
= get_remote_arch();
128 if (rval
&& (ra_type
!= RA_SAMBA
) && (ra_type
!= RA_CIFSFS
)) {
129 val
= SMB_ROUNDUP(val
,rval
);
134 /****************************************************************************
135 Utility functions for dealing with extended attributes.
136 ****************************************************************************/
138 /****************************************************************************
139 Refuse to allow clients to overwrite our private xattrs.
140 ****************************************************************************/
142 bool samba_private_attr_name(const char *unix_ea_name
)
144 bool prohibited
= false;
146 prohibited
|= strequal(unix_ea_name
, SAMBA_POSIX_INHERITANCE_EA_NAME
);
147 prohibited
|= strequal(unix_ea_name
, SAMBA_XATTR_DOS_ATTRIB
);
148 prohibited
|= strequal(unix_ea_name
, SAMBA_XATTR_MARKER
);
149 prohibited
|= strequal(unix_ea_name
, XATTR_NTACL_NAME
);
150 prohibited
|= strequal(unix_ea_name
, AFPINFO_EA_NETATALK
);
156 if (strncasecmp_m(unix_ea_name
, SAMBA_XATTR_DOSSTREAM_PREFIX
,
157 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX
)) == 0) {
163 /****************************************************************************
164 Get one EA value. Fill in a struct ea_struct.
165 ****************************************************************************/
167 NTSTATUS
get_ea_value_fsp(TALLOC_CTX
*mem_ctx
,
170 struct ea_struct
*pea
)
172 /* Get the value of this xattr. Max size is 64k. */
173 size_t attr_size
= 256;
176 size_t max_xattr_size
= 0;
180 return NT_STATUS_INVALID_HANDLE
;
182 status
= refuse_symlink_fsp(fsp
);
183 if (!NT_STATUS_IS_OK(status
)) {
187 max_xattr_size
= lp_smbd_max_xattr_size(SNUM(fsp
->conn
));
191 val
= talloc_realloc(mem_ctx
, val
, char, attr_size
);
193 return NT_STATUS_NO_MEMORY
;
196 sizeret
= SMB_VFS_FGETXATTR(fsp
, ea_name
, val
, attr_size
);
197 if (sizeret
== -1 && errno
== ERANGE
&& attr_size
< max_xattr_size
) {
198 attr_size
= max_xattr_size
;
203 return map_nt_error_from_unix(errno
);
206 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name
, (unsigned int)sizeret
));
207 dump_data(10, (uint8_t *)val
, sizeret
);
210 if (strnequal(ea_name
, "user.", 5)) {
211 pea
->name
= talloc_strdup(mem_ctx
, &ea_name
[5]);
213 pea
->name
= talloc_strdup(mem_ctx
, ea_name
);
215 if (pea
->name
== NULL
) {
217 return NT_STATUS_NO_MEMORY
;
219 pea
->value
.data
= (unsigned char *)val
;
220 pea
->value
.length
= (size_t)sizeret
;
224 NTSTATUS
get_ea_names_from_fsp(TALLOC_CTX
*mem_ctx
,
230 /* Get a list of all xattrs. Max namesize is 64k. */
231 size_t ea_namelist_size
= 1024;
232 char *ea_namelist
= smallbuf
;
233 char *to_free
= NULL
;
238 ssize_t sizeret
= -1;
246 if ((fsp
== NULL
) || !NT_STATUS_IS_OK(refuse_symlink_fsp(fsp
))) {
248 * Callers may pass fsp == NULL when passing smb_fname->fsp of a
249 * symlink. This is ok, handle it here, by just return no EA's
255 sizeret
= SMB_VFS_FLISTXATTR(fsp
, ea_namelist
,
258 if ((sizeret
== -1) && (errno
== ERANGE
)) {
259 ea_namelist_size
= 65536;
260 ea_namelist
= talloc_array(mem_ctx
, char, ea_namelist_size
);
261 if (ea_namelist
== NULL
) {
262 return NT_STATUS_NO_MEMORY
;
264 to_free
= ea_namelist
;
266 sizeret
= SMB_VFS_FLISTXATTR(fsp
, ea_namelist
,
271 status
= map_nt_error_from_unix(errno
);
272 TALLOC_FREE(to_free
);
276 DBG_DEBUG("ea_namelist size = %zd\n", sizeret
);
279 TALLOC_FREE(to_free
);
284 * Ensure the result is 0-terminated
287 if (ea_namelist
[sizeret
-1] != '\0') {
288 TALLOC_FREE(to_free
);
289 return NT_STATUS_INTERNAL_ERROR
;
297 for (p
= ea_namelist
; p
- ea_namelist
< sizeret
; p
+= strlen(p
)+1) {
301 *pnum_names
= num_names
;
303 if (pnames
== NULL
) {
304 TALLOC_FREE(to_free
);
308 names
= talloc_array(mem_ctx
, char *, num_names
);
310 DEBUG(0, ("talloc failed\n"));
311 TALLOC_FREE(to_free
);
312 return NT_STATUS_NO_MEMORY
;
315 if (ea_namelist
== smallbuf
) {
316 ea_namelist
= talloc_memdup(names
, smallbuf
, sizeret
);
317 if (ea_namelist
== NULL
) {
319 return NT_STATUS_NO_MEMORY
;
322 talloc_steal(names
, ea_namelist
);
324 ea_namelist
= talloc_realloc(names
, ea_namelist
, char,
326 if (ea_namelist
== NULL
) {
328 return NT_STATUS_NO_MEMORY
;
334 for (p
= ea_namelist
; p
- ea_namelist
< sizeret
; p
+= strlen(p
)+1) {
335 names
[num_names
++] = p
;
343 /****************************************************************************
344 Return a linked list of the total EA's. Plus the total size
345 ****************************************************************************/
347 static NTSTATUS
get_ea_list_from_fsp(TALLOC_CTX
*mem_ctx
,
349 size_t *pea_total_len
,
350 struct ea_list
**ea_list
)
352 /* Get a list of all xattrs. Max namesize is 64k. */
355 struct ea_list
*ea_list_head
= NULL
;
356 bool posix_pathnames
= false;
367 if (!lp_ea_support(SNUM(fsp
->conn
))) {
371 if (fsp_is_alternate_stream(fsp
)) {
372 return NT_STATUS_INVALID_PARAMETER
;
375 posix_pathnames
= (fsp
->fsp_name
->flags
& SMB_FILENAME_POSIX_PATH
);
377 status
= get_ea_names_from_fsp(talloc_tos(),
382 if (!NT_STATUS_IS_OK(status
)) {
386 if (num_names
== 0) {
390 for (i
=0; i
<num_names
; i
++) {
391 struct ea_list
*listp
;
395 * POSIX EA names are divided into several namespaces by
396 * means of string prefixes. Usually, the system controls
397 * semantics for each namespace, but the 'user' namespace is
398 * available for arbitrary use, which comes closest to
399 * Windows EA semantics. Hence, we map POSIX EAs from the
400 * 'user' namespace to Windows EAs, and just ignore all the
401 * other namespaces. Also, a few specific names in the 'user'
402 * namespace are used by Samba internally. Filter them out as
403 * well, and only present the EAs that are available for
406 if (!strnequal(names
[i
], "user.", 5)
407 || samba_private_attr_name(names
[i
]))
411 * Filter out any underlying POSIX EA names
412 * that a Windows client can't handle.
414 if (!posix_pathnames
&&
415 is_invalid_windows_ea_name(names
[i
])) {
419 listp
= talloc(mem_ctx
, struct ea_list
);
421 return NT_STATUS_NO_MEMORY
;
424 status
= get_ea_value_fsp(listp
,
429 if (!NT_STATUS_IS_OK(status
)) {
434 if (listp
->ea
.value
.length
== 0) {
436 * We can never return a zero length EA.
437 * Windows reports the EA's as corrupted.
441 } else if (listp
->ea
.value
.length
> 65536) {
443 * SMB clients may report error with file
444 * if large EA is presented to them.
446 DBG_ERR("EA [%s] on file [%s] exceeds "
447 "maximum permitted EA size of 64KiB: %zu\n.",
448 listp
->ea
.name
, fsp_str_dbg(fsp
),
449 listp
->ea
.value
.length
);
454 push_ascii_fstring(dos_ea_name
, listp
->ea
.name
);
457 4 + strlen(dos_ea_name
) + 1 + listp
->ea
.value
.length
;
459 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
460 "= %u\n", (unsigned int)*pea_total_len
, dos_ea_name
,
461 (unsigned int)listp
->ea
.value
.length
));
463 DLIST_ADD_END(ea_list_head
, listp
);
467 /* Add on 4 for total length. */
468 if (*pea_total_len
) {
472 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
473 (unsigned int)*pea_total_len
));
475 *ea_list
= ea_list_head
;
479 /****************************************************************************
480 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
482 ****************************************************************************/
484 static unsigned int fill_ea_buffer(TALLOC_CTX
*mem_ctx
, char *pdata
, unsigned int total_data_size
,
485 connection_struct
*conn
, struct ea_list
*ea_list
)
487 unsigned int ret_data_size
= 4;
490 SMB_ASSERT(total_data_size
>= 4);
492 if (!lp_ea_support(SNUM(conn
))) {
497 for (p
= pdata
+ 4; ea_list
; ea_list
= ea_list
->next
) {
500 push_ascii_fstring(dos_ea_name
, ea_list
->ea
.name
);
501 dos_namelen
= strlen(dos_ea_name
);
502 if (dos_namelen
> 255 || dos_namelen
== 0) {
505 if (ea_list
->ea
.value
.length
> 65535) {
508 if (4 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
> total_data_size
) {
512 /* We know we have room. */
513 SCVAL(p
,0,ea_list
->ea
.flags
);
514 SCVAL(p
,1,dos_namelen
);
515 SSVAL(p
,2,ea_list
->ea
.value
.length
);
516 strlcpy(p
+4, dos_ea_name
, dos_namelen
+1);
517 if (ea_list
->ea
.value
.length
> 0) {
518 memcpy(p
+ 4 + dos_namelen
+ 1,
519 ea_list
->ea
.value
.data
,
520 ea_list
->ea
.value
.length
);
523 total_data_size
-= 4 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
;
524 p
+= 4 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
;
527 ret_data_size
= PTR_DIFF(p
, pdata
);
528 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size
));
529 SIVAL(pdata
,0,ret_data_size
);
530 return ret_data_size
;
533 static NTSTATUS
fill_ea_chained_buffer(TALLOC_CTX
*mem_ctx
,
535 unsigned int total_data_size
,
536 unsigned int *ret_data_size
,
537 connection_struct
*conn
,
538 struct ea_list
*ea_list
)
540 uint8_t *p
= (uint8_t *)pdata
;
541 uint8_t *last_start
= NULL
;
542 bool do_store_data
= (pdata
!= NULL
);
546 if (!lp_ea_support(SNUM(conn
))) {
547 return NT_STATUS_NO_EAS_ON_FILE
;
550 for (; ea_list
; ea_list
= ea_list
->next
) {
556 if (last_start
!= NULL
&& do_store_data
) {
557 SIVAL(last_start
, 0, PTR_DIFF(p
, last_start
));
561 push_ascii_fstring(dos_ea_name
, ea_list
->ea
.name
);
562 dos_namelen
= strlen(dos_ea_name
);
563 if (dos_namelen
> 255 || dos_namelen
== 0) {
564 return NT_STATUS_INTERNAL_ERROR
;
566 if (ea_list
->ea
.value
.length
> 65535) {
567 return NT_STATUS_INTERNAL_ERROR
;
570 this_size
= 0x08 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
;
573 pad
= (4 - (this_size
% 4)) % 4;
578 if (this_size
> total_data_size
) {
579 return NT_STATUS_INFO_LENGTH_MISMATCH
;
582 /* We know we have room. */
583 SIVAL(p
, 0x00, 0); /* next offset */
584 SCVAL(p
, 0x04, ea_list
->ea
.flags
);
585 SCVAL(p
, 0x05, dos_namelen
);
586 SSVAL(p
, 0x06, ea_list
->ea
.value
.length
);
587 strlcpy((char *)(p
+0x08), dos_ea_name
, dos_namelen
+1);
588 memcpy(p
+ 0x08 + dos_namelen
+ 1, ea_list
->ea
.value
.data
, ea_list
->ea
.value
.length
);
590 memset(p
+ 0x08 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
,
594 total_data_size
-= this_size
;
600 *ret_data_size
= PTR_DIFF(p
, pdata
);
601 DEBUG(10,("fill_ea_chained_buffer: data_size = %u\n", *ret_data_size
));
605 unsigned int estimate_ea_size(files_struct
*fsp
)
607 size_t total_ea_len
= 0;
609 struct ea_list
*ea_list
= NULL
;
617 if (!lp_ea_support(SNUM(fsp
->conn
))) {
621 mem_ctx
= talloc_stackframe();
623 /* If this is a stream fsp, then we need to instead find the
624 * estimated ea len from the main file, not the stream
625 * (streams cannot have EAs), but the estimate isn't just 0 in
627 fsp
= metadata_fsp(fsp
);
628 (void)get_ea_list_from_fsp(mem_ctx
,
633 if(fsp
->conn
->sconn
->using_smb2
) {
634 unsigned int ret_data_size
;
636 * We're going to be using fill_ea_chained_buffer() to
637 * marshall EA's - this size is significantly larger
638 * than the SMB1 buffer. Re-calculate the size without
641 status
= fill_ea_chained_buffer(mem_ctx
,
647 if (!NT_STATUS_IS_OK(status
)) {
650 total_ea_len
= ret_data_size
;
652 TALLOC_FREE(mem_ctx
);
656 /****************************************************************************
657 Ensure the EA name is case insensitive by matching any existing EA name.
658 ****************************************************************************/
660 static void canonicalize_ea_name(files_struct
*fsp
,
661 fstring unix_ea_name
)
664 TALLOC_CTX
*mem_ctx
= talloc_tos();
665 struct ea_list
*ea_list
;
666 NTSTATUS status
= get_ea_list_from_fsp(mem_ctx
,
670 if (!NT_STATUS_IS_OK(status
)) {
674 for (; ea_list
; ea_list
= ea_list
->next
) {
675 if (strequal(&unix_ea_name
[5], ea_list
->ea
.name
)) {
676 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
677 &unix_ea_name
[5], ea_list
->ea
.name
));
678 strlcpy(&unix_ea_name
[5], ea_list
->ea
.name
, sizeof(fstring
)-5);
684 /****************************************************************************
685 Set or delete an extended attribute.
686 ****************************************************************************/
688 NTSTATUS
set_ea(connection_struct
*conn
, files_struct
*fsp
,
689 struct ea_list
*ea_list
)
692 bool posix_pathnames
= false;
694 if (!lp_ea_support(SNUM(conn
))) {
695 return NT_STATUS_EAS_NOT_SUPPORTED
;
699 return NT_STATUS_INVALID_HANDLE
;
702 posix_pathnames
= (fsp
->fsp_name
->flags
& SMB_FILENAME_POSIX_PATH
);
704 status
= refuse_symlink_fsp(fsp
);
705 if (!NT_STATUS_IS_OK(status
)) {
709 status
= check_any_access_fsp(fsp
, FILE_WRITE_EA
);
710 if (!NT_STATUS_IS_OK(status
)) {
714 /* Setting EAs on streams isn't supported. */
715 if (fsp_is_alternate_stream(fsp
)) {
716 return NT_STATUS_INVALID_PARAMETER
;
720 * Filter out invalid Windows EA names - before
721 * we set *any* of them.
724 if (!posix_pathnames
&& ea_list_has_invalid_name(ea_list
)) {
725 return STATUS_INVALID_EA_NAME
;
728 for (;ea_list
; ea_list
= ea_list
->next
) {
730 fstring unix_ea_name
;
733 * Complementing the forward mapping from POSIX EAs to
734 * Windows EAs in get_ea_list_from_fsp(), here we map in the
735 * opposite direction from Windows EAs to the 'user' namespace
736 * of POSIX EAs. Hence, all POSIX EA names the we set here must
737 * start with a 'user.' prefix.
739 fstrcpy(unix_ea_name
, "user.");
740 fstrcat(unix_ea_name
, ea_list
->ea
.name
);
742 canonicalize_ea_name(fsp
, unix_ea_name
);
744 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name
, (unsigned int)ea_list
->ea
.value
.length
));
746 if (samba_private_attr_name(unix_ea_name
)) {
747 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name
));
748 return NT_STATUS_ACCESS_DENIED
;
751 if (ea_list
->ea
.value
.length
== 0) {
752 /* Remove the attribute. */
753 DBG_DEBUG("deleting ea name %s on "
754 "file %s by file descriptor.\n",
755 unix_ea_name
, fsp_str_dbg(fsp
));
756 ret
= SMB_VFS_FREMOVEXATTR(fsp
, unix_ea_name
);
758 /* Removing a non existent attribute always succeeds. */
759 if (ret
== -1 && errno
== ENOATTR
) {
760 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
766 DEBUG(10,("set_ea: setting ea name %s on file "
767 "%s by file descriptor.\n",
768 unix_ea_name
, fsp_str_dbg(fsp
)));
769 ret
= SMB_VFS_FSETXATTR(fsp
, unix_ea_name
,
770 ea_list
->ea
.value
.data
, ea_list
->ea
.value
.length
, 0);
775 if (errno
== ENOTSUP
) {
776 return NT_STATUS_EAS_NOT_SUPPORTED
;
779 return map_nt_error_from_unix(errno
);
786 /****************************************************************************
787 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
788 ****************************************************************************/
790 struct ea_list
*read_ea_list(TALLOC_CTX
*ctx
, const char *pdata
, size_t data_size
)
792 struct ea_list
*ea_list_head
= NULL
;
794 size_t bytes_used
= 0;
796 while (offset
< data_size
) {
797 struct ea_list
*eal
= read_ea_list_entry(ctx
, pdata
+ offset
, data_size
- offset
, &bytes_used
);
803 DLIST_ADD_END(ea_list_head
, eal
);
804 offset
+= bytes_used
;
810 /****************************************************************************
811 Count the total EA size needed.
812 ****************************************************************************/
814 static size_t ea_list_size(struct ea_list
*ealist
)
817 struct ea_list
*listp
;
820 for (listp
= ealist
; listp
; listp
= listp
->next
) {
821 push_ascii_fstring(dos_ea_name
, listp
->ea
.name
);
822 ret
+= 4 + strlen(dos_ea_name
) + 1 + listp
->ea
.value
.length
;
824 /* Add on 4 for total length. */
832 /****************************************************************************
833 Return a union of EA's from a file list and a list of names.
834 The TALLOC context for the two lists *MUST* be identical as we steal
835 memory from one list to add to another. JRA.
836 ****************************************************************************/
838 static struct ea_list
*ea_list_union(struct ea_list
*name_list
, struct ea_list
*file_list
, size_t *total_ea_len
)
840 struct ea_list
*nlistp
, *flistp
;
842 for (nlistp
= name_list
; nlistp
; nlistp
= nlistp
->next
) {
843 for (flistp
= file_list
; flistp
; flistp
= flistp
->next
) {
844 if (strequal(nlistp
->ea
.name
, flistp
->ea
.name
)) {
850 /* Copy the data from this entry. */
851 nlistp
->ea
.flags
= flistp
->ea
.flags
;
852 nlistp
->ea
.value
= flistp
->ea
.value
;
855 nlistp
->ea
.flags
= 0;
856 ZERO_STRUCT(nlistp
->ea
.value
);
860 *total_ea_len
= ea_list_size(name_list
);
864 /****************************************************************************
865 Return the filetype for UNIX extensions.
866 ****************************************************************************/
868 static uint32_t unix_filetype(mode_t mode
)
871 return UNIX_TYPE_FILE
;
872 else if(S_ISDIR(mode
))
873 return UNIX_TYPE_DIR
;
875 else if(S_ISLNK(mode
))
876 return UNIX_TYPE_SYMLINK
;
879 else if(S_ISCHR(mode
))
880 return UNIX_TYPE_CHARDEV
;
883 else if(S_ISBLK(mode
))
884 return UNIX_TYPE_BLKDEV
;
887 else if(S_ISFIFO(mode
))
888 return UNIX_TYPE_FIFO
;
891 else if(S_ISSOCK(mode
))
892 return UNIX_TYPE_SOCKET
;
895 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode
));
896 return UNIX_TYPE_UNKNOWN
;
899 /****************************************************************************
900 Map wire perms onto standard UNIX permissions. Obey share restrictions.
901 ****************************************************************************/
903 NTSTATUS
unix_perms_from_wire(connection_struct
*conn
,
904 const SMB_STRUCT_STAT
*psbuf
,
906 enum perm_type ptype
,
911 if (perms
== SMB_MODE_NO_CHANGE
) {
912 if (!VALID_STAT(*psbuf
)) {
913 return NT_STATUS_INVALID_PARAMETER
;
915 *ret_perms
= psbuf
->st_ex_mode
;
920 ret
= wire_perms_to_unix(perms
);
922 if (ptype
== PERM_NEW_FILE
) {
924 * "create mask"/"force create mode" are
925 * only applied to new files, not existing ones.
927 ret
&= lp_create_mask(SNUM(conn
));
928 /* Add in force bits */
929 ret
|= lp_force_create_mode(SNUM(conn
));
930 } else if (ptype
== PERM_NEW_DIR
) {
932 * "directory mask"/"force directory mode" are
933 * only applied to new directories, not existing ones.
935 ret
&= lp_directory_mask(SNUM(conn
));
936 /* Add in force bits */
937 ret
|= lp_force_directory_mode(SNUM(conn
));
944 /****************************************************************************
945 Get a level dependent lanman2 dir entry.
946 ****************************************************************************/
948 struct smbd_dirptr_lanman2_state
{
949 connection_struct
*conn
;
951 bool check_mangled_names
;
955 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX
*ctx
,
961 struct smbd_dirptr_lanman2_state
*state
=
962 (struct smbd_dirptr_lanman2_state
*)private_data
;
964 char mangled_name
[13]; /* mangled 8.3 name. */
968 /* Mangle fname if it's an illegal name. */
969 if (mangle_must_mangle(dname
, state
->conn
->params
)) {
971 * Slow path - ensure we can push the original name as UCS2. If
972 * not, then just don't return this name.
976 size_t len
= (strlen(dname
) + 2) * 4; /* Allow enough space. */
977 uint8_t *tmp
= talloc_array(talloc_tos(),
981 status
= srvstr_push(NULL
,
982 FLAGS2_UNICODE_STRINGS
,
991 if (!NT_STATUS_IS_OK(status
)) {
995 ok
= name_to_8_3(dname
, mangled_name
,
996 true, state
->conn
->params
);
1000 fname
= mangled_name
;
1005 got_match
= mask_match(fname
, mask
,
1006 state
->case_sensitive
);
1008 if(!got_match
&& state
->check_mangled_names
&&
1009 !mangle_is_8_3(fname
, false, state
->conn
->params
)) {
1011 * It turns out that NT matches wildcards against
1012 * both long *and* short names. This may explain some
1013 * of the wildcard weirdness from old DOS clients
1014 * that some people have been seeing.... JRA.
1016 /* Force the mangling into 8.3. */
1017 ok
= name_to_8_3(fname
, mangled_name
,
1018 false, state
->conn
->params
);
1023 got_match
= mask_match(mangled_name
, mask
,
1024 state
->case_sensitive
);
1031 *_fname
= talloc_strdup(ctx
, fname
);
1032 if (*_fname
== NULL
) {
1039 static uint32_t get_dirent_ea_size(uint32_t mode
, files_struct
*fsp
)
1041 if (!(mode
& FILE_ATTRIBUTE_REPARSE_POINT
)) {
1042 unsigned ea_size
= estimate_ea_size(fsp
);
1045 return IO_REPARSE_TAG_DFS
;
1048 static NTSTATUS
smbd_marshall_dir_entry(TALLOC_CTX
*ctx
,
1049 connection_struct
*conn
,
1051 uint32_t info_level
,
1052 struct ea_list
*name_list
,
1053 bool check_mangled_names
,
1054 bool requires_resume_key
,
1057 const struct smb_filename
*smb_fname
,
1058 int space_remaining
,
1064 uint64_t *last_entry_off
)
1066 char *p
, *q
, *pdata
= *ppdata
;
1068 uint64_t file_size
= 0;
1069 uint64_t allocation_size
= 0;
1070 uint64_t file_id
= 0;
1072 struct timespec mdate_ts
= {0};
1073 struct timespec adate_ts
= {0};
1074 struct timespec cdate_ts
= {0};
1075 struct timespec create_date_ts
= {0};
1077 char *last_entry_ptr
;
1082 struct readdir_attr_data
*readdir_attr_data
= NULL
;
1085 if (!(mode
& FILE_ATTRIBUTE_DIRECTORY
)) {
1086 file_size
= get_file_size_stat(&smb_fname
->st
);
1088 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
, NULL
, &smb_fname
->st
);
1091 * Skip SMB_VFS_FREADDIR_ATTR if the directory entry is a symlink or
1094 if (smb_fname
->fsp
!= NULL
&&
1095 !(mode
& FILE_ATTRIBUTE_REPARSE_POINT
)) {
1096 status
= SMB_VFS_FREADDIR_ATTR(smb_fname
->fsp
,
1098 &readdir_attr_data
);
1099 if (!NT_STATUS_IS_OK(status
)) {
1100 if (!NT_STATUS_EQUAL(NT_STATUS_NOT_SUPPORTED
,
1107 file_id
= SMB_VFS_FS_FILE_ID(conn
, &smb_fname
->st
);
1109 mdate_ts
= smb_fname
->st
.st_ex_mtime
;
1110 adate_ts
= smb_fname
->st
.st_ex_atime
;
1111 create_date_ts
= get_create_timespec(conn
, NULL
, smb_fname
);
1112 cdate_ts
= get_change_timespec(conn
, NULL
, smb_fname
);
1114 if (lp_dos_filetime_resolution(SNUM(conn
))) {
1115 dos_filetime_timespec(&create_date_ts
);
1116 dos_filetime_timespec(&mdate_ts
);
1117 dos_filetime_timespec(&adate_ts
);
1118 dos_filetime_timespec(&cdate_ts
);
1121 /* align the record */
1122 SMB_ASSERT(align
>= 1);
1124 off
= (int)PTR_DIFF(pdata
, base_data
);
1125 pad
= (off
+ (align
-1)) & ~(align
-1);
1128 if (pad
&& pad
> space_remaining
) {
1129 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1130 "for padding (wanted %u, had %d)\n",
1133 return STATUS_MORE_ENTRIES
; /* Not finished - just out of space */
1137 /* initialize padding to 0 */
1139 memset(pdata
, 0, pad
);
1141 space_remaining
-= pad
;
1143 DEBUG(10,("smbd_marshall_dir_entry: space_remaining = %d\n",
1153 switch (info_level
) {
1154 case SMB_FIND_INFO_STANDARD
:
1155 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1156 if(requires_resume_key
) {
1160 srv_put_dos_date2_ts(p
, 0, create_date_ts
);
1161 srv_put_dos_date2_ts(p
, 4, adate_ts
);
1162 srv_put_dos_date2_ts(p
, 8, mdate_ts
);
1163 SIVAL(p
,12,(uint32_t)file_size
);
1164 SIVAL(p
,16,(uint32_t)allocation_size
);
1168 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1169 p
+= ucs2_align(base_data
, p
, 0);
1171 status
= srvstr_push(base_data
, flags2
, p
,
1172 fname
, PTR_DIFF(end_data
, p
),
1173 STR_TERMINATE
, &len
);
1174 if (!NT_STATUS_IS_OK(status
)) {
1177 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1179 SCVAL(nameptr
, -1, len
- 2);
1181 SCVAL(nameptr
, -1, 0);
1185 SCVAL(nameptr
, -1, len
- 1);
1187 SCVAL(nameptr
, -1, 0);
1193 case SMB_FIND_EA_SIZE
:
1194 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
1195 if (requires_resume_key
) {
1199 srv_put_dos_date2_ts(p
, 0, create_date_ts
);
1200 srv_put_dos_date2_ts(p
, 4, adate_ts
);
1201 srv_put_dos_date2_ts(p
, 8, mdate_ts
);
1202 SIVAL(p
,12,(uint32_t)file_size
);
1203 SIVAL(p
,16,(uint32_t)allocation_size
);
1206 ea_size
= estimate_ea_size(smb_fname
->fsp
);
1207 SIVAL(p
,22,ea_size
); /* Extended attributes */
1211 status
= srvstr_push(base_data
, flags2
,
1212 p
, fname
, PTR_DIFF(end_data
, p
),
1213 STR_TERMINATE
| STR_NOALIGN
, &len
);
1214 if (!NT_STATUS_IS_OK(status
)) {
1217 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1230 SCVAL(nameptr
,0,len
);
1232 SCVAL(p
,0,0); p
+= 1; /* Extra zero byte ? - why.. */
1235 case SMB_FIND_EA_LIST
:
1237 struct ea_list
*file_list
= NULL
;
1240 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
1242 return NT_STATUS_INVALID_PARAMETER
;
1244 if (requires_resume_key
) {
1248 srv_put_dos_date2_ts(p
, 0, create_date_ts
);
1249 srv_put_dos_date2_ts(p
, 4, adate_ts
);
1250 srv_put_dos_date2_ts(p
, 8, mdate_ts
);
1251 SIVAL(p
,12,(uint32_t)file_size
);
1252 SIVAL(p
,16,(uint32_t)allocation_size
);
1254 p
+= 22; /* p now points to the EA area. */
1256 status
= get_ea_list_from_fsp(ctx
,
1258 &ea_len
, &file_list
);
1259 if (!NT_STATUS_IS_OK(status
)) {
1262 name_list
= ea_list_union(name_list
, file_list
, &ea_len
);
1264 /* We need to determine if this entry will fit in the space available. */
1265 /* Max string size is 255 bytes. */
1266 if (PTR_DIFF(p
+ 255 + ea_len
,pdata
) > space_remaining
) {
1267 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1268 "(wanted %u, had %d)\n",
1269 (unsigned int)PTR_DIFF(p
+ 255 + ea_len
,pdata
),
1271 return STATUS_MORE_ENTRIES
; /* Not finished - just out of space */
1274 /* Push the ea_data followed by the name. */
1275 p
+= fill_ea_buffer(ctx
, p
, space_remaining
, conn
, name_list
);
1277 status
= srvstr_push(base_data
, flags2
,
1278 p
+ 1, fname
, PTR_DIFF(end_data
, p
+1),
1279 STR_TERMINATE
| STR_NOALIGN
, &len
);
1280 if (!NT_STATUS_IS_OK(status
)) {
1283 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1296 SCVAL(nameptr
,0,len
);
1298 SCVAL(p
,0,0); p
+= 1; /* Extra zero byte ? - why.. */
1302 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
1303 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1304 was_8_3
= mangle_is_8_3(fname
, True
, conn
->params
);
1306 SIVAL(p
,0,reskey
); p
+= 4;
1307 put_long_date_full_timespec(conn
->ts_res
,p
,&create_date_ts
); p
+= 8;
1308 put_long_date_full_timespec(conn
->ts_res
,p
,&adate_ts
); p
+= 8;
1309 put_long_date_full_timespec(conn
->ts_res
,p
,&mdate_ts
); p
+= 8;
1310 put_long_date_full_timespec(conn
->ts_res
,p
,&cdate_ts
); p
+= 8;
1311 SOFF_T(p
,0,file_size
); p
+= 8;
1312 SOFF_T(p
,0,allocation_size
); p
+= 8;
1313 SIVAL(p
,0,mode
); p
+= 4;
1314 q
= p
; p
+= 4; /* q is placeholder for name length. */
1315 ea_size
= get_dirent_ea_size(mode
, smb_fname
->fsp
);
1316 SIVAL(p
, 0, ea_size
);
1318 /* Clear the short name buffer. This is
1319 * IMPORTANT as not doing so will trigger
1320 * a Win2k client bug. JRA.
1322 if (!was_8_3
&& check_mangled_names
) {
1323 char mangled_name
[13]; /* mangled 8.3 name. */
1324 if (!name_to_8_3(fname
,mangled_name
,True
,
1326 /* Error - mangle failed ! */
1327 memset(mangled_name
,'\0',12);
1329 mangled_name
[12] = 0;
1330 status
= srvstr_push(base_data
, flags2
,
1331 p
+2, mangled_name
, 24,
1332 STR_UPPER
|STR_UNICODE
, &len
);
1333 if (!NT_STATUS_IS_OK(status
)) {
1337 memset(p
+ 2 + len
,'\0',24 - len
);
1344 status
= srvstr_push(base_data
, flags2
, p
,
1345 fname
, PTR_DIFF(end_data
, p
),
1346 STR_TERMINATE_ASCII
, &len
);
1347 if (!NT_STATUS_IS_OK(status
)) {
1353 len
= PTR_DIFF(p
, pdata
);
1354 pad
= (len
+ (align
-1)) & ~(align
-1);
1356 * offset to the next entry, the caller
1357 * will overwrite it for the last entry
1358 * that's why we always include the padding
1362 * set padding to zero
1365 memset(p
, 0, pad
- len
);
1372 case SMB_FIND_FILE_DIRECTORY_INFO
:
1373 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1375 SIVAL(p
,0,reskey
); p
+= 4;
1376 put_long_date_full_timespec(conn
->ts_res
,p
,&create_date_ts
); p
+= 8;
1377 put_long_date_full_timespec(conn
->ts_res
,p
,&adate_ts
); p
+= 8;
1378 put_long_date_full_timespec(conn
->ts_res
,p
,&mdate_ts
); p
+= 8;
1379 put_long_date_full_timespec(conn
->ts_res
,p
,&cdate_ts
); p
+= 8;
1380 SOFF_T(p
,0,file_size
); p
+= 8;
1381 SOFF_T(p
,0,allocation_size
); p
+= 8;
1382 SIVAL(p
,0,mode
); p
+= 4;
1383 status
= srvstr_push(base_data
, flags2
,
1384 p
+ 4, fname
, PTR_DIFF(end_data
, p
+4),
1385 STR_TERMINATE_ASCII
, &len
);
1386 if (!NT_STATUS_IS_OK(status
)) {
1392 len
= PTR_DIFF(p
, pdata
);
1393 pad
= (len
+ (align
-1)) & ~(align
-1);
1395 * offset to the next entry, the caller
1396 * will overwrite it for the last entry
1397 * that's why we always include the padding
1401 * set padding to zero
1404 memset(p
, 0, pad
- len
);
1411 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
1412 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1414 SIVAL(p
,0,reskey
); p
+= 4;
1415 put_long_date_full_timespec(conn
->ts_res
,p
,&create_date_ts
); p
+= 8;
1416 put_long_date_full_timespec(conn
->ts_res
,p
,&adate_ts
); p
+= 8;
1417 put_long_date_full_timespec(conn
->ts_res
,p
,&mdate_ts
); p
+= 8;
1418 put_long_date_full_timespec(conn
->ts_res
,p
,&cdate_ts
); p
+= 8;
1419 SOFF_T(p
,0,file_size
); p
+= 8;
1420 SOFF_T(p
,0,allocation_size
); p
+= 8;
1421 SIVAL(p
,0,mode
); p
+= 4;
1422 q
= p
; p
+= 4; /* q is placeholder for name length. */
1423 ea_size
= get_dirent_ea_size(mode
, smb_fname
->fsp
);
1424 SIVAL(p
, 0, ea_size
);
1426 status
= srvstr_push(base_data
, flags2
, p
,
1427 fname
, PTR_DIFF(end_data
, p
),
1428 STR_TERMINATE_ASCII
, &len
);
1429 if (!NT_STATUS_IS_OK(status
)) {
1435 len
= PTR_DIFF(p
, pdata
);
1436 pad
= (len
+ (align
-1)) & ~(align
-1);
1438 * offset to the next entry, the caller
1439 * will overwrite it for the last entry
1440 * that's why we always include the padding
1444 * set padding to zero
1447 memset(p
, 0, pad
- len
);
1454 case SMB_FIND_FILE_NAMES_INFO
:
1455 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1457 SIVAL(p
,0,reskey
); p
+= 4;
1459 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1460 acl on a dir (tridge) */
1461 status
= srvstr_push(base_data
, flags2
, p
,
1462 fname
, PTR_DIFF(end_data
, p
),
1463 STR_TERMINATE_ASCII
, &len
);
1464 if (!NT_STATUS_IS_OK(status
)) {
1470 len
= PTR_DIFF(p
, pdata
);
1471 pad
= (len
+ (align
-1)) & ~(align
-1);
1473 * offset to the next entry, the caller
1474 * will overwrite it for the last entry
1475 * that's why we always include the padding
1479 * set padding to zero
1482 memset(p
, 0, pad
- len
);
1489 case SMB_FIND_ID_FULL_DIRECTORY_INFO
:
1490 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1492 SIVAL(p
,0,reskey
); p
+= 4;
1493 put_long_date_full_timespec(conn
->ts_res
,p
,&create_date_ts
); p
+= 8;
1494 put_long_date_full_timespec(conn
->ts_res
,p
,&adate_ts
); p
+= 8;
1495 put_long_date_full_timespec(conn
->ts_res
,p
,&mdate_ts
); p
+= 8;
1496 put_long_date_full_timespec(conn
->ts_res
,p
,&cdate_ts
); p
+= 8;
1497 SOFF_T(p
,0,file_size
); p
+= 8;
1498 SOFF_T(p
,0,allocation_size
); p
+= 8;
1499 SIVAL(p
,0,mode
); p
+= 4;
1500 q
= p
; p
+= 4; /* q is placeholder for name length. */
1501 ea_size
= get_dirent_ea_size(mode
, smb_fname
->fsp
);
1502 SIVAL(p
, 0, ea_size
);
1504 SIVAL(p
,0,0); p
+= 4; /* Unknown - reserved ? */
1505 SBVAL(p
,0,file_id
); p
+= 8;
1506 status
= srvstr_push(base_data
, flags2
, p
,
1507 fname
, PTR_DIFF(end_data
, p
),
1508 STR_TERMINATE_ASCII
, &len
);
1509 if (!NT_STATUS_IS_OK(status
)) {
1515 len
= PTR_DIFF(p
, pdata
);
1516 pad
= (len
+ (align
-1)) & ~(align
-1);
1518 * offset to the next entry, the caller
1519 * will overwrite it for the last entry
1520 * that's why we always include the padding
1524 * set padding to zero
1527 memset(p
, 0, pad
- len
);
1534 case SMB_FIND_ID_BOTH_DIRECTORY_INFO
:
1535 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1536 was_8_3
= mangle_is_8_3(fname
, True
, conn
->params
);
1538 SIVAL(p
,0,reskey
); p
+= 4;
1539 put_long_date_full_timespec(conn
->ts_res
,p
,&create_date_ts
); p
+= 8;
1540 put_long_date_full_timespec(conn
->ts_res
,p
,&adate_ts
); p
+= 8;
1541 put_long_date_full_timespec(conn
->ts_res
,p
,&mdate_ts
); p
+= 8;
1542 put_long_date_full_timespec(conn
->ts_res
,p
,&cdate_ts
); p
+= 8;
1543 SOFF_T(p
,0,file_size
); p
+= 8;
1544 SOFF_T(p
,0,allocation_size
); p
+= 8;
1545 SIVAL(p
,0,mode
); p
+= 4;
1546 q
= p
; p
+= 4; /* q is placeholder for name length */
1547 if (readdir_attr_data
&&
1548 readdir_attr_data
->type
== RDATTR_AAPL
) {
1550 * OS X specific SMB2 extension negotiated via
1551 * AAPL create context: return max_access in
1554 ea_size
= readdir_attr_data
->attr_data
.aapl
.max_access
;
1556 ea_size
= get_dirent_ea_size(mode
, smb_fname
->fsp
);
1558 SIVAL(p
,0,ea_size
); /* Extended attributes */
1561 if (readdir_attr_data
&&
1562 readdir_attr_data
->type
== RDATTR_AAPL
) {
1564 * OS X specific SMB2 extension negotiated via
1565 * AAPL create context: return resource fork
1566 * length and compressed FinderInfo in
1569 * According to documentation short_name_len
1570 * should be 0, but on the wire behaviour
1571 * shows its set to 24 by clients.
1575 /* Resourefork length */
1576 SBVAL(p
, 2, readdir_attr_data
->attr_data
.aapl
.rfork_size
);
1578 /* Compressed FinderInfo */
1579 memcpy(p
+ 10, &readdir_attr_data
->attr_data
.aapl
.finder_info
, 16);
1580 } else if (!was_8_3
&& check_mangled_names
) {
1581 char mangled_name
[13]; /* mangled 8.3 name. */
1582 if (!name_to_8_3(fname
,mangled_name
,True
,
1584 /* Error - mangle failed ! */
1585 memset(mangled_name
,'\0',12);
1587 mangled_name
[12] = 0;
1588 status
= srvstr_push(base_data
, flags2
,
1589 p
+2, mangled_name
, 24,
1590 STR_UPPER
|STR_UNICODE
, &len
);
1591 if (!NT_STATUS_IS_OK(status
)) {
1596 memset(p
+ 2 + len
,'\0',24 - len
);
1600 /* Clear the short name buffer. This is
1601 * IMPORTANT as not doing so will trigger
1602 * a Win2k client bug. JRA.
1609 if (readdir_attr_data
&&
1610 readdir_attr_data
->type
== RDATTR_AAPL
) {
1612 * OS X specific SMB2 extension negotiated via
1613 * AAPL create context: return UNIX mode in
1616 uint16_t aapl_mode
= (uint16_t)readdir_attr_data
->attr_data
.aapl
.unix_mode
;
1617 SSVAL(p
, 0, aapl_mode
);
1623 SBVAL(p
,0,file_id
); p
+= 8;
1624 status
= srvstr_push(base_data
, flags2
, p
,
1625 fname
, PTR_DIFF(end_data
, p
),
1626 STR_TERMINATE_ASCII
, &len
);
1627 if (!NT_STATUS_IS_OK(status
)) {
1633 len
= PTR_DIFF(p
, pdata
);
1634 pad
= (len
+ (align
-1)) & ~(align
-1);
1636 * offset to the next entry, the caller
1637 * will overwrite it for the last entry
1638 * that's why we always include the padding
1642 * set padding to zero
1645 memset(p
, 0, pad
- len
);
1652 /* CIFS UNIX Extension. */
1654 case SMB_FIND_FILE_UNIX
:
1655 case SMB_FIND_FILE_UNIX_INFO2
:
1657 SIVAL(p
,0,reskey
); p
+= 4; /* Used for continuing search. */
1659 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1661 if (info_level
== SMB_FIND_FILE_UNIX
) {
1662 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
1663 p
= store_file_unix_basic(conn
, p
,
1664 NULL
, &smb_fname
->st
);
1665 status
= srvstr_push(base_data
, flags2
, p
,
1666 fname
, PTR_DIFF(end_data
, p
),
1667 STR_TERMINATE
, &len
);
1668 if (!NT_STATUS_IS_OK(status
)) {
1672 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
1673 p
= store_file_unix_basic_info2(conn
, p
,
1674 NULL
, &smb_fname
->st
);
1677 status
= srvstr_push(base_data
, flags2
, p
, fname
,
1678 PTR_DIFF(end_data
, p
), 0, &len
);
1679 if (!NT_STATUS_IS_OK(status
)) {
1682 SIVAL(nameptr
, 0, len
);
1687 len
= PTR_DIFF(p
, pdata
);
1688 pad
= (len
+ (align
-1)) & ~(align
-1);
1690 * offset to the next entry, the caller
1691 * will overwrite it for the last entry
1692 * that's why we always include the padding
1696 * set padding to zero
1699 memset(p
, 0, pad
- len
);
1704 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1708 /* SMB2 UNIX Extension. */
1710 case SMB2_FILE_POSIX_INFORMATION
:
1712 struct smb3_file_posix_information info
= {};
1713 uint8_t buf
[sizeof(info
)];
1714 struct ndr_push ndr
= {
1716 .alloc_size
= sizeof(buf
),
1717 .fixed_buf_size
= true,
1719 enum ndr_err_code ndr_err
;
1722 SIVAL(p
,0,reskey
); p
+= 4;
1724 DBG_DEBUG("SMB2_FILE_POSIX_INFORMATION\n");
1726 if (!(conn
->sconn
->using_smb2
)) {
1727 return NT_STATUS_INVALID_LEVEL
;
1730 smb3_file_posix_information_init(
1731 conn
, &smb_fname
->st
, 0, mode
, &info
);
1733 ndr_err
= ndr_push_smb3_file_posix_information(
1734 &ndr
, NDR_SCALARS
|NDR_BUFFERS
, &info
);
1735 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
1736 return NT_STATUS_INSUFFICIENT_RESOURCES
;
1739 memcpy(p
, buf
, ndr
.offset
);
1744 status
= srvstr_push(base_data
, flags2
, p
, fname
,
1745 PTR_DIFF(end_data
, p
), 0, &len
);
1746 if (!NT_STATUS_IS_OK(status
)) {
1749 SIVAL(nameptr
, 0, len
);
1753 len
= PTR_DIFF(p
, pdata
);
1754 pad
= (len
+ (align
-1)) & ~(align
-1);
1756 * offset to the next entry, the caller
1757 * will overwrite it for the last entry
1758 * that's why we always include the padding
1765 return NT_STATUS_INVALID_LEVEL
;
1768 if (PTR_DIFF(p
,pdata
) > space_remaining
) {
1769 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1770 "(wanted %u, had %d)\n",
1771 (unsigned int)PTR_DIFF(p
,pdata
),
1773 return STATUS_MORE_ENTRIES
; /* Not finished - just out of space */
1776 /* Setup the last entry pointer, as an offset from base_data */
1777 *last_entry_off
= PTR_DIFF(last_entry_ptr
,base_data
);
1778 /* Advance the data pointer to the next slot */
1781 return NT_STATUS_OK
;
1784 NTSTATUS
smbd_dirptr_lanman2_entry(TALLOC_CTX
*ctx
,
1785 connection_struct
*conn
,
1786 struct dptr_struct
*dirptr
,
1788 const char *path_mask
,
1791 int requires_resume_key
,
1800 int space_remaining
,
1801 struct smb_filename
**_smb_fname
,
1802 int *_last_entry_off
,
1803 struct ea_list
*name_list
,
1804 struct file_id
*file_id
)
1807 const char *mask
= NULL
;
1810 struct smb_filename
*smb_fname
= NULL
;
1811 struct smbd_dirptr_lanman2_state state
;
1813 uint64_t last_entry_off
= 0;
1815 enum mangled_names_options mangled_names
;
1816 bool marshall_with_83_names
;
1818 mangled_names
= lp_mangled_names(conn
->params
);
1822 state
.info_level
= info_level
;
1823 if (mangled_names
!= MANGLED_NAMES_NO
) {
1824 state
.check_mangled_names
= true;
1826 state
.case_sensitive
= dptr_case_sensitive(dirptr
);
1828 p
= strrchr_m(path_mask
,'/');
1839 ok
= smbd_dirptr_get_entry(ctx
,
1846 smbd_dirptr_lanman2_match_fn
,
1852 return NT_STATUS_END_OF_FILE
;
1855 marshall_with_83_names
= (mangled_names
== MANGLED_NAMES_YES
);
1857 status
= smbd_marshall_dir_entry(ctx
,
1862 marshall_with_83_names
,
1863 requires_resume_key
,
1874 if (NT_STATUS_EQUAL(status
, NT_STATUS_ILLEGAL_CHARACTER
)) {
1875 DEBUG(1,("Conversion error: illegal character: %s\n",
1876 smb_fname_str_dbg(smb_fname
)));
1879 if (file_id
!= NULL
) {
1880 *file_id
= vfs_file_id_from_sbuf(conn
, &smb_fname
->st
);
1883 if (NT_STATUS_EQUAL(status
, STATUS_MORE_ENTRIES
)) {
1884 smbd_dirptr_push_overflow(dirptr
, &fname
, &smb_fname
, mode
);
1887 if (!NT_STATUS_IS_OK(status
)) {
1888 TALLOC_FREE(smb_fname
);
1893 smbd_dirptr_set_last_name_sent(dirptr
, &smb_fname
->base_name
);
1895 if (_smb_fname
!= NULL
) {
1897 * smb_fname is already talloc'ed off ctx.
1898 * We just need to make sure we don't return
1899 * any stream_name, and replace base_name
1900 * with fname in case base_name got mangled.
1901 * This allows us to preserve any smb_fname->fsp
1902 * for asynchronous handle lookups.
1904 TALLOC_FREE(smb_fname
->stream_name
);
1907 * smbd_dirptr_set_last_name_sent() above consumed
1910 smb_fname
->base_name
= talloc_strdup(smb_fname
, fname
);
1912 if (smb_fname
->base_name
== NULL
) {
1913 TALLOC_FREE(smb_fname
);
1915 return NT_STATUS_NO_MEMORY
;
1917 *_smb_fname
= smb_fname
;
1919 TALLOC_FREE(smb_fname
);
1923 *_last_entry_off
= last_entry_off
;
1924 return NT_STATUS_OK
;
1927 unsigned char *create_volume_objectid(connection_struct
*conn
, unsigned char objid
[16])
1929 const struct loadparm_substitution
*lp_sub
=
1930 loadparm_s3_global_substitution();
1932 E_md4hash(lp_servicename(talloc_tos(), lp_sub
, SNUM(conn
)),objid
);
1936 static void samba_extended_info_version(struct smb_extended_info
*extended_info
)
1938 SMB_ASSERT(extended_info
!= NULL
);
1940 extended_info
->samba_magic
= SAMBA_EXTENDED_INFO_MAGIC
;
1941 extended_info
->samba_version
= ((SAMBA_VERSION_MAJOR
& 0xff) << 24)
1942 | ((SAMBA_VERSION_MINOR
& 0xff) << 16)
1943 | ((SAMBA_VERSION_RELEASE
& 0xff) << 8);
1944 #ifdef SAMBA_VERSION_REVISION
1945 extended_info
->samba_version
|= (tolower(*SAMBA_VERSION_REVISION
) - 'a' + 1) & 0xff;
1947 extended_info
->samba_subversion
= 0;
1948 #ifdef SAMBA_VERSION_RC_RELEASE
1949 extended_info
->samba_subversion
|= (SAMBA_VERSION_RC_RELEASE
& 0xff) << 24;
1951 #ifdef SAMBA_VERSION_PRE_RELEASE
1952 extended_info
->samba_subversion
|= (SAMBA_VERSION_PRE_RELEASE
& 0xff) << 16;
1955 #ifdef SAMBA_VERSION_VENDOR_PATCH
1956 extended_info
->samba_subversion
|= (SAMBA_VERSION_VENDOR_PATCH
& 0xffff);
1958 extended_info
->samba_gitcommitdate
= 0;
1959 #ifdef SAMBA_VERSION_COMMIT_TIME
1960 unix_to_nt_time(&extended_info
->samba_gitcommitdate
, SAMBA_VERSION_COMMIT_TIME
);
1963 memset(extended_info
->samba_version_string
, 0,
1964 sizeof(extended_info
->samba_version_string
));
1966 snprintf (extended_info
->samba_version_string
,
1967 sizeof(extended_info
->samba_version_string
),
1968 "%s", samba_version_string());
1971 static bool fsinfo_unix_valid_level(connection_struct
*conn
,
1972 struct files_struct
*fsp
,
1973 uint16_t info_level
)
1975 if (conn
->sconn
->using_smb2
&&
1976 fsp
->posix_flags
== FSP_POSIX_FLAGS_OPEN
&&
1977 info_level
== SMB2_FS_POSIX_INFORMATION_INTERNAL
)
1981 #if defined(SMB1SERVER)
1982 if (lp_smb1_unix_extensions() &&
1983 info_level
== SMB_QUERY_POSIX_FS_INFO
) {
1991 * fsp is only valid for SMB2.
1993 NTSTATUS
smbd_do_qfsinfo(struct smbXsrv_connection
*xconn
,
1994 connection_struct
*conn
,
1995 TALLOC_CTX
*mem_ctx
,
1996 uint16_t info_level
,
1998 unsigned int max_data_bytes
,
1999 size_t *fixed_portion
,
2000 struct files_struct
*fsp
,
2001 struct smb_filename
*fname
,
2005 const struct loadparm_substitution
*lp_sub
=
2006 loadparm_s3_global_substitution();
2007 char *pdata
, *end_data
;
2010 const char *vname
= volume_label(talloc_tos(), SNUM(conn
));
2011 int snum
= SNUM(conn
);
2012 const char *fstype
= lp_fstype(SNUM(conn
));
2013 const char *filename
= NULL
;
2014 const uint64_t bytes_per_sector
= 512;
2015 uint32_t additional_flags
= 0;
2016 struct smb_filename smb_fname
;
2018 NTSTATUS status
= NT_STATUS_OK
;
2022 if (fname
== NULL
|| fname
->base_name
== NULL
) {
2025 filename
= fname
->base_name
;
2029 if (info_level
!= SMB_QUERY_CIFS_UNIX_INFO
) {
2030 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
2031 "info level (0x%x) on IPC$.\n",
2032 (unsigned int)info_level
));
2033 return NT_STATUS_ACCESS_DENIED
;
2037 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level
));
2039 smb_fname
= (struct smb_filename
) {
2040 .base_name
= discard_const_p(char, filename
),
2041 .flags
= fname
? fname
->flags
: 0,
2042 .twrp
= fname
? fname
->twrp
: 0,
2045 if(info_level
!= SMB_FS_QUOTA_INFORMATION
2046 && SMB_VFS_STAT(conn
, &smb_fname
) != 0) {
2047 DEBUG(2,("stat of . failed (%s)\n", strerror(errno
)));
2048 return map_nt_error_from_unix(errno
);
2053 if (max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
< max_data_bytes
) {
2054 return NT_STATUS_INVALID_PARAMETER
;
2057 *ppdata
= (char *)SMB_REALLOC(
2058 *ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
2059 if (*ppdata
== NULL
) {
2060 return NT_STATUS_NO_MEMORY
;
2064 memset((char *)pdata
,'\0',max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
2065 end_data
= pdata
+ max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
- 1;
2069 switch (info_level
) {
2070 case SMB_INFO_ALLOCATION
:
2072 uint64_t dfree
,dsize
,bsize
,block_size
,sectors_per_unit
;
2074 df_ret
= get_dfree_info(conn
, &smb_fname
, &bsize
,
2076 if (df_ret
== (uint64_t)-1) {
2077 return map_nt_error_from_unix(errno
);
2080 block_size
= lp_block_size(snum
);
2081 if (bsize
< block_size
) {
2082 uint64_t factor
= block_size
/bsize
;
2087 if (bsize
> block_size
) {
2088 uint64_t factor
= bsize
/block_size
;
2093 sectors_per_unit
= bsize
/bytes_per_sector
;
2095 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2096 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st
.st_ex_dev
, (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
2097 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
2100 * For large drives, return max values and not modulo.
2102 dsize
= MIN(dsize
, UINT32_MAX
);
2103 dfree
= MIN(dfree
, UINT32_MAX
);
2105 SIVAL(pdata
,l1_idFileSystem
,st
.st_ex_dev
);
2106 SIVAL(pdata
,l1_cSectorUnit
,sectors_per_unit
);
2107 SIVAL(pdata
,l1_cUnit
,dsize
);
2108 SIVAL(pdata
,l1_cUnitAvail
,dfree
);
2109 SSVAL(pdata
,l1_cbSector
,bytes_per_sector
);
2113 case SMB_INFO_VOLUME
:
2114 /* Return volume name */
2116 * Add volume serial number - hash of a combination of
2117 * the called hostname and the service name.
2119 serial
= generate_volume_serial_number(lp_sub
, snum
);
2120 SIVAL(pdata
,0,serial
);
2122 * Win2k3 and previous mess this up by sending a name length
2123 * one byte short. I believe only older clients (OS/2 Win9x) use
2124 * this call so try fixing this by adding a terminating null to
2125 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2127 status
= srvstr_push(
2129 pdata
+l2_vol_szVolLabel
, vname
,
2130 PTR_DIFF(end_data
, pdata
+l2_vol_szVolLabel
),
2131 STR_NOALIGN
|STR_TERMINATE
, &len
);
2132 if (!NT_STATUS_IS_OK(status
)) {
2135 SCVAL(pdata
,l2_vol_cch
,len
);
2136 data_len
= l2_vol_szVolLabel
+ len
;
2137 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %u, "
2138 "name = %s serial = 0x%04"PRIx32
"\n",
2139 (unsigned)convert_timespec_to_time_t(st
.st_ex_ctime
),
2140 (unsigned)len
, vname
, serial
));
2143 case SMB_QUERY_FS_ATTRIBUTE_INFO
:
2144 case SMB_FS_ATTRIBUTE_INFORMATION
:
2146 additional_flags
= 0;
2147 #if defined(HAVE_SYS_QUOTAS)
2148 additional_flags
|= FILE_VOLUME_QUOTAS
;
2151 if(lp_nt_acl_support(SNUM(conn
))) {
2152 additional_flags
|= FILE_PERSISTENT_ACLS
;
2155 /* Capabilities are filled in at connection time through STATVFS call */
2156 additional_flags
|= conn
->fs_capabilities
;
2157 additional_flags
|= lp_parm_int(conn
->params
->service
,
2158 "share", "fake_fscaps",
2161 SIVAL(pdata
,0,FILE_CASE_PRESERVED_NAMES
|FILE_CASE_SENSITIVE_SEARCH
|
2162 FILE_SUPPORTS_OBJECT_IDS
|FILE_UNICODE_ON_DISK
|
2163 additional_flags
); /* FS ATTRIBUTES */
2165 SIVAL(pdata
,4,255); /* Max filename component length */
2166 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2167 and will think we can't do long filenames */
2168 status
= srvstr_push(pdata
, flags2
, pdata
+12, fstype
,
2169 PTR_DIFF(end_data
, pdata
+12),
2171 if (!NT_STATUS_IS_OK(status
)) {
2175 data_len
= 12 + len
;
2176 if (max_data_bytes
>= 16 && data_len
> max_data_bytes
) {
2177 /* the client only requested a portion of the
2179 data_len
= max_data_bytes
;
2180 status
= STATUS_BUFFER_OVERFLOW
;
2182 *fixed_portion
= 16;
2185 case SMB_QUERY_FS_LABEL_INFO
:
2186 case SMB_FS_LABEL_INFORMATION
:
2187 status
= srvstr_push(pdata
, flags2
, pdata
+4, vname
,
2188 PTR_DIFF(end_data
, pdata
+4), 0, &len
);
2189 if (!NT_STATUS_IS_OK(status
)) {
2196 case SMB_QUERY_FS_VOLUME_INFO
:
2197 case SMB_FS_VOLUME_INFORMATION
:
2198 put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER
,
2199 pdata
, &st
.st_ex_btime
);
2201 * Add volume serial number - hash of a combination of
2202 * the called hostname and the service name.
2204 serial
= generate_volume_serial_number(lp_sub
, snum
);
2205 SIVAL(pdata
,8,serial
);
2207 /* Max label len is 32 characters. */
2208 status
= srvstr_push(pdata
, flags2
, pdata
+18, vname
,
2209 PTR_DIFF(end_data
, pdata
+18),
2211 if (!NT_STATUS_IS_OK(status
)) {
2214 SIVAL(pdata
,12,len
);
2217 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO "
2218 "namelen = %d, vol=%s serv=%s "
2219 "serial=0x%04"PRIx32
"\n",
2220 (int)strlen(vname
),vname
,
2221 lp_servicename(talloc_tos(), lp_sub
, snum
),
2223 if (max_data_bytes
>= 24 && data_len
> max_data_bytes
) {
2224 /* the client only requested a portion of the
2226 data_len
= max_data_bytes
;
2227 status
= STATUS_BUFFER_OVERFLOW
;
2229 *fixed_portion
= 24;
2232 case SMB_QUERY_FS_SIZE_INFO
:
2233 case SMB_FS_SIZE_INFORMATION
:
2235 uint64_t dfree
,dsize
,bsize
,block_size
,sectors_per_unit
;
2237 df_ret
= get_dfree_info(conn
, &smb_fname
, &bsize
,
2239 if (df_ret
== (uint64_t)-1) {
2240 return map_nt_error_from_unix(errno
);
2242 block_size
= lp_block_size(snum
);
2243 if (bsize
< block_size
) {
2244 uint64_t factor
= block_size
/bsize
;
2249 if (bsize
> block_size
) {
2250 uint64_t factor
= bsize
/block_size
;
2255 sectors_per_unit
= bsize
/bytes_per_sector
;
2256 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2257 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
2258 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
2259 SBIG_UINT(pdata
,0,dsize
);
2260 SBIG_UINT(pdata
,8,dfree
);
2261 SIVAL(pdata
,16,sectors_per_unit
);
2262 SIVAL(pdata
,20,bytes_per_sector
);
2263 *fixed_portion
= 24;
2267 case SMB_FS_FULL_SIZE_INFORMATION
:
2269 uint64_t dfree
,dsize
,bsize
,block_size
,sectors_per_unit
;
2271 df_ret
= get_dfree_info(conn
, &smb_fname
, &bsize
,
2273 if (df_ret
== (uint64_t)-1) {
2274 return map_nt_error_from_unix(errno
);
2276 block_size
= lp_block_size(snum
);
2277 if (bsize
< block_size
) {
2278 uint64_t factor
= block_size
/bsize
;
2283 if (bsize
> block_size
) {
2284 uint64_t factor
= bsize
/block_size
;
2289 sectors_per_unit
= bsize
/bytes_per_sector
;
2290 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2291 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
2292 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
2293 SBIG_UINT(pdata
,0,dsize
); /* Total Allocation units. */
2294 SBIG_UINT(pdata
,8,dfree
); /* Caller available allocation units. */
2295 SBIG_UINT(pdata
,16,dfree
); /* Actual available allocation units. */
2296 SIVAL(pdata
,24,sectors_per_unit
); /* Sectors per allocation unit. */
2297 SIVAL(pdata
,28,bytes_per_sector
); /* Bytes per sector. */
2298 *fixed_portion
= 32;
2302 case SMB_QUERY_FS_DEVICE_INFO
:
2303 case SMB_FS_DEVICE_INFORMATION
:
2305 uint32_t characteristics
= FILE_DEVICE_IS_MOUNTED
;
2307 if (!CAN_WRITE(conn
)) {
2308 characteristics
|= FILE_READ_ONLY_DEVICE
;
2311 SIVAL(pdata
,0,FILE_DEVICE_DISK
); /* dev type */
2312 SIVAL(pdata
,4,characteristics
);
2317 #ifdef HAVE_SYS_QUOTAS
2318 case SMB_FS_QUOTA_INFORMATION
:
2320 * what we have to send --metze:
2322 * Unknown1: 24 NULL bytes
2323 * Soft Quota Threshold: 8 bytes seems like uint64_t or so
2324 * Hard Quota Limit: 8 bytes seems like uint64_t or so
2325 * Quota Flags: 2 byte :
2326 * Unknown3: 6 NULL bytes
2330 * details for Quota Flags:
2332 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2333 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2334 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2335 * 0x0001 Enable Quotas: enable quota for this fs
2339 /* we need to fake up a fsp here,
2340 * because its not send in this call
2342 files_struct tmpfsp
;
2343 SMB_NTQUOTA_STRUCT quotas
;
2345 ZERO_STRUCT(tmpfsp
);
2346 ZERO_STRUCT(quotas
);
2349 tmpfsp
.fnum
= FNUM_FIELD_INVALID
;
2352 if (get_current_uid(conn
) != 0) {
2353 DEBUG(0,("get_user_quota: access_denied "
2354 "service [%s] user [%s]\n",
2355 lp_servicename(talloc_tos(), lp_sub
, SNUM(conn
)),
2356 conn
->session_info
->unix_info
->unix_name
));
2357 return NT_STATUS_ACCESS_DENIED
;
2360 status
= vfs_get_ntquota(&tmpfsp
, SMB_USER_FS_QUOTA_TYPE
,
2362 if (!NT_STATUS_IS_OK(status
)) {
2363 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), lp_sub
, SNUM(conn
))));
2369 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
2370 lp_servicename(talloc_tos(), lp_sub
, SNUM(conn
))));
2372 /* Unknown1 24 NULL bytes*/
2373 SBIG_UINT(pdata
,0,(uint64_t)0);
2374 SBIG_UINT(pdata
,8,(uint64_t)0);
2375 SBIG_UINT(pdata
,16,(uint64_t)0);
2377 /* Default Soft Quota 8 bytes */
2378 SBIG_UINT(pdata
,24,quotas
.softlim
);
2380 /* Default Hard Quota 8 bytes */
2381 SBIG_UINT(pdata
,32,quotas
.hardlim
);
2383 /* Quota flag 2 bytes */
2384 SSVAL(pdata
,40,quotas
.qflags
);
2386 /* Unknown3 6 NULL bytes */
2392 #endif /* HAVE_SYS_QUOTAS */
2393 case SMB_FS_OBJECTID_INFORMATION
:
2395 unsigned char objid
[16];
2396 struct smb_extended_info extended_info
;
2397 memcpy(pdata
,create_volume_objectid(conn
, objid
),16);
2398 samba_extended_info_version (&extended_info
);
2399 SIVAL(pdata
,16,extended_info
.samba_magic
);
2400 SIVAL(pdata
,20,extended_info
.samba_version
);
2401 SIVAL(pdata
,24,extended_info
.samba_subversion
);
2402 SBIG_UINT(pdata
,28,extended_info
.samba_gitcommitdate
);
2403 memcpy(pdata
+36,extended_info
.samba_version_string
,28);
2408 case SMB_FS_SECTOR_SIZE_INFORMATION
:
2412 * These values match a physical Windows Server 2012
2413 * share backed by NTFS atop spinning rust.
2415 DEBUG(5, ("SMB_FS_SECTOR_SIZE_INFORMATION:"));
2416 /* logical_bytes_per_sector */
2417 SIVAL(pdata
, 0, bytes_per_sector
);
2418 /* phys_bytes_per_sector_atomic */
2419 SIVAL(pdata
, 4, bytes_per_sector
);
2420 /* phys_bytes_per_sector_perf */
2421 SIVAL(pdata
, 8, bytes_per_sector
);
2422 /* fs_effective_phys_bytes_per_sector_atomic */
2423 SIVAL(pdata
, 12, bytes_per_sector
);
2425 SIVAL(pdata
, 16, SSINFO_FLAGS_ALIGNED_DEVICE
2426 | SSINFO_FLAGS_PARTITION_ALIGNED_ON_DEVICE
);
2427 /* byte_off_sector_align */
2428 SIVAL(pdata
, 20, 0);
2429 /* byte_off_partition_align */
2430 SIVAL(pdata
, 24, 0);
2431 *fixed_portion
= 28;
2436 #if defined(WITH_SMB1SERVER)
2438 * Query the version and capabilities of the CIFS UNIX extensions
2442 case SMB_QUERY_CIFS_UNIX_INFO
:
2444 bool large_write
= lp_min_receive_file_size() &&
2445 !smb1_srv_is_signing_active(xconn
);
2446 bool large_read
= !smb1_srv_is_signing_active(xconn
);
2447 int encrypt_caps
= 0;
2449 if (!lp_smb1_unix_extensions()) {
2450 return NT_STATUS_INVALID_LEVEL
;
2453 switch (conn
->encrypt_level
) {
2454 case SMB_SIGNING_OFF
:
2457 case SMB_SIGNING_DESIRED
:
2458 case SMB_SIGNING_IF_REQUIRED
:
2459 case SMB_SIGNING_DEFAULT
:
2460 encrypt_caps
= CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP
;
2462 case SMB_SIGNING_REQUIRED
:
2463 encrypt_caps
= CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP
|
2464 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP
;
2465 large_write
= false;
2471 SSVAL(pdata
,0,CIFS_UNIX_MAJOR_VERSION
);
2472 SSVAL(pdata
,2,CIFS_UNIX_MINOR_VERSION
);
2474 /* We have POSIX ACLs, pathname, encryption,
2475 * large read/write, and locking capability. */
2477 SBIG_UINT(pdata
,4,((uint64_t)(
2478 CIFS_UNIX_POSIX_ACLS_CAP
|
2479 CIFS_UNIX_POSIX_PATHNAMES_CAP
|
2480 CIFS_UNIX_FCNTL_LOCKS_CAP
|
2481 CIFS_UNIX_EXTATTR_CAP
|
2482 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP
|
2484 (large_read
? CIFS_UNIX_LARGE_READ_CAP
: 0) |
2486 CIFS_UNIX_LARGE_WRITE_CAP
: 0))));
2491 case SMB_QUERY_POSIX_FS_INFO
:
2492 case SMB2_FS_POSIX_INFORMATION_INTERNAL
:
2495 struct vfs_statvfs_struct svfs
;
2497 if (!fsinfo_unix_valid_level(conn
, fsp
, info_level
)) {
2498 return NT_STATUS_INVALID_LEVEL
;
2501 rc
= SMB_VFS_STATVFS(conn
, &smb_fname
, &svfs
);
2505 SIVAL(pdata
,0,svfs
.OptimalTransferSize
);
2506 SIVAL(pdata
,4,svfs
.BlockSize
);
2507 SBIG_UINT(pdata
,8,svfs
.TotalBlocks
);
2508 SBIG_UINT(pdata
,16,svfs
.BlocksAvail
);
2509 SBIG_UINT(pdata
,24,svfs
.UserBlocksAvail
);
2510 SBIG_UINT(pdata
,32,svfs
.TotalFileNodes
);
2511 SBIG_UINT(pdata
,40,svfs
.FreeFileNodes
);
2512 SBIG_UINT(pdata
,48,svfs
.FsIdentifier
);
2513 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO successful\n"));
2515 } else if (rc
== EOPNOTSUPP
) {
2516 return NT_STATUS_INVALID_LEVEL
;
2517 #endif /* EOPNOTSUPP */
2519 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(talloc_tos(), lp_sub
, SNUM(conn
))));
2520 return NT_STATUS_DOS(ERRSRV
, ERRerror
);
2525 case SMB_QUERY_POSIX_WHOAMI
:
2531 if (!lp_smb1_unix_extensions()) {
2532 return NT_STATUS_INVALID_LEVEL
;
2535 if (max_data_bytes
< 40) {
2536 return NT_STATUS_BUFFER_TOO_SMALL
;
2539 if (security_session_user_level(conn
->session_info
, NULL
) < SECURITY_USER
) {
2540 flags
|= SMB_WHOAMI_GUEST
;
2543 /* NOTE: 8 bytes for UID/GID, irrespective of native
2544 * platform size. This matches
2545 * SMB_QUERY_FILE_UNIX_BASIC and friends.
2547 data_len
= 4 /* flags */
2554 + 4 /* pad/reserved */
2555 + (conn
->session_info
->unix_token
->ngroups
* 8)
2557 + (conn
->session_info
->security_token
->num_sids
*
2561 SIVAL(pdata
, 0, flags
);
2562 SIVAL(pdata
, 4, SMB_WHOAMI_MASK
);
2564 (uint64_t)conn
->session_info
->unix_token
->uid
);
2565 SBIG_UINT(pdata
, 16,
2566 (uint64_t)conn
->session_info
->unix_token
->gid
);
2569 if (data_len
>= max_data_bytes
) {
2570 /* Potential overflow, skip the GIDs and SIDs. */
2572 SIVAL(pdata
, 24, 0); /* num_groups */
2573 SIVAL(pdata
, 28, 0); /* num_sids */
2574 SIVAL(pdata
, 32, 0); /* num_sid_bytes */
2575 SIVAL(pdata
, 36, 0); /* reserved */
2581 SIVAL(pdata
, 24, conn
->session_info
->unix_token
->ngroups
);
2582 SIVAL(pdata
, 28, conn
->session_info
->security_token
->num_sids
);
2584 /* We walk the SID list twice, but this call is fairly
2585 * infrequent, and I don't expect that it's performance
2586 * sensitive -- jpeach
2588 for (i
= 0, sid_bytes
= 0;
2589 i
< conn
->session_info
->security_token
->num_sids
; ++i
) {
2590 sid_bytes
+= ndr_size_dom_sid(
2591 &conn
->session_info
->security_token
->sids
[i
],
2595 /* SID list byte count */
2596 SIVAL(pdata
, 32, sid_bytes
);
2598 /* 4 bytes pad/reserved - must be zero */
2599 SIVAL(pdata
, 36, 0);
2603 for (i
= 0; i
< conn
->session_info
->unix_token
->ngroups
; ++i
) {
2604 SBIG_UINT(pdata
, data_len
,
2605 (uint64_t)conn
->session_info
->unix_token
->groups
[i
]);
2611 i
< conn
->session_info
->security_token
->num_sids
; ++i
) {
2612 int sid_len
= ndr_size_dom_sid(
2613 &conn
->session_info
->security_token
->sids
[i
],
2616 sid_linearize((uint8_t *)(pdata
+ data_len
),
2618 &conn
->session_info
->security_token
->sids
[i
]);
2619 data_len
+= sid_len
;
2625 case SMB_MAC_QUERY_FS_INFO
:
2627 * Thursby MAC extension... ONLY on NTFS filesystems
2628 * once we do streams then we don't need this
2630 if (strequal(lp_fstype(SNUM(conn
)),"NTFS")) {
2632 SIVAL(pdata
,84,0x100); /* Don't support mac... */
2638 return NT_STATUS_INVALID_LEVEL
;
2641 *ret_data_len
= data_len
;
2645 NTSTATUS
smb_set_fsquota(connection_struct
*conn
,
2646 struct smb_request
*req
,
2648 const DATA_BLOB
*qdata
)
2650 const struct loadparm_substitution
*lp_sub
=
2651 loadparm_s3_global_substitution();
2653 SMB_NTQUOTA_STRUCT quotas
;
2655 ZERO_STRUCT(quotas
);
2658 if ((get_current_uid(conn
) != 0) || !CAN_WRITE(conn
)) {
2659 DBG_NOTICE("access_denied service [%s] user [%s]\n",
2660 lp_servicename(talloc_tos(), lp_sub
, SNUM(conn
)),
2661 conn
->session_info
->unix_info
->unix_name
);
2662 return NT_STATUS_ACCESS_DENIED
;
2665 if (!check_fsp_ntquota_handle(conn
, req
,
2667 DBG_WARNING("no valid QUOTA HANDLE\n");
2668 return NT_STATUS_INVALID_HANDLE
;
2671 /* note: normally there're 48 bytes,
2672 * but we didn't use the last 6 bytes for now
2675 if (qdata
->length
< 42) {
2676 DBG_ERR("requires total_data(%zu) >= 42 bytes!\n",
2678 return NT_STATUS_INVALID_PARAMETER
;
2681 /* unknown_1 24 NULL bytes in pdata*/
2683 /* the soft quotas 8 bytes (uint64_t)*/
2684 quotas
.softlim
= BVAL(qdata
->data
,24);
2686 /* the hard quotas 8 bytes (uint64_t)*/
2687 quotas
.hardlim
= BVAL(qdata
->data
,32);
2689 /* quota_flags 2 bytes **/
2690 quotas
.qflags
= SVAL(qdata
->data
,40);
2692 /* unknown_2 6 NULL bytes follow*/
2694 /* now set the quotas */
2695 if (vfs_set_ntquota(fsp
, SMB_USER_FS_QUOTA_TYPE
, NULL
, "as
)!=0) {
2696 DBG_WARNING("vfs_set_ntquota() failed for service [%s]\n",
2697 lp_servicename(talloc_tos(), lp_sub
, SNUM(conn
)));
2698 status
= map_nt_error_from_unix(errno
);
2700 status
= NT_STATUS_OK
;
2705 NTSTATUS
smbd_do_setfsinfo(connection_struct
*conn
,
2706 struct smb_request
*req
,
2707 TALLOC_CTX
*mem_ctx
,
2708 uint16_t info_level
,
2710 const DATA_BLOB
*pdata
)
2712 switch (info_level
) {
2713 case SMB_FS_QUOTA_INFORMATION
:
2715 return smb_set_fsquota(conn
,
2724 return NT_STATUS_INVALID_LEVEL
;
2727 /****************************************************************************
2728 Store the FILE_UNIX_BASIC info.
2729 ****************************************************************************/
2731 char *store_file_unix_basic(connection_struct
*conn
,
2734 const SMB_STRUCT_STAT
*psbuf
)
2738 DBG_DEBUG("SMB_QUERY_FILE_UNIX_BASIC\n");
2739 DBG_NOTICE("st_mode=%o\n", (int)psbuf
->st_ex_mode
);
2741 SOFF_T(pdata
,0,get_file_size_stat(psbuf
)); /* File size 64 Bit */
2744 SOFF_T(pdata
,0,SMB_VFS_GET_ALLOC_SIZE(conn
,fsp
,psbuf
)); /* Number of bytes used on disk - 64 Bit */
2747 put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER
, pdata
, &psbuf
->st_ex_ctime
); /* Change Time 64 Bit */
2748 put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER
,pdata
+8, &psbuf
->st_ex_atime
); /* Last access time 64 Bit */
2749 put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER
, pdata
+16, &psbuf
->st_ex_mtime
); /* Last modification time 64 Bit */
2752 SIVAL(pdata
,0,psbuf
->st_ex_uid
); /* user id for the owner */
2756 SIVAL(pdata
,0,psbuf
->st_ex_gid
); /* group id of owner */
2760 SIVAL(pdata
,0,unix_filetype(psbuf
->st_ex_mode
));
2763 if (S_ISBLK(psbuf
->st_ex_mode
) || S_ISCHR(psbuf
->st_ex_mode
)) {
2764 devno
= psbuf
->st_ex_rdev
;
2766 devno
= psbuf
->st_ex_dev
;
2769 SIVAL(pdata
,0,unix_dev_major(devno
)); /* Major device number if type is device */
2773 SIVAL(pdata
,0,unix_dev_minor(devno
)); /* Minor device number if type is device */
2777 SINO_T_VAL(pdata
, 0, psbuf
->st_ex_ino
); /* inode number */
2780 SIVAL(pdata
,0, unix_perms_to_wire(psbuf
->st_ex_mode
)); /* Standard UNIX file permissions */
2784 SIVAL(pdata
,0,psbuf
->st_ex_nlink
); /* number of hard links */
2791 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
2792 * the chflags(2) (or equivalent) flags.
2794 * XXX: this really should be behind the VFS interface. To do this, we would
2795 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
2796 * Each VFS module could then implement its own mapping as appropriate for the
2797 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
2799 static const struct {unsigned stat_fflag
; unsigned smb_fflag
;}
2803 { UF_NODUMP
, EXT_DO_NOT_BACKUP
},
2807 { UF_IMMUTABLE
, EXT_IMMUTABLE
},
2811 { UF_APPEND
, EXT_OPEN_APPEND_ONLY
},
2815 { UF_HIDDEN
, EXT_HIDDEN
},
2818 /* Do not remove. We need to guarantee that this array has at least one
2819 * entry to build on HP-UX.
2825 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT
*psbuf
,
2826 uint32_t *smb_fflags
, uint32_t *smb_fmask
)
2830 for (i
= 0; i
< ARRAY_SIZE(info2_flags_map
); ++i
) {
2831 *smb_fmask
|= info2_flags_map
[i
].smb_fflag
;
2832 if (psbuf
->st_ex_flags
& info2_flags_map
[i
].stat_fflag
) {
2833 *smb_fflags
|= info2_flags_map
[i
].smb_fflag
;
2838 bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT
*psbuf
,
2839 const uint32_t smb_fflags
,
2840 const uint32_t smb_fmask
,
2843 uint32_t max_fmask
= 0;
2846 *stat_fflags
= psbuf
->st_ex_flags
;
2848 /* For each flags requested in smb_fmask, check the state of the
2849 * corresponding flag in smb_fflags and set or clear the matching
2853 for (i
= 0; i
< ARRAY_SIZE(info2_flags_map
); ++i
) {
2854 max_fmask
|= info2_flags_map
[i
].smb_fflag
;
2855 if (smb_fmask
& info2_flags_map
[i
].smb_fflag
) {
2856 if (smb_fflags
& info2_flags_map
[i
].smb_fflag
) {
2857 *stat_fflags
|= info2_flags_map
[i
].stat_fflag
;
2859 *stat_fflags
&= ~info2_flags_map
[i
].stat_fflag
;
2864 /* If smb_fmask is asking to set any bits that are not supported by
2865 * our flag mappings, we should fail.
2867 if ((smb_fmask
& max_fmask
) != smb_fmask
) {
2875 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
2876 * of file flags and birth (create) time.
2878 char *store_file_unix_basic_info2(connection_struct
*conn
,
2881 const SMB_STRUCT_STAT
*psbuf
)
2883 uint32_t file_flags
= 0;
2884 uint32_t flags_mask
= 0;
2886 pdata
= store_file_unix_basic(conn
, pdata
, fsp
, psbuf
);
2888 /* Create (birth) time 64 bit */
2889 put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER
,pdata
, &psbuf
->st_ex_btime
);
2892 map_info2_flags_from_sbuf(psbuf
, &file_flags
, &flags_mask
);
2893 SIVAL(pdata
, 0, file_flags
); /* flags */
2894 SIVAL(pdata
, 4, flags_mask
); /* mask */
2900 static NTSTATUS
marshall_stream_info(unsigned int num_streams
,
2901 const struct stream_struct
*streams
,
2903 unsigned int max_data_bytes
,
2904 unsigned int *data_size
)
2907 unsigned int ofs
= 0;
2909 if (max_data_bytes
< 32) {
2910 return NT_STATUS_INFO_LENGTH_MISMATCH
;
2913 for (i
= 0; i
< num_streams
; i
++) {
2914 unsigned int next_offset
;
2916 smb_ucs2_t
*namebuf
;
2918 if (!push_ucs2_talloc(talloc_tos(), &namebuf
,
2919 streams
[i
].name
, &namelen
) ||
2922 return NT_STATUS_INVALID_PARAMETER
;
2926 * name_buf is now null-terminated, we need to marshall as not
2933 * We cannot overflow ...
2935 if ((ofs
+ 24 + namelen
) > max_data_bytes
) {
2936 DEBUG(10, ("refusing to overflow reply at stream %u\n",
2938 TALLOC_FREE(namebuf
);
2939 return STATUS_BUFFER_OVERFLOW
;
2942 SIVAL(data
, ofs
+4, namelen
);
2943 SOFF_T(data
, ofs
+8, streams
[i
].size
);
2944 SOFF_T(data
, ofs
+16, streams
[i
].alloc_size
);
2945 memcpy(data
+ofs
+24, namebuf
, namelen
);
2946 TALLOC_FREE(namebuf
);
2948 next_offset
= ofs
+ 24 + namelen
;
2950 if (i
== num_streams
-1) {
2951 SIVAL(data
, ofs
, 0);
2954 unsigned int align
= ndr_align_size(next_offset
, 8);
2956 if ((next_offset
+ align
) > max_data_bytes
) {
2957 DEBUG(10, ("refusing to overflow align "
2958 "reply at stream %u\n",
2960 TALLOC_FREE(namebuf
);
2961 return STATUS_BUFFER_OVERFLOW
;
2964 memset(data
+next_offset
, 0, align
);
2965 next_offset
+= align
;
2967 SIVAL(data
, ofs
, next_offset
- ofs
);
2974 DEBUG(10, ("max_data: %u, data_size: %u\n", max_data_bytes
, ofs
));
2978 return NT_STATUS_OK
;
2981 NTSTATUS
smbd_do_qfilepathinfo(connection_struct
*conn
,
2982 TALLOC_CTX
*mem_ctx
,
2983 struct smb_request
*req
,
2984 uint16_t info_level
,
2986 struct smb_filename
*smb_fname
,
2987 bool delete_pending
,
2988 struct timespec write_time_ts
,
2989 struct ea_list
*ea_list
,
2991 unsigned int max_data_bytes
,
2992 size_t *fixed_portion
,
2994 unsigned int *pdata_size
)
2996 char *pdata
= *ppdata
;
2997 char *dstart
, *dend
;
2998 unsigned int data_size
;
2999 struct timespec create_time_ts
, mtime_ts
, atime_ts
, ctime_ts
;
3000 SMB_STRUCT_STAT
*psbuf
= NULL
;
3001 SMB_STRUCT_STAT
*base_sp
= NULL
;
3008 uint64_t file_size
= 0;
3010 uint64_t allocation_size
= 0;
3011 uint64_t file_id
= 0;
3012 uint32_t access_mask
= 0;
3015 if (INFO_LEVEL_IS_UNIX(info_level
)) {
3018 if (lp_smb1_unix_extensions() && req
->posix_pathnames
) {
3019 DBG_DEBUG("SMB1 unix extensions activated\n");
3023 if (conn
->sconn
->using_smb2
&&
3024 (fsp
->posix_flags
& FSP_POSIX_FLAGS_OPEN
))
3026 DBG_DEBUG("SMB2 posix open\n");
3031 return NT_STATUS_INVALID_LEVEL
;
3035 DBG_INFO("%s (%s) level=%d max_data=%u\n",
3036 smb_fname_str_dbg(smb_fname
),
3038 info_level
, max_data_bytes
);
3041 * In case of querying a symlink in POSIX context,
3042 * fsp will be NULL. fdos_mode() deals with it.
3045 smb_fname
= fsp
->fsp_name
;
3047 mode
= fdos_mode(fsp
);
3048 psbuf
= &smb_fname
->st
;
3051 base_sp
= fsp
->base_fsp
?
3052 &fsp
->base_fsp
->fsp_name
->st
:
3055 base_sp
= &smb_fname
->st
;
3058 nlink
= psbuf
->st_ex_nlink
;
3060 if (nlink
&& (mode
&FILE_ATTRIBUTE_DIRECTORY
)) {
3064 if ((nlink
> 0) && delete_pending
) {
3068 if (max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
< max_data_bytes
) {
3069 return NT_STATUS_INVALID_PARAMETER
;
3072 data_size
= max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
;
3073 *ppdata
= (char *)SMB_REALLOC(*ppdata
, data_size
);
3074 if (*ppdata
== NULL
) {
3075 return NT_STATUS_NO_MEMORY
;
3079 dend
= dstart
+ data_size
- 1;
3081 if (!is_omit_timespec(&write_time_ts
) &&
3082 !INFO_LEVEL_IS_UNIX(info_level
))
3084 update_stat_ex_mtime(psbuf
, write_time_ts
);
3087 create_time_ts
= get_create_timespec(conn
, fsp
, smb_fname
);
3088 mtime_ts
= psbuf
->st_ex_mtime
;
3089 atime_ts
= psbuf
->st_ex_atime
;
3090 ctime_ts
= get_change_timespec(conn
, fsp
, smb_fname
);
3092 if (lp_dos_filetime_resolution(SNUM(conn
))) {
3093 dos_filetime_timespec(&create_time_ts
);
3094 dos_filetime_timespec(&mtime_ts
);
3095 dos_filetime_timespec(&atime_ts
);
3096 dos_filetime_timespec(&ctime_ts
);
3099 p
= strrchr_m(smb_fname
->base_name
,'/');
3101 base_name
= smb_fname
->base_name
;
3105 /* NT expects the name to be in an exact form of the *full*
3106 filename. See the trans2 torture test */
3107 if (ISDOT(base_name
)) {
3108 dos_fname
= talloc_strdup(mem_ctx
, "\\");
3110 return NT_STATUS_NO_MEMORY
;
3113 dos_fname
= talloc_asprintf(mem_ctx
,
3115 smb_fname
->base_name
);
3117 return NT_STATUS_NO_MEMORY
;
3119 if (is_named_stream(smb_fname
)) {
3120 dos_fname
= talloc_asprintf(dos_fname
, "%s",
3121 smb_fname
->stream_name
);
3123 return NT_STATUS_NO_MEMORY
;
3127 string_replace(dos_fname
, '/', '\\');
3130 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
, fsp
, psbuf
);
3132 if (fsp
== NULL
|| !fsp
->fsp_flags
.is_fsa
) {
3133 /* Do we have this path open ? */
3134 struct file_id fileid
= vfs_file_id_from_sbuf(conn
, psbuf
);
3135 files_struct
*fsp1
= file_find_di_first(
3136 conn
->sconn
, fileid
, true);
3137 if (fsp1
&& fsp1
->initial_allocation_size
) {
3138 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
, fsp1
, psbuf
);
3142 if (!(mode
& FILE_ATTRIBUTE_DIRECTORY
)) {
3143 file_size
= get_file_size_stat(psbuf
);
3147 pos
= fh_get_position_information(fsp
->fh
);
3151 access_mask
= fsp
->access_mask
;
3153 /* GENERIC_EXECUTE mapping from Windows */
3154 access_mask
= 0x12019F;
3157 /* This should be an index number - looks like
3160 I think this causes us to fail the IFSKIT
3161 BasicFileInformationTest. -tpot */
3162 file_id
= SMB_VFS_FS_FILE_ID(conn
, base_sp
);
3166 switch (info_level
) {
3167 case SMB_INFO_STANDARD
:
3168 DBG_DEBUG("SMB_INFO_STANDARD\n");
3170 srv_put_dos_date2_ts(pdata
,
3173 srv_put_dos_date2_ts(pdata
,
3176 srv_put_dos_date2_ts(pdata
,
3178 mtime_ts
); /* write time */
3179 SIVAL(pdata
,l1_cbFile
,(uint32_t)file_size
);
3180 SIVAL(pdata
,l1_cbFileAlloc
,(uint32_t)allocation_size
);
3181 SSVAL(pdata
,l1_attrFile
,mode
);
3184 case SMB_INFO_QUERY_EA_SIZE
:
3186 unsigned int ea_size
=
3187 estimate_ea_size(smb_fname
->fsp
);
3188 DBG_DEBUG("SMB_INFO_QUERY_EA_SIZE\n");
3190 srv_put_dos_date2_ts(pdata
, 0, create_time_ts
);
3191 srv_put_dos_date2_ts(pdata
, 4, atime_ts
);
3192 srv_put_dos_date2_ts(pdata
,
3194 mtime_ts
); /* write time */
3195 SIVAL(pdata
,12,(uint32_t)file_size
);
3196 SIVAL(pdata
,16,(uint32_t)allocation_size
);
3197 SSVAL(pdata
,20,mode
);
3198 SIVAL(pdata
,22,ea_size
);
3202 case SMB_INFO_IS_NAME_VALID
:
3203 DBG_DEBUG("SMB_INFO_IS_NAME_VALID\n");
3205 /* os/2 needs this ? really ?*/
3206 return NT_STATUS_DOS(ERRDOS
, ERRbadfunc
);
3208 /* This is only reached for qpathinfo */
3212 case SMB_INFO_QUERY_EAS_FROM_LIST
:
3214 size_t total_ea_len
= 0;
3215 struct ea_list
*ea_file_list
= NULL
;
3216 DBG_DEBUG("SMB_INFO_QUERY_EAS_FROM_LIST\n");
3219 get_ea_list_from_fsp(mem_ctx
,
3221 &total_ea_len
, &ea_file_list
);
3222 if (!NT_STATUS_IS_OK(status
)) {
3226 ea_list
= ea_list_union(ea_list
, ea_file_list
, &total_ea_len
);
3228 if (!ea_list
|| (total_ea_len
> data_size
)) {
3230 SIVAL(pdata
,0,4); /* EA List Length must be set to 4 if no EA's. */
3234 data_size
= fill_ea_buffer(mem_ctx
, pdata
, data_size
, conn
, ea_list
);
3238 case SMB_INFO_QUERY_ALL_EAS
:
3240 /* We have data_size bytes to put EA's into. */
3241 size_t total_ea_len
= 0;
3242 DBG_DEBUG(" SMB_INFO_QUERY_ALL_EAS\n");
3244 status
= get_ea_list_from_fsp(mem_ctx
,
3246 &total_ea_len
, &ea_list
);
3247 if (!NT_STATUS_IS_OK(status
)) {
3251 if (!ea_list
|| (total_ea_len
> data_size
)) {
3253 SIVAL(pdata
,0,4); /* EA List Length must be set to 4 if no EA's. */
3257 data_size
= fill_ea_buffer(mem_ctx
, pdata
, data_size
, conn
, ea_list
);
3261 case SMB2_FILE_FULL_EA_INFORMATION
:
3263 /* We have data_size bytes to put EA's into. */
3264 size_t total_ea_len
= 0;
3265 struct ea_list
*ea_file_list
= NULL
;
3267 DBG_DEBUG("SMB2_INFO_QUERY_ALL_EAS\n");
3269 /*TODO: add filtering and index handling */
3272 get_ea_list_from_fsp(mem_ctx
,
3274 &total_ea_len
, &ea_file_list
);
3275 if (!NT_STATUS_IS_OK(status
)) {
3278 if (!ea_file_list
) {
3279 return NT_STATUS_NO_EAS_ON_FILE
;
3282 status
= fill_ea_chained_buffer(mem_ctx
,
3286 conn
, ea_file_list
);
3287 if (!NT_STATUS_IS_OK(status
)) {
3293 case SMB_FILE_BASIC_INFORMATION
:
3294 case SMB_QUERY_FILE_BASIC_INFO
:
3296 if (info_level
== SMB_QUERY_FILE_BASIC_INFO
) {
3297 DBG_DEBUG("SMB_QUERY_FILE_BASIC_INFO\n");
3298 data_size
= 36; /* w95 returns 40 bytes not 36 - why ?. */
3300 DBG_DEBUG("SMB_FILE_BASIC_INFORMATION\n");
3304 put_long_date_full_timespec(conn
->ts_res
,pdata
,&create_time_ts
);
3305 put_long_date_full_timespec(conn
->ts_res
,pdata
+8,&atime_ts
);
3306 put_long_date_full_timespec(conn
->ts_res
,pdata
+16,&mtime_ts
); /* write time */
3307 put_long_date_full_timespec(conn
->ts_res
,pdata
+24,&ctime_ts
); /* change time */
3308 SIVAL(pdata
,32,mode
);
3310 DBG_INFO("SMB_QFBI - create: %s access: %s "
3311 "write: %s change: %s mode: %x\n",
3312 ctime(&create_time_ts
.tv_sec
),
3313 ctime(&atime_ts
.tv_sec
),
3314 ctime(&mtime_ts
.tv_sec
),
3315 ctime(&ctime_ts
.tv_sec
),
3317 *fixed_portion
= data_size
;
3320 case SMB_FILE_STANDARD_INFORMATION
:
3321 case SMB_QUERY_FILE_STANDARD_INFO
:
3323 DBG_DEBUG("SMB_FILE_STANDARD_INFORMATION\n");
3325 SOFF_T(pdata
,0,allocation_size
);
3326 SOFF_T(pdata
,8,file_size
);
3327 SIVAL(pdata
,16,nlink
);
3328 SCVAL(pdata
,20,delete_pending
?1:0);
3329 SCVAL(pdata
,21,(mode
&FILE_ATTRIBUTE_DIRECTORY
)?1:0);
3330 SSVAL(pdata
,22,0); /* Padding. */
3331 *fixed_portion
= 24;
3334 case SMB_FILE_EA_INFORMATION
:
3335 case SMB_QUERY_FILE_EA_INFO
:
3337 unsigned int ea_size
=
3338 estimate_ea_size(smb_fname
->fsp
);
3339 DBG_DEBUG("SMB_FILE_EA_INFORMATION\n");
3342 SIVAL(pdata
,0,ea_size
);
3346 /* Get the 8.3 name - used if NT SMB was negotiated. */
3347 case SMB_QUERY_FILE_ALT_NAME_INFO
:
3348 case SMB_FILE_ALTERNATE_NAME_INFORMATION
:
3350 char mangled_name
[13];
3351 DBG_DEBUG("SMB_FILE_ALTERNATE_NAME_INFORMATION\n");
3352 if (!name_to_8_3(base_name
,mangled_name
,
3353 True
,conn
->params
)) {
3354 return NT_STATUS_NO_MEMORY
;
3356 status
= srvstr_push(dstart
, flags2
,
3357 pdata
+4, mangled_name
,
3358 PTR_DIFF(dend
, pdata
+4),
3360 if (!NT_STATUS_IS_OK(status
)) {
3363 data_size
= 4 + len
;
3369 case SMB_QUERY_FILE_NAME_INFO
:
3372 this must be *exactly* right for ACLs on mapped drives to work
3374 status
= srvstr_push(dstart
, flags2
,
3376 PTR_DIFF(dend
, pdata
+4),
3378 if (!NT_STATUS_IS_OK(status
)) {
3381 DBG_DEBUG("SMB_QUERY_FILE_NAME_INFO\n");
3382 data_size
= 4 + len
;
3387 case SMB_FILE_NORMALIZED_NAME_INFORMATION
:
3389 char *nfname
= NULL
;
3391 if (fsp
== NULL
|| !fsp
->conn
->sconn
->using_smb2
) {
3392 return NT_STATUS_INVALID_LEVEL
;
3395 nfname
= talloc_strdup(mem_ctx
, smb_fname
->base_name
);
3396 if (nfname
== NULL
) {
3397 return NT_STATUS_NO_MEMORY
;
3400 if (ISDOT(nfname
)) {
3403 string_replace(nfname
, '/', '\\');
3405 if (fsp_is_alternate_stream(fsp
)) {
3406 const char *s
= smb_fname
->stream_name
;
3407 const char *e
= NULL
;
3410 SMB_ASSERT(s
[0] != '\0');
3413 * smb_fname->stream_name is in form
3414 * of ':StrEam:$DATA', but we should only
3415 * append ':StrEam' here.
3418 e
= strchr(&s
[1], ':');
3424 nfname
= talloc_strndup_append(nfname
, s
, n
);
3425 if (nfname
== NULL
) {
3426 return NT_STATUS_NO_MEMORY
;
3430 status
= srvstr_push(dstart
, flags2
,
3432 PTR_DIFF(dend
, pdata
+4),
3434 if (!NT_STATUS_IS_OK(status
)) {
3437 DBG_DEBUG("SMB_FILE_NORMALIZED_NAME_INFORMATION\n");
3438 data_size
= 4 + len
;
3444 case SMB_FILE_ALLOCATION_INFORMATION
:
3445 case SMB_QUERY_FILE_ALLOCATION_INFO
:
3446 DBG_DEBUG("SMB_FILE_ALLOCATION_INFORMATION\n");
3448 SOFF_T(pdata
,0,allocation_size
);
3451 case SMB_FILE_END_OF_FILE_INFORMATION
:
3452 case SMB_QUERY_FILE_END_OF_FILEINFO
:
3453 DBG_DEBUG("SMB_FILE_END_OF_FILE_INFORMATION\n");
3455 SOFF_T(pdata
,0,file_size
);
3458 case SMB_QUERY_FILE_ALL_INFO
:
3459 case SMB_FILE_ALL_INFORMATION
:
3461 unsigned int ea_size
=
3462 estimate_ea_size(smb_fname
->fsp
);
3463 DBG_DEBUG("SMB_FILE_ALL_INFORMATION\n");
3464 put_long_date_full_timespec(conn
->ts_res
,pdata
,&create_time_ts
);
3465 put_long_date_full_timespec(conn
->ts_res
,pdata
+8,&atime_ts
);
3466 put_long_date_full_timespec(conn
->ts_res
,pdata
+16,&mtime_ts
); /* write time */
3467 put_long_date_full_timespec(conn
->ts_res
,pdata
+24,&ctime_ts
); /* change time */
3468 SIVAL(pdata
,32,mode
);
3469 SIVAL(pdata
,36,0); /* padding. */
3471 SOFF_T(pdata
,0,allocation_size
);
3472 SOFF_T(pdata
,8,file_size
);
3473 SIVAL(pdata
,16,nlink
);
3474 SCVAL(pdata
,20,delete_pending
);
3475 SCVAL(pdata
,21,(mode
&FILE_ATTRIBUTE_DIRECTORY
)?1:0);
3478 SIVAL(pdata
,0,ea_size
);
3479 pdata
+= 4; /* EA info */
3480 status
= srvstr_push(dstart
, flags2
,
3482 PTR_DIFF(dend
, pdata
+4),
3484 if (!NT_STATUS_IS_OK(status
)) {
3489 data_size
= PTR_DIFF(pdata
,(*ppdata
));
3490 *fixed_portion
= 10;
3494 case SMB2_FILE_ALL_INFORMATION
:
3496 unsigned int ea_size
=
3497 estimate_ea_size(smb_fname
->fsp
);
3498 DBG_DEBUG("SMB2_FILE_ALL_INFORMATION\n");
3499 put_long_date_full_timespec(conn
->ts_res
,pdata
+0x00,&create_time_ts
);
3500 put_long_date_full_timespec(conn
->ts_res
,pdata
+0x08,&atime_ts
);
3501 put_long_date_full_timespec(conn
->ts_res
,pdata
+0x10,&mtime_ts
); /* write time */
3502 put_long_date_full_timespec(conn
->ts_res
,pdata
+0x18,&ctime_ts
); /* change time */
3503 SIVAL(pdata
, 0x20, mode
);
3504 SIVAL(pdata
, 0x24, 0); /* padding. */
3505 SBVAL(pdata
, 0x28, allocation_size
);
3506 SBVAL(pdata
, 0x30, file_size
);
3507 SIVAL(pdata
, 0x38, nlink
);
3508 SCVAL(pdata
, 0x3C, delete_pending
);
3509 SCVAL(pdata
, 0x3D, (mode
&FILE_ATTRIBUTE_DIRECTORY
)?1:0);
3510 SSVAL(pdata
, 0x3E, 0); /* padding */
3511 SBVAL(pdata
, 0x40, file_id
);
3512 SIVAL(pdata
, 0x48, ea_size
);
3513 SIVAL(pdata
, 0x4C, access_mask
);
3514 SBVAL(pdata
, 0x50, pos
);
3515 SIVAL(pdata
, 0x58, mode
); /*TODO: mode != mode fix this!!! */
3516 SIVAL(pdata
, 0x5C, 0); /* No alignment needed. */
3520 status
= srvstr_push(dstart
, flags2
,
3522 PTR_DIFF(dend
, pdata
+4),
3524 if (!NT_STATUS_IS_OK(status
)) {
3529 data_size
= PTR_DIFF(pdata
,(*ppdata
));
3530 *fixed_portion
= 104;
3533 case SMB_FILE_INTERNAL_INFORMATION
:
3535 DBG_DEBUG("SMB_FILE_INTERNAL_INFORMATION\n");
3536 SBVAL(pdata
, 0, file_id
);
3541 case SMB_FILE_ACCESS_INFORMATION
:
3542 DBG_DEBUG("SMB_FILE_ACCESS_INFORMATION\n");
3543 SIVAL(pdata
, 0, access_mask
);
3548 case SMB_FILE_NAME_INFORMATION
:
3549 /* Pathname with leading '\'. */
3552 byte_len
= dos_PutUniCode(pdata
+4,dos_fname
,(size_t)max_data_bytes
,False
);
3553 DBG_DEBUG("SMB_FILE_NAME_INFORMATION\n");
3554 SIVAL(pdata
,0,byte_len
);
3555 data_size
= 4 + byte_len
;
3559 case SMB_FILE_DISPOSITION_INFORMATION
:
3560 DBG_DEBUG("SMB_FILE_DISPOSITION_INFORMATION\n");
3562 SCVAL(pdata
,0,delete_pending
);
3566 case SMB_FILE_POSITION_INFORMATION
:
3567 DBG_DEBUG("SMB_FILE_POSITION_INFORMATION\n");
3569 SOFF_T(pdata
,0,pos
);
3573 case SMB_FILE_MODE_INFORMATION
:
3574 DBG_DEBUG("SMB_FILE_MODE_INFORMATION\n");
3575 SIVAL(pdata
,0,mode
);
3580 case SMB_FILE_ALIGNMENT_INFORMATION
:
3581 DBG_DEBUG("SMB_FILE_ALIGNMENT_INFORMATION\n");
3582 SIVAL(pdata
,0,0); /* No alignment needed. */
3588 * NT4 server just returns "invalid query" to this - if we try
3589 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
3592 /* The first statement above is false - verified using Thursby
3593 * client against NT4 -- gcolley.
3595 case SMB_QUERY_FILE_STREAM_INFO
:
3596 case SMB_FILE_STREAM_INFORMATION
: {
3597 unsigned int num_streams
= 0;
3598 struct stream_struct
*streams
= NULL
;
3600 DBG_DEBUG("SMB_FILE_STREAM_INFORMATION\n");
3602 if (is_ntfs_stream_smb_fname(smb_fname
)) {
3603 return NT_STATUS_INVALID_PARAMETER
;
3606 status
= vfs_fstreaminfo(fsp
,
3611 if (!NT_STATUS_IS_OK(status
)) {
3612 DBG_DEBUG("could not get stream info: %s\n",
3617 status
= marshall_stream_info(num_streams
, streams
,
3618 pdata
, max_data_bytes
,
3621 if (!NT_STATUS_IS_OK(status
)) {
3622 DBG_DEBUG("marshall_stream_info failed: %s\n",
3624 TALLOC_FREE(streams
);
3628 TALLOC_FREE(streams
);
3630 *fixed_portion
= 32;
3634 case SMB_QUERY_COMPRESSION_INFO
:
3635 case SMB_FILE_COMPRESSION_INFORMATION
:
3636 DBG_DEBUG("SMB_FILE_COMPRESSION_INFORMATION\n");
3637 SOFF_T(pdata
,0,file_size
);
3638 SIVAL(pdata
,8,0); /* ??? */
3639 SIVAL(pdata
,12,0); /* ??? */
3641 *fixed_portion
= 16;
3644 case SMB_FILE_NETWORK_OPEN_INFORMATION
:
3645 DBG_DEBUG("SMB_FILE_NETWORK_OPEN_INFORMATION\n");
3646 put_long_date_full_timespec(conn
->ts_res
,pdata
,&create_time_ts
);
3647 put_long_date_full_timespec(conn
->ts_res
,pdata
+8,&atime_ts
);
3648 put_long_date_full_timespec(conn
->ts_res
,pdata
+16,&mtime_ts
); /* write time */
3649 put_long_date_full_timespec(conn
->ts_res
,pdata
+24,&ctime_ts
); /* change time */
3650 SOFF_T(pdata
,32,allocation_size
);
3651 SOFF_T(pdata
,40,file_size
);
3652 SIVAL(pdata
,48,mode
);
3653 SIVAL(pdata
,52,0); /* ??? */
3655 *fixed_portion
= 56;
3658 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION
:
3659 DBG_DEBUG(" SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n");
3660 SIVAL(pdata
,0,mode
);
3667 * SMB2 UNIX Extensions.
3669 case SMB2_FILE_POSIX_INFORMATION_INTERNAL
:
3671 struct smb3_file_posix_information info
= {};
3672 uint8_t buf
[sizeof(info
)];
3673 struct ndr_push ndr
= {
3675 .alloc_size
= sizeof(buf
),
3676 .fixed_buf_size
= true,
3678 enum ndr_err_code ndr_err
;
3680 if (!(conn
->sconn
->using_smb2
)) {
3681 return NT_STATUS_INVALID_LEVEL
;
3684 return NT_STATUS_INVALID_HANDLE
;
3686 if (!(fsp
->posix_flags
& FSP_POSIX_FLAGS_OPEN
)) {
3687 return NT_STATUS_INVALID_LEVEL
;
3690 smb3_file_posix_information_init(
3691 conn
, &smb_fname
->st
, 0, mode
, &info
);
3693 ndr_err
= ndr_push_smb3_file_posix_information(
3694 &ndr
, NDR_SCALARS
|NDR_BUFFERS
, &info
);
3695 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
3696 return NT_STATUS_INSUFFICIENT_RESOURCES
;
3699 memcpy(pdata
, buf
, ndr
.offset
);
3700 data_size
= ndr
.offset
;
3705 return NT_STATUS_INVALID_LEVEL
;
3708 *pdata_size
= data_size
;
3709 return NT_STATUS_OK
;
3712 /****************************************************************************
3713 Set a hard link (called by UNIX extensions and by NT rename with HARD link
3715 ****************************************************************************/
3717 NTSTATUS
hardlink_internals(TALLOC_CTX
*ctx
,
3718 connection_struct
*conn
,
3719 struct smb_request
*req
,
3720 bool overwrite_if_exists
,
3721 const struct smb_filename
*smb_fname_old
,
3722 struct smb_filename
*smb_fname_new
)
3724 NTSTATUS status
= NT_STATUS_OK
;
3727 struct smb_filename
*parent_fname_old
= NULL
;
3728 struct smb_filename
*base_name_old
= NULL
;
3729 struct smb_filename
*parent_fname_new
= NULL
;
3730 struct smb_filename
*base_name_new
= NULL
;
3732 /* source must already exist. */
3733 if (!VALID_STAT(smb_fname_old
->st
)) {
3734 status
= NT_STATUS_OBJECT_NAME_NOT_FOUND
;
3738 /* No links from a directory. */
3739 if (S_ISDIR(smb_fname_old
->st
.st_ex_mode
)) {
3740 status
= NT_STATUS_FILE_IS_A_DIRECTORY
;
3744 /* Setting a hardlink to/from a stream isn't currently supported. */
3745 ok
= is_ntfs_stream_smb_fname(smb_fname_old
);
3747 DBG_DEBUG("Old name has streams\n");
3748 status
= NT_STATUS_INVALID_PARAMETER
;
3751 ok
= is_ntfs_stream_smb_fname(smb_fname_new
);
3753 DBG_DEBUG("New name has streams\n");
3754 status
= NT_STATUS_INVALID_PARAMETER
;
3758 if (smb_fname_old
->twrp
!= 0) {
3759 status
= NT_STATUS_NOT_SAME_DEVICE
;
3763 status
= parent_pathref(talloc_tos(),
3768 if (!NT_STATUS_IS_OK(status
)) {
3772 status
= parent_pathref(talloc_tos(),
3777 if (!NT_STATUS_IS_OK(status
)) {
3781 if (VALID_STAT(smb_fname_new
->st
)) {
3782 if (overwrite_if_exists
) {
3783 if (S_ISDIR(smb_fname_new
->st
.st_ex_mode
)) {
3784 status
= NT_STATUS_FILE_IS_A_DIRECTORY
;
3787 status
= unlink_internals(conn
,
3789 FILE_ATTRIBUTE_NORMAL
,
3790 NULL
, /* new_dirfsp */
3792 if (!NT_STATUS_IS_OK(status
)) {
3796 /* Disallow if newname already exists. */
3797 status
= NT_STATUS_OBJECT_NAME_COLLISION
;
3802 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
3803 smb_fname_old
->base_name
, smb_fname_new
->base_name
));
3805 ret
= SMB_VFS_LINKAT(conn
,
3806 parent_fname_old
->fsp
,
3808 parent_fname_new
->fsp
,
3813 status
= map_nt_error_from_unix(errno
);
3814 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
3815 nt_errstr(status
), smb_fname_old
->base_name
,
3816 smb_fname_new
->base_name
));
3821 TALLOC_FREE(parent_fname_old
);
3822 TALLOC_FREE(parent_fname_new
);
3826 /****************************************************************************
3827 Deal with setting the time from any of the setfilepathinfo functions.
3828 NOTE !!!! The check for FILE_WRITE_ATTRIBUTES access must be done *before*
3829 calling this function.
3830 ****************************************************************************/
3832 NTSTATUS
smb_set_file_time(connection_struct
*conn
,
3834 struct smb_filename
*smb_fname
,
3835 struct smb_file_time
*ft
,
3836 bool setting_write_time
)
3838 struct files_struct
*set_fsp
= NULL
;
3839 struct timeval_buf tbuf
[4];
3841 FILE_NOTIFY_CHANGE_LAST_ACCESS
3842 |FILE_NOTIFY_CHANGE_LAST_WRITE
3843 |FILE_NOTIFY_CHANGE_CREATION
;
3846 if (!VALID_STAT(smb_fname
->st
)) {
3847 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
3852 return NT_STATUS_OK
;
3855 set_fsp
= metadata_fsp(fsp
);
3857 /* get some defaults (no modifications) if any info is zero or -1. */
3858 if (is_omit_timespec(&ft
->create_time
)) {
3859 action
&= ~FILE_NOTIFY_CHANGE_CREATION
;
3862 if (is_omit_timespec(&ft
->atime
)) {
3863 action
&= ~FILE_NOTIFY_CHANGE_LAST_ACCESS
;
3866 if (is_omit_timespec(&ft
->mtime
)) {
3867 action
&= ~FILE_NOTIFY_CHANGE_LAST_WRITE
;
3870 if (!setting_write_time
) {
3871 /* ft->mtime comes from change time, not write time. */
3872 action
&= ~FILE_NOTIFY_CHANGE_LAST_WRITE
;
3875 /* Ensure the resolution is the correct for
3876 * what we can store on this filesystem. */
3878 round_timespec(conn
->ts_res
, &ft
->create_time
);
3879 round_timespec(conn
->ts_res
, &ft
->ctime
);
3880 round_timespec(conn
->ts_res
, &ft
->atime
);
3881 round_timespec(conn
->ts_res
, &ft
->mtime
);
3883 DBG_DEBUG("smb_set_filetime: actime: %s\n ",
3884 timespec_string_buf(&ft
->atime
, true, &tbuf
[0]));
3885 DBG_DEBUG("smb_set_filetime: modtime: %s\n ",
3886 timespec_string_buf(&ft
->mtime
, true, &tbuf
[1]));
3887 DBG_DEBUG("smb_set_filetime: ctime: %s\n ",
3888 timespec_string_buf(&ft
->ctime
, true, &tbuf
[2]));
3889 DBG_DEBUG("smb_set_file_time: createtime: %s\n ",
3890 timespec_string_buf(&ft
->create_time
, true, &tbuf
[3]));
3892 if (setting_write_time
) {
3894 * This was a Windows setfileinfo on an open file.
3895 * NT does this a lot. We also need to
3896 * set the time here, as it can be read by
3897 * FindFirst/FindNext and with the patch for bug #2045
3898 * in smbd/fileio.c it ensures that this timestamp is
3899 * kept sticky even after a write. We save the request
3900 * away and will set it on file close and after a write. JRA.
3903 DBG_DEBUG("setting pending modtime to %s\n",
3904 timespec_string_buf(&ft
->mtime
, true, &tbuf
[0]));
3906 if (set_fsp
!= NULL
) {
3907 set_sticky_write_time_fsp(set_fsp
, ft
->mtime
);
3909 set_sticky_write_time_path(
3910 vfs_file_id_from_sbuf(conn
, &smb_fname
->st
),
3915 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
3917 ret
= file_ntimes(conn
, set_fsp
, ft
);
3919 return map_nt_error_from_unix(errno
);
3922 notify_fname(conn
, NOTIFY_ACTION_MODIFIED
, action
,
3923 smb_fname
->base_name
);
3924 return NT_STATUS_OK
;
3927 /****************************************************************************
3928 Deal with setting the dosmode from any of the setfilepathinfo functions.
3929 NB. The check for FILE_WRITE_ATTRIBUTES access on this path must have been
3930 done before calling this function.
3931 ****************************************************************************/
3933 static NTSTATUS
smb_set_file_dosmode(connection_struct
*conn
,
3934 struct files_struct
*fsp
,
3937 struct files_struct
*dos_fsp
= NULL
;
3938 uint32_t current_dosmode
;
3941 if (!VALID_STAT(fsp
->fsp_name
->st
)) {
3942 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
3945 dos_fsp
= metadata_fsp(fsp
);
3948 if (S_ISDIR(fsp
->fsp_name
->st
.st_ex_mode
)) {
3949 dosmode
|= FILE_ATTRIBUTE_DIRECTORY
;
3951 dosmode
&= ~FILE_ATTRIBUTE_DIRECTORY
;
3955 DBG_DEBUG("dosmode: 0x%" PRIx32
"\n", dosmode
);
3957 /* check the mode isn't different, before changing it */
3959 return NT_STATUS_OK
;
3961 current_dosmode
= fdos_mode(dos_fsp
);
3962 if (dosmode
== current_dosmode
) {
3963 return NT_STATUS_OK
;
3966 DBG_DEBUG("file %s : setting dos mode 0x%" PRIx32
"\n",
3967 fsp_str_dbg(dos_fsp
), dosmode
);
3969 ret
= file_set_dosmode(conn
, dos_fsp
->fsp_name
, dosmode
, NULL
, false);
3971 DBG_WARNING("file_set_dosmode of %s failed: %s\n",
3972 fsp_str_dbg(dos_fsp
), strerror(errno
));
3973 return map_nt_error_from_unix(errno
);
3976 return NT_STATUS_OK
;
3979 /****************************************************************************
3980 Deal with setting the size from any of the setfilepathinfo functions.
3981 ****************************************************************************/
3983 NTSTATUS
smb_set_file_size(connection_struct
*conn
,
3984 struct smb_request
*req
,
3986 struct smb_filename
*smb_fname
,
3987 const SMB_STRUCT_STAT
*psbuf
,
3989 bool fail_after_createfile
)
3991 NTSTATUS status
= NT_STATUS_OK
;
3992 files_struct
*new_fsp
= NULL
;
3994 if (!VALID_STAT(*psbuf
)) {
3995 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
3998 DBG_INFO("size: %"PRIu64
", file_size_stat=%"PRIu64
"\n",
4000 get_file_size_stat(psbuf
));
4002 if (size
== get_file_size_stat(psbuf
)) {
4004 return NT_STATUS_OK
;
4006 if (!fsp
->fsp_flags
.modified
) {
4007 return NT_STATUS_OK
;
4009 trigger_write_time_update_immediate(fsp
);
4010 return NT_STATUS_OK
;
4013 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
4014 smb_fname_str_dbg(smb_fname
), (double)size
));
4017 !fsp
->fsp_flags
.is_pathref
&&
4018 fsp_get_io_fd(fsp
) != -1)
4020 /* Handle based call. */
4021 status
= check_any_access_fsp(fsp
, FILE_WRITE_DATA
);
4022 if (!NT_STATUS_IS_OK(status
)) {
4026 if (vfs_set_filelen(fsp
, size
) == -1) {
4027 return map_nt_error_from_unix(errno
);
4029 trigger_write_time_update_immediate(fsp
);
4030 return NT_STATUS_OK
;
4033 status
= SMB_VFS_CREATE_FILE(
4037 smb_fname
, /* fname */
4038 FILE_WRITE_DATA
, /* access_mask */
4039 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
4041 FILE_OPEN
, /* create_disposition*/
4042 0, /* create_options */
4043 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
4044 0, /* oplock_request */
4046 0, /* allocation_size */
4047 0, /* private_flags */
4050 &new_fsp
, /* result */
4052 NULL
, NULL
); /* create context */
4054 if (!NT_STATUS_IS_OK(status
)) {
4055 /* NB. We check for open_was_deferred in the caller. */
4059 /* See RAW-SFILEINFO-END-OF-FILE */
4060 if (fail_after_createfile
) {
4061 close_file_free(req
, &new_fsp
, NORMAL_CLOSE
);
4062 return NT_STATUS_INVALID_LEVEL
;
4065 if (vfs_set_filelen(new_fsp
, size
) == -1) {
4066 status
= map_nt_error_from_unix(errno
);
4067 close_file_free(req
, &new_fsp
, NORMAL_CLOSE
);
4071 trigger_write_time_update_immediate(new_fsp
);
4072 close_file_free(req
, &new_fsp
, NORMAL_CLOSE
);
4073 return NT_STATUS_OK
;
4076 /****************************************************************************
4077 Deal with SMB_INFO_SET_EA.
4078 ****************************************************************************/
4080 static NTSTATUS
smb_info_set_ea(connection_struct
*conn
,
4084 struct smb_filename
*smb_fname
)
4086 struct ea_list
*ea_list
= NULL
;
4087 TALLOC_CTX
*ctx
= NULL
;
4088 NTSTATUS status
= NT_STATUS_OK
;
4090 if (total_data
< 10) {
4092 /* OS/2 workplace shell seems to send SET_EA requests of "null"
4093 length. They seem to have no effect. Bug #3212. JRA */
4095 if ((total_data
== 4) && (IVAL(pdata
,0) == 4)) {
4096 /* We're done. We only get EA info in this call. */
4097 return NT_STATUS_OK
;
4100 return NT_STATUS_INVALID_PARAMETER
;
4103 if (IVAL(pdata
,0) > total_data
) {
4104 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
4105 IVAL(pdata
,0), (unsigned int)total_data
));
4106 return NT_STATUS_INVALID_PARAMETER
;
4110 ea_list
= read_ea_list(ctx
, pdata
+ 4, total_data
- 4);
4112 return NT_STATUS_INVALID_PARAMETER
;
4117 * The only way fsp can be NULL here is if
4118 * smb_fname points at a symlink and
4119 * and we're in POSIX context.
4120 * Ensure this is the case.
4122 * In this case we cannot set the EA.
4124 SMB_ASSERT(smb_fname
->flags
& SMB_FILENAME_POSIX_PATH
);
4125 return NT_STATUS_ACCESS_DENIED
;
4128 status
= set_ea(conn
, fsp
, ea_list
);
4133 /****************************************************************************
4134 Deal with SMB_FILE_FULL_EA_INFORMATION set.
4135 ****************************************************************************/
4137 static NTSTATUS
smb_set_file_full_ea_info(connection_struct
*conn
,
4142 struct ea_list
*ea_list
= NULL
;
4146 return NT_STATUS_INVALID_HANDLE
;
4149 if (!lp_ea_support(SNUM(conn
))) {
4150 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
4151 "EA's not supported.\n",
4152 (unsigned int)total_data
));
4153 return NT_STATUS_EAS_NOT_SUPPORTED
;
4156 if (total_data
< 10) {
4157 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
4159 (unsigned int)total_data
));
4160 return NT_STATUS_INVALID_PARAMETER
;
4163 ea_list
= read_nttrans_ea_list(talloc_tos(),
4168 return NT_STATUS_INVALID_PARAMETER
;
4171 status
= set_ea(conn
, fsp
, ea_list
);
4173 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
4174 smb_fname_str_dbg(fsp
->fsp_name
),
4175 nt_errstr(status
) ));
4181 /****************************************************************************
4182 Deal with SMB_SET_FILE_DISPOSITION_INFO.
4183 ****************************************************************************/
4185 NTSTATUS
smb_set_file_disposition_info(connection_struct
*conn
,
4189 struct smb_filename
*smb_fname
)
4191 NTSTATUS status
= NT_STATUS_OK
;
4192 bool delete_on_close
;
4193 uint32_t dosmode
= 0;
4195 if (total_data
< 1) {
4196 return NT_STATUS_INVALID_PARAMETER
;
4200 return NT_STATUS_INVALID_HANDLE
;
4203 delete_on_close
= (CVAL(pdata
,0) ? True
: False
);
4204 dosmode
= fdos_mode(fsp
);
4206 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
4207 "delete_on_close = %u\n",
4208 smb_fname_str_dbg(smb_fname
),
4209 (unsigned int)dosmode
,
4210 (unsigned int)delete_on_close
));
4212 if (delete_on_close
) {
4213 status
= can_set_delete_on_close(fsp
, dosmode
);
4214 if (!NT_STATUS_IS_OK(status
)) {
4219 /* The set is across all open files on this dev/inode pair. */
4220 if (!set_delete_on_close(fsp
, delete_on_close
,
4221 conn
->session_info
->security_token
,
4222 conn
->session_info
->unix_token
)) {
4223 return NT_STATUS_ACCESS_DENIED
;
4225 return NT_STATUS_OK
;
4228 /****************************************************************************
4229 Deal with SMB_FILE_POSITION_INFORMATION.
4230 ****************************************************************************/
4232 static NTSTATUS
smb_file_position_information(connection_struct
*conn
,
4237 uint64_t position_information
;
4239 if (total_data
< 8) {
4240 return NT_STATUS_INVALID_PARAMETER
;
4244 /* Ignore on pathname based set. */
4245 return NT_STATUS_OK
;
4248 position_information
= (uint64_t)IVAL(pdata
,0);
4249 position_information
|= (((uint64_t)IVAL(pdata
,4)) << 32);
4251 DEBUG(10,("smb_file_position_information: Set file position "
4252 "information for file %s to %.0f\n", fsp_str_dbg(fsp
),
4253 (double)position_information
));
4254 fh_set_position_information(fsp
->fh
, position_information
);
4255 return NT_STATUS_OK
;
4258 /****************************************************************************
4259 Deal with SMB_FILE_MODE_INFORMATION.
4260 ****************************************************************************/
4262 static NTSTATUS
smb_file_mode_information(connection_struct
*conn
,
4268 if (total_data
< 4) {
4269 return NT_STATUS_INVALID_PARAMETER
;
4271 mode
= IVAL(pdata
,0);
4272 if (mode
!= 0 && mode
!= 2 && mode
!= 4 && mode
!= 6) {
4273 return NT_STATUS_INVALID_PARAMETER
;
4275 return NT_STATUS_OK
;
4278 /****************************************************************************
4279 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
4280 ****************************************************************************/
4282 static NTSTATUS
smb2_file_rename_information(connection_struct
*conn
,
4283 struct smb_request
*req
,
4287 struct smb_filename
*smb_fname_src
)
4291 char *newname
= NULL
;
4292 struct files_struct
*dst_dirfsp
= NULL
;
4293 struct smb_filename
*smb_fname_dst
= NULL
;
4294 const char *dst_original_lcomp
= NULL
;
4295 uint32_t ucf_flags
= ucf_flags_from_smb_request(req
);
4296 NTSTATUS status
= NT_STATUS_OK
;
4297 TALLOC_CTX
*ctx
= talloc_tos();
4300 return NT_STATUS_INVALID_HANDLE
;
4303 if (total_data
< 20) {
4304 return NT_STATUS_INVALID_PARAMETER
;
4307 overwrite
= (CVAL(pdata
,0) ? True
: False
);
4308 len
= IVAL(pdata
,16);
4310 if (len
> (total_data
- 20) || (len
== 0)) {
4311 return NT_STATUS_INVALID_PARAMETER
;
4314 (void)srvstr_pull_talloc(ctx
,
4322 if (newname
== NULL
) {
4323 return NT_STATUS_INVALID_PARAMETER
;
4326 /* SMB2 rename paths are never DFS. */
4327 req
->flags2
&= ~FLAGS2_DFS_PATHNAMES
;
4328 ucf_flags
&= ~UCF_DFS_PATHNAME
;
4330 status
= check_path_syntax(newname
,
4331 fsp
->fsp_name
->flags
& SMB_FILENAME_POSIX_PATH
);
4332 if (!NT_STATUS_IS_OK(status
)) {
4336 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
4339 if (newname
[0] == ':') {
4340 /* Create an smb_fname to call rename_internals_fsp() with. */
4341 smb_fname_dst
= synthetic_smb_fname(talloc_tos(),
4342 fsp
->base_fsp
->fsp_name
->base_name
,
4345 fsp
->base_fsp
->fsp_name
->twrp
,
4346 fsp
->base_fsp
->fsp_name
->flags
);
4347 if (smb_fname_dst
== NULL
) {
4348 status
= NT_STATUS_NO_MEMORY
;
4352 status
= filename_convert_dirfsp(ctx
,
4356 0, /* Never a TWRP. */
4359 if (!NT_STATUS_IS_OK(status
)) {
4365 * Set the original last component, since
4366 * rename_internals_fsp() requires it.
4368 dst_original_lcomp
= get_original_lcomp(smb_fname_dst
,
4372 if (dst_original_lcomp
== NULL
) {
4373 status
= NT_STATUS_NO_MEMORY
;
4377 DEBUG(10,("smb2_file_rename_information: "
4378 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
4379 fsp_fnum_dbg(fsp
), fsp_str_dbg(fsp
),
4380 smb_fname_str_dbg(smb_fname_dst
)));
4381 status
= rename_internals_fsp(conn
,
4385 (FILE_ATTRIBUTE_HIDDEN
|FILE_ATTRIBUTE_SYSTEM
),
4389 TALLOC_FREE(smb_fname_dst
);
4393 static NTSTATUS
smb2_file_link_information(connection_struct
*conn
,
4394 struct smb_request
*req
,
4398 struct smb_filename
*smb_fname_src
)
4402 char *newname
= NULL
;
4403 struct files_struct
*dst_dirfsp
= NULL
;
4404 struct smb_filename
*smb_fname_dst
= NULL
;
4405 NTSTATUS status
= NT_STATUS_OK
;
4406 uint32_t ucf_flags
= ucf_flags_from_smb_request(req
);
4408 TALLOC_CTX
*ctx
= talloc_tos();
4411 return NT_STATUS_INVALID_HANDLE
;
4414 if (total_data
< 20) {
4415 return NT_STATUS_INVALID_PARAMETER
;
4418 overwrite
= (CVAL(pdata
,0) ? true : false);
4419 len
= IVAL(pdata
,16);
4421 if (len
> (total_data
- 20) || (len
== 0)) {
4422 return NT_STATUS_INVALID_PARAMETER
;
4425 ret
= srvstr_pull_talloc(ctx
,
4433 if (ret
== (size_t)-1 || newname
== NULL
) {
4434 return NT_STATUS_INVALID_PARAMETER
;
4437 /* SMB2 hardlink paths are never DFS. */
4438 req
->flags2
&= ~FLAGS2_DFS_PATHNAMES
;
4439 ucf_flags
&= ~UCF_DFS_PATHNAME
;
4441 status
= check_path_syntax(newname
,
4442 fsp
->fsp_name
->flags
& SMB_FILENAME_POSIX_PATH
);
4443 if (!NT_STATUS_IS_OK(status
)) {
4447 DBG_DEBUG("got name |%s|\n", newname
);
4449 status
= filename_convert_dirfsp(ctx
,
4456 if (!NT_STATUS_IS_OK(status
)) {
4460 if (fsp
->base_fsp
) {
4461 /* No stream names. */
4462 return NT_STATUS_NOT_SUPPORTED
;
4465 DBG_DEBUG("SMB_FILE_LINK_INFORMATION (%s) %s -> %s\n",
4466 fsp_fnum_dbg(fsp
), fsp_str_dbg(fsp
),
4467 smb_fname_str_dbg(smb_fname_dst
));
4468 status
= hardlink_internals(ctx
,
4475 TALLOC_FREE(smb_fname_dst
);
4479 static NTSTATUS
smb_file_link_information(connection_struct
*conn
,
4480 struct smb_request
*req
,
4484 struct smb_filename
*smb_fname_src
)
4488 char *newname
= NULL
;
4489 struct files_struct
*dst_dirfsp
= NULL
;
4490 struct smb_filename
*smb_fname_dst
= NULL
;
4491 NTSTATUS status
= NT_STATUS_OK
;
4492 uint32_t ucf_flags
= ucf_flags_from_smb_request(req
);
4493 NTTIME dst_twrp
= 0;
4494 TALLOC_CTX
*ctx
= talloc_tos();
4497 return NT_STATUS_INVALID_HANDLE
;
4500 if (total_data
< 20) {
4501 return NT_STATUS_INVALID_PARAMETER
;
4504 overwrite
= (CVAL(pdata
,0) ? true : false);
4505 len
= IVAL(pdata
,16);
4507 if (len
> (total_data
- 20) || (len
== 0)) {
4508 return NT_STATUS_INVALID_PARAMETER
;
4511 if (smb_fname_src
->flags
& SMB_FILENAME_POSIX_PATH
) {
4512 srvstr_get_path_posix(ctx
,
4520 ucf_flags
|= UCF_POSIX_PATHNAMES
;
4522 srvstr_get_path(ctx
,
4531 if (!NT_STATUS_IS_OK(status
)) {
4535 DEBUG(10,("smb_file_link_information: got name |%s|\n",
4538 if (ucf_flags
& UCF_GMT_PATHNAME
) {
4539 extract_snapshot_token(newname
, &dst_twrp
);
4541 /* hardlink paths are never DFS. */
4542 ucf_flags
&= ~UCF_DFS_PATHNAME
;
4544 status
= filename_convert_dirfsp(ctx
,
4551 if (!NT_STATUS_IS_OK(status
)) {
4555 if (fsp
->base_fsp
) {
4556 /* No stream names. */
4557 return NT_STATUS_NOT_SUPPORTED
;
4560 DEBUG(10,("smb_file_link_information: "
4561 "SMB_FILE_LINK_INFORMATION (%s) %s -> %s\n",
4562 fsp_fnum_dbg(fsp
), fsp_str_dbg(fsp
),
4563 smb_fname_str_dbg(smb_fname_dst
)));
4564 status
= hardlink_internals(ctx
,
4571 TALLOC_FREE(smb_fname_dst
);
4576 /****************************************************************************
4577 Deal with SMB_FILE_RENAME_INFORMATION.
4578 ****************************************************************************/
4580 static NTSTATUS
smb_file_rename_information(connection_struct
*conn
,
4581 struct smb_request
*req
,
4585 struct smb_filename
*smb_fname_src
)
4590 char *newname
= NULL
;
4591 struct files_struct
*dst_dirfsp
= NULL
;
4592 struct smb_filename
*smb_fname_dst
= NULL
;
4593 const char *dst_original_lcomp
= NULL
;
4594 NTSTATUS status
= NT_STATUS_OK
;
4596 TALLOC_CTX
*ctx
= talloc_tos();
4598 if (total_data
< 13) {
4599 return NT_STATUS_INVALID_PARAMETER
;
4602 overwrite
= (CVAL(pdata
,0) != 0);
4603 root_fid
= IVAL(pdata
,4);
4604 len
= IVAL(pdata
,8);
4606 if (len
> (total_data
- 12) || (len
== 0) || (root_fid
!= 0)) {
4607 return NT_STATUS_INVALID_PARAMETER
;
4610 if (req
->posix_pathnames
) {
4611 srvstr_get_path_posix(ctx
,
4620 srvstr_get_path(ctx
,
4629 if (!NT_STATUS_IS_OK(status
)) {
4633 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
4636 /* Check the new name has no '/' characters. */
4637 if (strchr_m(newname
, '/')) {
4638 return NT_STATUS_NOT_SUPPORTED
;
4641 if (fsp
&& fsp
->base_fsp
) {
4642 /* newname must be a stream name. */
4643 if (newname
[0] != ':') {
4644 return NT_STATUS_NOT_SUPPORTED
;
4647 /* Create an smb_fname to call rename_internals_fsp() with. */
4648 smb_fname_dst
= synthetic_smb_fname(talloc_tos(),
4649 fsp
->base_fsp
->fsp_name
->base_name
,
4652 fsp
->base_fsp
->fsp_name
->twrp
,
4653 fsp
->base_fsp
->fsp_name
->flags
);
4654 if (smb_fname_dst
== NULL
) {
4655 status
= NT_STATUS_NO_MEMORY
;
4660 * Get the original last component, since
4661 * rename_internals_fsp() requires it.
4663 dst_original_lcomp
= get_original_lcomp(smb_fname_dst
,
4667 if (dst_original_lcomp
== NULL
) {
4668 status
= NT_STATUS_NO_MEMORY
;
4674 * Build up an smb_fname_dst based on the filename passed in.
4675 * We basically just strip off the last component, and put on
4676 * the newname instead.
4678 char *base_name
= NULL
;
4679 uint32_t ucf_flags
= ucf_flags_from_smb_request(req
);
4680 NTTIME dst_twrp
= 0;
4682 /* newname must *not* be a stream name. */
4683 if (newname
[0] == ':') {
4684 return NT_STATUS_NOT_SUPPORTED
;
4688 * Strip off the last component (filename) of the path passed
4691 base_name
= talloc_strdup(ctx
, smb_fname_src
->base_name
);
4693 return NT_STATUS_NO_MEMORY
;
4695 p
= strrchr_m(base_name
, '/');
4699 base_name
= talloc_strdup(ctx
, "");
4701 return NT_STATUS_NO_MEMORY
;
4704 /* Append the new name. */
4705 base_name
= talloc_asprintf_append(base_name
,
4709 return NT_STATUS_NO_MEMORY
;
4712 if (ucf_flags
& UCF_GMT_PATHNAME
) {
4713 extract_snapshot_token(base_name
, &dst_twrp
);
4716 /* The newname is *not* a DFS path. */
4717 ucf_flags
&= ~UCF_DFS_PATHNAME
;
4719 status
= filename_convert_dirfsp(ctx
,
4727 if (!NT_STATUS_IS_OK(status
)) {
4730 dst_original_lcomp
= get_original_lcomp(smb_fname_dst
,
4734 if (dst_original_lcomp
== NULL
) {
4735 status
= NT_STATUS_NO_MEMORY
;
4740 if (fsp
!= NULL
&& fsp
->fsp_flags
.is_fsa
) {
4741 DEBUG(10,("smb_file_rename_information: "
4742 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
4743 fsp_fnum_dbg(fsp
), fsp_str_dbg(fsp
),
4744 smb_fname_str_dbg(smb_fname_dst
)));
4745 status
= rename_internals_fsp(conn
,
4752 DEBUG(10,("smb_file_rename_information: "
4753 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
4754 smb_fname_str_dbg(smb_fname_src
),
4755 smb_fname_str_dbg(smb_fname_dst
)));
4756 status
= rename_internals(ctx
,
4759 NULL
, /* src_dirfsp */
4765 FILE_WRITE_ATTRIBUTES
);
4768 TALLOC_FREE(smb_fname_dst
);
4772 /****************************************************************************
4773 Deal with SMB_SET_FILE_BASIC_INFO.
4774 ****************************************************************************/
4776 static NTSTATUS
smb_set_file_basic_info(connection_struct
*conn
,
4780 struct smb_filename
*smb_fname
)
4782 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
4783 struct smb_file_time ft
;
4784 uint32_t dosmode
= 0;
4785 NTSTATUS status
= NT_STATUS_OK
;
4787 init_smb_file_time(&ft
);
4789 if (total_data
< 36) {
4790 return NT_STATUS_INVALID_PARAMETER
;
4794 return NT_STATUS_INVALID_HANDLE
;
4797 status
= check_any_access_fsp(fsp
, FILE_WRITE_ATTRIBUTES
);
4798 if (!NT_STATUS_IS_OK(status
)) {
4802 /* Set the attributes */
4803 dosmode
= IVAL(pdata
,32);
4804 status
= smb_set_file_dosmode(conn
, fsp
, dosmode
);
4805 if (!NT_STATUS_IS_OK(status
)) {
4810 ft
.create_time
= pull_long_date_full_timespec(pdata
);
4813 ft
.atime
= pull_long_date_full_timespec(pdata
+8);
4816 ft
.mtime
= pull_long_date_full_timespec(pdata
+16);
4819 ft
.ctime
= pull_long_date_full_timespec(pdata
+24);
4821 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
4822 smb_fname_str_dbg(smb_fname
)));
4824 status
= smb_set_file_time(conn
, fsp
, smb_fname
, &ft
, true);
4825 if (!NT_STATUS_IS_OK(status
)) {
4829 if (fsp
->fsp_flags
.modified
) {
4830 trigger_write_time_update_immediate(fsp
);
4832 return NT_STATUS_OK
;
4835 /****************************************************************************
4836 Deal with SMB_INFO_STANDARD.
4837 ****************************************************************************/
4839 static NTSTATUS
smb_set_info_standard(connection_struct
*conn
,
4843 struct smb_filename
*smb_fname
)
4846 struct smb_file_time ft
;
4848 init_smb_file_time(&ft
);
4850 if (total_data
< 12) {
4851 return NT_STATUS_INVALID_PARAMETER
;
4855 return NT_STATUS_INVALID_HANDLE
;
4859 ft
.create_time
= time_t_to_full_timespec(srv_make_unix_date2(pdata
));
4861 ft
.atime
= time_t_to_full_timespec(srv_make_unix_date2(pdata
+4));
4863 ft
.mtime
= time_t_to_full_timespec(srv_make_unix_date2(pdata
+8));
4865 DEBUG(10,("smb_set_info_standard: file %s\n",
4866 smb_fname_str_dbg(smb_fname
)));
4868 status
= check_any_access_fsp(fsp
, FILE_WRITE_ATTRIBUTES
);
4869 if (!NT_STATUS_IS_OK(status
)) {
4873 status
= smb_set_file_time(conn
, fsp
, smb_fname
, &ft
, true);
4874 if (!NT_STATUS_IS_OK(status
)) {
4878 if (fsp
->fsp_flags
.modified
) {
4879 trigger_write_time_update_immediate(fsp
);
4881 return NT_STATUS_OK
;
4884 /****************************************************************************
4885 Deal with SMB_SET_FILE_ALLOCATION_INFO.
4886 ****************************************************************************/
4888 static NTSTATUS
smb_set_file_allocation_info(connection_struct
*conn
,
4889 struct smb_request
*req
,
4893 struct smb_filename
*smb_fname
)
4895 uint64_t allocation_size
= 0;
4896 NTSTATUS status
= NT_STATUS_OK
;
4897 files_struct
*new_fsp
= NULL
;
4899 if (!VALID_STAT(smb_fname
->st
)) {
4900 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
4903 if (total_data
< 8) {
4904 return NT_STATUS_INVALID_PARAMETER
;
4907 allocation_size
= (uint64_t)IVAL(pdata
,0);
4908 allocation_size
|= (((uint64_t)IVAL(pdata
,4)) << 32);
4909 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
4910 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname
),
4911 (double)allocation_size
));
4913 if (allocation_size
) {
4914 allocation_size
= smb_roundup(conn
, allocation_size
);
4917 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
4918 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname
),
4919 (double)allocation_size
));
4922 !fsp
->fsp_flags
.is_pathref
&&
4923 fsp_get_io_fd(fsp
) != -1)
4925 /* Open file handle. */
4926 status
= check_any_access_fsp(fsp
, FILE_WRITE_DATA
);
4927 if (!NT_STATUS_IS_OK(status
)) {
4931 /* Only change if needed. */
4932 if (allocation_size
!= get_file_size_stat(&smb_fname
->st
)) {
4933 if (vfs_allocate_file_space(fsp
, allocation_size
) == -1) {
4934 return map_nt_error_from_unix(errno
);
4937 /* But always update the time. */
4939 * This is equivalent to a write. Ensure it's seen immediately
4940 * if there are no pending writes.
4942 trigger_write_time_update_immediate(fsp
);
4943 return NT_STATUS_OK
;
4946 /* Pathname or stat or directory file. */
4947 status
= SMB_VFS_CREATE_FILE(
4951 smb_fname
, /* fname */
4952 FILE_WRITE_DATA
, /* access_mask */
4953 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
4955 FILE_OPEN
, /* create_disposition*/
4956 0, /* create_options */
4957 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
4958 0, /* oplock_request */
4960 0, /* allocation_size */
4961 0, /* private_flags */
4964 &new_fsp
, /* result */
4966 NULL
, NULL
); /* create context */
4968 if (!NT_STATUS_IS_OK(status
)) {
4969 /* NB. We check for open_was_deferred in the caller. */
4973 /* Only change if needed. */
4974 if (allocation_size
!= get_file_size_stat(&smb_fname
->st
)) {
4975 if (vfs_allocate_file_space(new_fsp
, allocation_size
) == -1) {
4976 status
= map_nt_error_from_unix(errno
);
4977 close_file_free(req
, &new_fsp
, NORMAL_CLOSE
);
4982 /* Changing the allocation size should set the last mod time. */
4984 * This is equivalent to a write. Ensure it's seen immediately
4985 * if there are no pending writes.
4987 trigger_write_time_update_immediate(new_fsp
);
4988 close_file_free(req
, &new_fsp
, NORMAL_CLOSE
);
4989 return NT_STATUS_OK
;
4992 /****************************************************************************
4993 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
4994 ****************************************************************************/
4996 static NTSTATUS
smb_set_file_end_of_file_info(connection_struct
*conn
,
4997 struct smb_request
*req
,
5001 struct smb_filename
*smb_fname
,
5002 bool fail_after_createfile
)
5006 if (total_data
< 8) {
5007 return NT_STATUS_INVALID_PARAMETER
;
5010 size
= IVAL(pdata
,0);
5011 size
|= (((off_t
)IVAL(pdata
,4)) << 32);
5012 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
5013 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname
),
5016 return smb_set_file_size(conn
, req
,
5021 fail_after_createfile
);
5024 NTSTATUS
smbd_do_setfilepathinfo(connection_struct
*conn
,
5025 struct smb_request
*req
,
5026 TALLOC_CTX
*mem_ctx
,
5027 uint16_t info_level
,
5029 struct smb_filename
*smb_fname
,
5030 char **ppdata
, int total_data
,
5033 char *pdata
= *ppdata
;
5034 NTSTATUS status
= NT_STATUS_OK
;
5035 int data_return_size
= 0;
5039 DEBUG(3,("smbd_do_setfilepathinfo: %s (%s) info_level=%d "
5040 "totdata=%d\n", smb_fname_str_dbg(smb_fname
),
5042 info_level
, total_data
));
5044 switch (info_level
) {
5046 case SMB_INFO_STANDARD
:
5048 status
= smb_set_info_standard(conn
,
5056 case SMB_INFO_SET_EA
:
5058 status
= smb_info_set_ea(conn
,
5066 case SMB_SET_FILE_BASIC_INFO
:
5067 case SMB_FILE_BASIC_INFORMATION
:
5069 status
= smb_set_file_basic_info(conn
,
5077 case SMB_FILE_ALLOCATION_INFORMATION
:
5078 case SMB_SET_FILE_ALLOCATION_INFO
:
5080 status
= smb_set_file_allocation_info(conn
, req
,
5088 case SMB_FILE_END_OF_FILE_INFORMATION
:
5089 case SMB_SET_FILE_END_OF_FILE_INFO
:
5092 * XP/Win7 both fail after the createfile with
5093 * SMB_SET_FILE_END_OF_FILE_INFO but not
5094 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
5095 * The level is known here, so pass it down
5099 (info_level
== SMB_SET_FILE_END_OF_FILE_INFO
);
5101 status
= smb_set_file_end_of_file_info(conn
, req
,
5110 case SMB_FILE_DISPOSITION_INFORMATION
:
5111 case SMB_SET_FILE_DISPOSITION_INFO
: /* Set delete on close for open file. */
5114 /* JRA - We used to just ignore this on a path ?
5115 * Shouldn't this be invalid level on a pathname
5118 if (tran_call
!= TRANSACT2_SETFILEINFO
) {
5119 return ERROR_NT(NT_STATUS_INVALID_LEVEL
);
5122 status
= smb_set_file_disposition_info(conn
,
5130 case SMB_FILE_POSITION_INFORMATION
:
5132 status
= smb_file_position_information(conn
,
5139 case SMB_FILE_FULL_EA_INFORMATION
:
5141 status
= smb_set_file_full_ea_info(conn
,
5148 /* From tridge Samba4 :
5149 * MODE_INFORMATION in setfileinfo (I have no
5150 * idea what "mode information" on a file is - it takes a value of 0,
5151 * 2, 4 or 6. What could it be?).
5154 case SMB_FILE_MODE_INFORMATION
:
5156 status
= smb_file_mode_information(conn
,
5162 /* [MS-SMB2] 3.3.5.21.1 states we MUST fail with STATUS_NOT_SUPPORTED. */
5163 case SMB_FILE_VALID_DATA_LENGTH_INFORMATION
:
5164 case SMB_FILE_SHORT_NAME_INFORMATION
:
5165 return NT_STATUS_NOT_SUPPORTED
;
5167 case SMB_FILE_RENAME_INFORMATION
:
5169 status
= smb_file_rename_information(conn
, req
,
5175 case SMB2_FILE_RENAME_INFORMATION_INTERNAL
:
5177 /* SMB2 rename information. */
5178 status
= smb2_file_rename_information(conn
, req
,
5184 case SMB_FILE_LINK_INFORMATION
:
5186 if (conn
->sconn
->using_smb2
) {
5187 status
= smb2_file_link_information(conn
,
5194 status
= smb_file_link_information(conn
,
5205 return NT_STATUS_INVALID_LEVEL
;
5208 if (!NT_STATUS_IS_OK(status
)) {
5212 *ret_data_size
= data_return_size
;
5213 return NT_STATUS_OK
;
5216 static uint32_t generate_volume_serial_number(
5217 const struct loadparm_substitution
*lp_sub
,
5220 int serial
= lp_volume_serial_number(snum
);
5221 return serial
!= -1 ? serial
:
5222 str_checksum(lp_servicename(talloc_tos(), lp_sub
, snum
)) ^
5223 (str_checksum(get_local_machine_name())<<16);