2 Unix SMB/CIFS implementation.
3 SMB transaction2 handling
4 Copyright (C) Jeremy Allison 1994-2007
5 Copyright (C) Stefan (metze) Metzmacher 2003
6 Copyright (C) Volker Lendecke 2005-2007
7 Copyright (C) Steve French 2005
8 Copyright (C) James Peach 2006-2007
10 Extensively modified by Andrew Tridgell, 1995
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 3 of the License, or
15 (at your option) any later version.
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with this program. If not, see <http://www.gnu.org/licenses/>.
28 #include "system/filesys.h"
29 #include "lib/util/time_basic.h"
31 #include "smbd/smbd.h"
32 #include "smbd/globals.h"
33 #include "../libcli/auth/libcli_auth.h"
34 #include "../librpc/gen_ndr/xattr.h"
35 #include "../librpc/gen_ndr/ndr_security.h"
36 #include "libcli/security/security.h"
39 #include "smbprofile.h"
40 #include "rpc_server/srv_pipe_hnd.h"
42 #include "lib/util_ea.h"
43 #include "lib/readdir_attr.h"
45 #include "libcli/smb/smb2_posix.h"
46 #include "lib/util/string_wrappers.h"
47 #include "source3/lib/substitute.h"
48 #include "source3/lib/adouble.h"
50 #define DIR_ENTRY_SAFETY_MARGIN 4096
52 static uint32_t generate_volume_serial_number(
53 const struct loadparm_substitution
*lp_sub
,
56 /****************************************************************************
57 Check if an open file handle is a symlink.
58 ****************************************************************************/
60 NTSTATUS
refuse_symlink_fsp(const files_struct
*fsp
)
63 if (!VALID_STAT(fsp
->fsp_name
->st
)) {
64 return NT_STATUS_ACCESS_DENIED
;
66 if (S_ISLNK(fsp
->fsp_name
->st
.st_ex_mode
)) {
67 return NT_STATUS_ACCESS_DENIED
;
69 if (fsp_get_pathref_fd(fsp
) == -1) {
70 return NT_STATUS_ACCESS_DENIED
;
76 * Check that one or more of the rights in access mask are
77 * allowed. Iow, access_requested can contain more then one right and
78 * it is sufficient having only one of those granted to pass.
80 NTSTATUS
check_any_access_fsp(struct files_struct
*fsp
,
81 uint32_t access_requested
)
83 const uint32_t ro_access
= SEC_RIGHTS_FILE_READ
| SEC_FILE_EXECUTE
;
84 uint32_t ro_access_granted
= 0;
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
)) {
105 access_granted
|= mask
;
106 if (fsp
->fsp_name
->twrp
== 0) {
108 * We can only optimize
109 * the non-snapshot case
117 if ((access_granted
& access_requested
) == 0) {
118 return NT_STATUS_ACCESS_DENIED
;
121 if (fsp
->fsp_name
->twrp
== 0) {
125 ro_access_granted
= access_granted
& ro_access
;
126 if ((ro_access_granted
& access_requested
) == 0) {
127 return NT_STATUS_MEDIA_WRITE_PROTECTED
;
133 /********************************************************************
134 Roundup a value to the nearest allocation roundup size boundary.
135 Only do this for Windows clients.
136 ********************************************************************/
138 uint64_t smb_roundup(connection_struct
*conn
, uint64_t val
)
140 uint64_t rval
= lp_allocation_roundup_size(SNUM(conn
));
142 /* Only roundup for Windows clients. */
143 enum remote_arch_types ra_type
= get_remote_arch();
144 if (rval
&& (ra_type
!= RA_SAMBA
) && (ra_type
!= RA_CIFSFS
)) {
145 val
= SMB_ROUNDUP(val
,rval
);
150 /****************************************************************************
151 Utility functions for dealing with extended attributes.
152 ****************************************************************************/
154 /****************************************************************************
155 Refuse to allow clients to overwrite our private xattrs.
156 ****************************************************************************/
158 bool samba_private_attr_name(const char *unix_ea_name
)
160 bool prohibited
= false;
162 prohibited
|= strequal(unix_ea_name
, SAMBA_POSIX_INHERITANCE_EA_NAME
);
163 prohibited
|= strequal(unix_ea_name
, SAMBA_XATTR_DOS_ATTRIB
);
164 prohibited
|= strequal(unix_ea_name
, SAMBA_XATTR_MARKER
);
165 prohibited
|= strequal(unix_ea_name
, XATTR_NTACL_NAME
);
166 prohibited
|= strequal(unix_ea_name
, AFPINFO_EA_NETATALK
);
172 if (strncasecmp_m(unix_ea_name
, SAMBA_XATTR_DOSSTREAM_PREFIX
,
173 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX
)) == 0) {
179 /****************************************************************************
180 Get one EA value. Fill in a struct ea_struct.
181 ****************************************************************************/
183 NTSTATUS
get_ea_value_fsp(TALLOC_CTX
*mem_ctx
,
186 struct ea_struct
*pea
)
188 /* Get the value of this xattr. Max size is 64k. */
189 size_t attr_size
= 256;
192 size_t max_xattr_size
= 0;
195 return NT_STATUS_INVALID_HANDLE
;
198 max_xattr_size
= lp_smbd_max_xattr_size(SNUM(fsp
->conn
));
202 val
= talloc_realloc(mem_ctx
, val
, char, attr_size
);
204 return NT_STATUS_NO_MEMORY
;
207 sizeret
= SMB_VFS_FGETXATTR(fsp
, ea_name
, val
, attr_size
);
208 if (sizeret
== -1 && errno
== ERANGE
&& attr_size
< max_xattr_size
) {
209 attr_size
= max_xattr_size
;
214 return map_nt_error_from_unix(errno
);
217 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name
, (unsigned int)sizeret
));
218 dump_data(10, (uint8_t *)val
, sizeret
);
221 if (strnequal(ea_name
, "user.", 5)) {
222 pea
->name
= talloc_strdup(mem_ctx
, &ea_name
[5]);
224 pea
->name
= talloc_strdup(mem_ctx
, ea_name
);
226 if (pea
->name
== NULL
) {
228 return NT_STATUS_NO_MEMORY
;
230 pea
->value
.data
= (unsigned char *)val
;
231 pea
->value
.length
= (size_t)sizeret
;
235 NTSTATUS
get_ea_names_from_fsp(TALLOC_CTX
*mem_ctx
,
241 /* Get a list of all xattrs. Max namesize is 64k. */
242 size_t ea_namelist_size
= 1024;
243 char *ea_namelist
= smallbuf
;
244 char *to_free
= NULL
;
249 ssize_t sizeret
= -1;
259 * Callers may pass fsp == NULL when passing smb_fname->fsp of a
260 * symlink. This is ok, handle it here, by just return no EA's
266 /* should be the case that fsp != NULL */
267 SMB_ASSERT(fsp
!= NULL
);
269 sizeret
= SMB_VFS_FLISTXATTR(fsp
, ea_namelist
,
272 if ((sizeret
== -1) && (errno
== ERANGE
)) {
273 ea_namelist_size
= 65536;
274 ea_namelist
= talloc_array(mem_ctx
, char, ea_namelist_size
);
275 if (ea_namelist
== NULL
) {
276 return NT_STATUS_NO_MEMORY
;
278 to_free
= ea_namelist
;
280 sizeret
= SMB_VFS_FLISTXATTR(fsp
, ea_namelist
,
285 status
= map_nt_error_from_unix(errno
);
286 TALLOC_FREE(to_free
);
290 DBG_DEBUG("ea_namelist size = %zd\n", sizeret
);
293 TALLOC_FREE(to_free
);
298 * Ensure the result is 0-terminated
301 if (ea_namelist
[sizeret
-1] != '\0') {
302 TALLOC_FREE(to_free
);
303 return NT_STATUS_INTERNAL_ERROR
;
311 for (p
= ea_namelist
; p
- ea_namelist
< sizeret
; p
+= strlen(p
)+1) {
315 *pnum_names
= num_names
;
317 if (pnames
== NULL
) {
318 TALLOC_FREE(to_free
);
322 names
= talloc_array(mem_ctx
, char *, num_names
);
324 DEBUG(0, ("talloc failed\n"));
325 TALLOC_FREE(to_free
);
326 return NT_STATUS_NO_MEMORY
;
329 if (ea_namelist
== smallbuf
) {
330 ea_namelist
= talloc_memdup(names
, smallbuf
, sizeret
);
331 if (ea_namelist
== NULL
) {
333 return NT_STATUS_NO_MEMORY
;
336 talloc_steal(names
, ea_namelist
);
338 ea_namelist
= talloc_realloc(names
, ea_namelist
, char,
340 if (ea_namelist
== NULL
) {
342 return NT_STATUS_NO_MEMORY
;
348 for (p
= ea_namelist
; p
- ea_namelist
< sizeret
; p
+= strlen(p
)+1) {
349 names
[num_names
++] = p
;
357 /****************************************************************************
358 Return a linked list of the total EA's. Plus the total size
359 ****************************************************************************/
361 static NTSTATUS
get_ea_list_from_fsp(TALLOC_CTX
*mem_ctx
,
363 size_t *pea_total_len
,
364 struct ea_list
**ea_list
)
366 /* Get a list of all xattrs. Max namesize is 64k. */
369 struct ea_list
*ea_list_head
= NULL
;
370 bool posix_pathnames
= false;
381 if (!lp_ea_support(SNUM(fsp
->conn
))) {
385 if (fsp_is_alternate_stream(fsp
)) {
386 return NT_STATUS_INVALID_PARAMETER
;
389 posix_pathnames
= (fsp
->fsp_name
->flags
& SMB_FILENAME_POSIX_PATH
);
391 status
= get_ea_names_from_fsp(talloc_tos(),
396 if (!NT_STATUS_IS_OK(status
)) {
400 if (num_names
== 0) {
404 for (i
=0; i
<num_names
; i
++) {
405 struct ea_list
*listp
;
409 * POSIX EA names are divided into several namespaces by
410 * means of string prefixes. Usually, the system controls
411 * semantics for each namespace, but the 'user' namespace is
412 * available for arbitrary use, which comes closest to
413 * Windows EA semantics. Hence, we map POSIX EAs from the
414 * 'user' namespace to Windows EAs, and just ignore all the
415 * other namespaces. Also, a few specific names in the 'user'
416 * namespace are used by Samba internally. Filter them out as
417 * well, and only present the EAs that are available for
420 if (!strnequal(names
[i
], "user.", 5)
421 || samba_private_attr_name(names
[i
]))
425 * Filter out any underlying POSIX EA names
426 * that a Windows client can't handle.
428 if (!posix_pathnames
&&
429 is_invalid_windows_ea_name(names
[i
])) {
433 listp
= talloc(mem_ctx
, struct ea_list
);
435 return NT_STATUS_NO_MEMORY
;
438 status
= get_ea_value_fsp(listp
,
443 if (!NT_STATUS_IS_OK(status
)) {
448 if (listp
->ea
.value
.length
== 0) {
450 * We can never return a zero length EA.
451 * Windows reports the EA's as corrupted.
455 } else if (listp
->ea
.value
.length
> 65536) {
457 * SMB clients may report error with file
458 * if large EA is presented to them.
460 DBG_ERR("EA [%s] on file [%s] exceeds "
461 "maximum permitted EA size of 64KiB: %zu\n.",
462 listp
->ea
.name
, fsp_str_dbg(fsp
),
463 listp
->ea
.value
.length
);
468 push_ascii_fstring(dos_ea_name
, listp
->ea
.name
);
471 4 + strlen(dos_ea_name
) + 1 + listp
->ea
.value
.length
;
473 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
474 "= %u\n", (unsigned int)*pea_total_len
, dos_ea_name
,
475 (unsigned int)listp
->ea
.value
.length
));
477 DLIST_ADD_END(ea_list_head
, listp
);
481 /* Add on 4 for total length. */
482 if (*pea_total_len
) {
486 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
487 (unsigned int)*pea_total_len
));
489 *ea_list
= ea_list_head
;
493 /****************************************************************************
494 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
496 ****************************************************************************/
498 static unsigned int fill_ea_buffer(TALLOC_CTX
*mem_ctx
, char *pdata
, unsigned int total_data_size
,
499 connection_struct
*conn
, struct ea_list
*ea_list
)
501 unsigned int ret_data_size
= 4;
504 SMB_ASSERT(total_data_size
>= 4);
506 if (!lp_ea_support(SNUM(conn
))) {
511 for (p
= pdata
+ 4; ea_list
; ea_list
= ea_list
->next
) {
514 push_ascii_fstring(dos_ea_name
, ea_list
->ea
.name
);
515 dos_namelen
= strlen(dos_ea_name
);
516 if (dos_namelen
> 255 || dos_namelen
== 0) {
519 if (ea_list
->ea
.value
.length
> 65535) {
522 if (4 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
> total_data_size
) {
526 /* We know we have room. */
527 SCVAL(p
,0,ea_list
->ea
.flags
);
528 SCVAL(p
,1,dos_namelen
);
529 SSVAL(p
,2,ea_list
->ea
.value
.length
);
530 strlcpy(p
+4, dos_ea_name
, dos_namelen
+1);
531 if (ea_list
->ea
.value
.length
> 0) {
532 memcpy(p
+ 4 + dos_namelen
+ 1,
533 ea_list
->ea
.value
.data
,
534 ea_list
->ea
.value
.length
);
537 total_data_size
-= 4 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
;
538 p
+= 4 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
;
541 ret_data_size
= PTR_DIFF(p
, pdata
);
542 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size
));
543 SIVAL(pdata
,0,ret_data_size
);
544 return ret_data_size
;
547 static NTSTATUS
fill_ea_chained_buffer(TALLOC_CTX
*mem_ctx
,
549 unsigned int total_data_size
,
550 unsigned int *ret_data_size
,
551 connection_struct
*conn
,
552 struct ea_list
*ea_list
)
554 uint8_t *p
= (uint8_t *)pdata
;
555 uint8_t *last_start
= NULL
;
556 bool do_store_data
= (pdata
!= NULL
);
560 if (!lp_ea_support(SNUM(conn
))) {
561 return NT_STATUS_NO_EAS_ON_FILE
;
564 for (; ea_list
; ea_list
= ea_list
->next
) {
570 if (last_start
!= NULL
&& do_store_data
) {
571 SIVAL(last_start
, 0, PTR_DIFF(p
, last_start
));
575 push_ascii_fstring(dos_ea_name
, ea_list
->ea
.name
);
576 dos_namelen
= strlen(dos_ea_name
);
577 if (dos_namelen
> 255 || dos_namelen
== 0) {
578 return NT_STATUS_INTERNAL_ERROR
;
580 if (ea_list
->ea
.value
.length
> 65535) {
581 return NT_STATUS_INTERNAL_ERROR
;
584 this_size
= 0x08 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
;
587 pad
= (4 - (this_size
% 4)) % 4;
592 if (this_size
> total_data_size
) {
593 return NT_STATUS_INFO_LENGTH_MISMATCH
;
596 /* We know we have room. */
597 SIVAL(p
, 0x00, 0); /* next offset */
598 SCVAL(p
, 0x04, ea_list
->ea
.flags
);
599 SCVAL(p
, 0x05, dos_namelen
);
600 SSVAL(p
, 0x06, ea_list
->ea
.value
.length
);
601 strlcpy((char *)(p
+0x08), dos_ea_name
, dos_namelen
+1);
602 memcpy(p
+ 0x08 + dos_namelen
+ 1, ea_list
->ea
.value
.data
, ea_list
->ea
.value
.length
);
604 memset(p
+ 0x08 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
,
608 total_data_size
-= this_size
;
614 *ret_data_size
= PTR_DIFF(p
, pdata
);
615 DEBUG(10,("fill_ea_chained_buffer: data_size = %u\n", *ret_data_size
));
619 unsigned int estimate_ea_size(files_struct
*fsp
)
621 size_t total_ea_len
= 0;
623 struct ea_list
*ea_list
= NULL
;
631 if (!lp_ea_support(SNUM(fsp
->conn
))) {
635 mem_ctx
= talloc_stackframe();
637 /* If this is a stream fsp, then we need to instead find the
638 * estimated ea len from the main file, not the stream
639 * (streams cannot have EAs), but the estimate isn't just 0 in
641 fsp
= metadata_fsp(fsp
);
642 (void)get_ea_list_from_fsp(mem_ctx
,
647 if(fsp
->conn
->sconn
->using_smb2
) {
648 unsigned int ret_data_size
;
650 * We're going to be using fill_ea_chained_buffer() to
651 * marshall EA's - this size is significantly larger
652 * than the SMB1 buffer. Re-calculate the size without
655 status
= fill_ea_chained_buffer(mem_ctx
,
661 if (!NT_STATUS_IS_OK(status
)) {
664 total_ea_len
= ret_data_size
;
666 TALLOC_FREE(mem_ctx
);
670 /****************************************************************************
671 Ensure the EA name is case insensitive by matching any existing EA name.
672 ****************************************************************************/
674 static void canonicalize_ea_name(files_struct
*fsp
,
675 fstring unix_ea_name
)
678 TALLOC_CTX
*mem_ctx
= talloc_tos();
679 struct ea_list
*ea_list
;
680 NTSTATUS status
= get_ea_list_from_fsp(mem_ctx
,
684 if (!NT_STATUS_IS_OK(status
)) {
688 for (; ea_list
; ea_list
= ea_list
->next
) {
689 if (strequal(&unix_ea_name
[5], ea_list
->ea
.name
)) {
690 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
691 &unix_ea_name
[5], ea_list
->ea
.name
));
692 strlcpy(&unix_ea_name
[5], ea_list
->ea
.name
, sizeof(fstring
)-5);
698 /****************************************************************************
699 Set or delete an extended attribute.
700 ****************************************************************************/
702 NTSTATUS
set_ea(connection_struct
*conn
, files_struct
*fsp
,
703 struct ea_list
*ea_list
)
706 bool posix_pathnames
= false;
708 if (!lp_ea_support(SNUM(conn
))) {
709 return NT_STATUS_EAS_NOT_SUPPORTED
;
713 return NT_STATUS_INVALID_HANDLE
;
716 posix_pathnames
= (fsp
->fsp_name
->flags
& SMB_FILENAME_POSIX_PATH
);
718 status
= refuse_symlink_fsp(fsp
);
719 if (!NT_STATUS_IS_OK(status
)) {
723 status
= check_any_access_fsp(fsp
, FILE_WRITE_EA
);
724 if (!NT_STATUS_IS_OK(status
)) {
728 /* Setting EAs on streams isn't supported. */
729 if (fsp_is_alternate_stream(fsp
)) {
730 return NT_STATUS_INVALID_PARAMETER
;
734 * Filter out invalid Windows EA names - before
735 * we set *any* of them.
738 if (!posix_pathnames
&& ea_list_has_invalid_name(ea_list
)) {
739 return STATUS_INVALID_EA_NAME
;
742 for (;ea_list
; ea_list
= ea_list
->next
) {
744 fstring unix_ea_name
;
747 * Complementing the forward mapping from POSIX EAs to
748 * Windows EAs in get_ea_list_from_fsp(), here we map in the
749 * opposite direction from Windows EAs to the 'user' namespace
750 * of POSIX EAs. Hence, all POSIX EA names the we set here must
751 * start with a 'user.' prefix.
753 fstrcpy(unix_ea_name
, "user.");
754 fstrcat(unix_ea_name
, ea_list
->ea
.name
);
756 canonicalize_ea_name(fsp
, unix_ea_name
);
758 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name
, (unsigned int)ea_list
->ea
.value
.length
));
760 if (samba_private_attr_name(unix_ea_name
)) {
761 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name
));
762 return NT_STATUS_ACCESS_DENIED
;
765 if (ea_list
->ea
.value
.length
== 0) {
766 /* Remove the attribute. */
767 DBG_DEBUG("deleting ea name %s on "
768 "file %s by file descriptor.\n",
769 unix_ea_name
, fsp_str_dbg(fsp
));
770 ret
= SMB_VFS_FREMOVEXATTR(fsp
, unix_ea_name
);
772 /* Removing a non existent attribute always succeeds. */
773 if (ret
== -1 && errno
== ENOATTR
) {
774 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
780 DEBUG(10,("set_ea: setting ea name %s on file "
781 "%s by file descriptor.\n",
782 unix_ea_name
, fsp_str_dbg(fsp
)));
783 ret
= SMB_VFS_FSETXATTR(fsp
, unix_ea_name
,
784 ea_list
->ea
.value
.data
, ea_list
->ea
.value
.length
, 0);
789 if (errno
== ENOTSUP
) {
790 return NT_STATUS_EAS_NOT_SUPPORTED
;
793 return map_nt_error_from_unix(errno
);
800 /****************************************************************************
801 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
802 ****************************************************************************/
804 struct ea_list
*read_ea_list(TALLOC_CTX
*ctx
, const char *pdata
, size_t data_size
)
806 struct ea_list
*ea_list_head
= NULL
;
808 size_t bytes_used
= 0;
810 while (offset
< data_size
) {
811 struct ea_list
*eal
= read_ea_list_entry(ctx
, pdata
+ offset
, data_size
- offset
, &bytes_used
);
817 DLIST_ADD_END(ea_list_head
, eal
);
818 offset
+= bytes_used
;
824 /****************************************************************************
825 Count the total EA size needed.
826 ****************************************************************************/
828 static size_t ea_list_size(struct ea_list
*ealist
)
831 struct ea_list
*listp
;
834 for (listp
= ealist
; listp
; listp
= listp
->next
) {
835 push_ascii_fstring(dos_ea_name
, listp
->ea
.name
);
836 ret
+= 4 + strlen(dos_ea_name
) + 1 + listp
->ea
.value
.length
;
838 /* Add on 4 for total length. */
846 /****************************************************************************
847 Return a union of EA's from a file list and a list of names.
848 The TALLOC context for the two lists *MUST* be identical as we steal
849 memory from one list to add to another. JRA.
850 ****************************************************************************/
852 static struct ea_list
*ea_list_union(struct ea_list
*name_list
, struct ea_list
*file_list
, size_t *total_ea_len
)
854 struct ea_list
*nlistp
, *flistp
;
856 for (nlistp
= name_list
; nlistp
; nlistp
= nlistp
->next
) {
857 for (flistp
= file_list
; flistp
; flistp
= flistp
->next
) {
858 if (strequal(nlistp
->ea
.name
, flistp
->ea
.name
)) {
864 /* Copy the data from this entry. */
865 nlistp
->ea
.flags
= flistp
->ea
.flags
;
866 nlistp
->ea
.value
= flistp
->ea
.value
;
869 nlistp
->ea
.flags
= 0;
870 ZERO_STRUCT(nlistp
->ea
.value
);
874 *total_ea_len
= ea_list_size(name_list
);
878 /****************************************************************************
879 Return the filetype for UNIX extensions.
880 ****************************************************************************/
882 static uint32_t unix_filetype(mode_t mode
)
885 return UNIX_TYPE_FILE
;
886 else if(S_ISDIR(mode
))
887 return UNIX_TYPE_DIR
;
889 else if(S_ISLNK(mode
))
890 return UNIX_TYPE_SYMLINK
;
893 else if(S_ISCHR(mode
))
894 return UNIX_TYPE_CHARDEV
;
897 else if(S_ISBLK(mode
))
898 return UNIX_TYPE_BLKDEV
;
901 else if(S_ISFIFO(mode
))
902 return UNIX_TYPE_FIFO
;
905 else if(S_ISSOCK(mode
))
906 return UNIX_TYPE_SOCKET
;
909 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode
));
910 return UNIX_TYPE_UNKNOWN
;
913 /****************************************************************************
914 Map wire perms onto standard UNIX permissions. Obey share restrictions.
915 ****************************************************************************/
917 NTSTATUS
unix_perms_from_wire(connection_struct
*conn
,
918 const SMB_STRUCT_STAT
*psbuf
,
920 enum perm_type ptype
,
925 if (perms
== SMB_MODE_NO_CHANGE
) {
926 if (!VALID_STAT(*psbuf
)) {
927 return NT_STATUS_INVALID_PARAMETER
;
929 *ret_perms
= psbuf
->st_ex_mode
;
934 ret
= wire_perms_to_unix(perms
);
936 if (ptype
== PERM_NEW_FILE
) {
938 * "create mask"/"force create mode" are
939 * only applied to new files, not existing ones.
941 ret
&= lp_create_mask(SNUM(conn
));
942 /* Add in force bits */
943 ret
|= lp_force_create_mode(SNUM(conn
));
944 } else if (ptype
== PERM_NEW_DIR
) {
946 * "directory mask"/"force directory mode" are
947 * only applied to new directories, not existing ones.
949 ret
&= lp_directory_mask(SNUM(conn
));
950 /* Add in force bits */
951 ret
|= lp_force_directory_mode(SNUM(conn
));
958 /****************************************************************************
959 Get a level dependent lanman2 dir entry.
960 ****************************************************************************/
962 struct smbd_dirptr_lanman2_state
{
963 connection_struct
*conn
;
965 bool check_mangled_names
;
969 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX
*ctx
,
975 struct smbd_dirptr_lanman2_state
*state
=
976 (struct smbd_dirptr_lanman2_state
*)private_data
;
978 char mangled_name
[13]; /* mangled 8.3 name. */
982 /* Mangle fname if it's an illegal name. */
983 if (mangle_must_mangle(dname
, state
->conn
->params
)) {
985 * Slow path - ensure we can push the original name as UCS2. If
986 * not, then just don't return this name.
990 size_t len
= (strlen(dname
) + 2) * 4; /* Allow enough space. */
991 uint8_t *tmp
= talloc_array(talloc_tos(),
995 status
= srvstr_push(NULL
,
996 FLAGS2_UNICODE_STRINGS
,
1005 if (!NT_STATUS_IS_OK(status
)) {
1009 ok
= name_to_8_3(dname
, mangled_name
,
1010 true, state
->conn
->params
);
1014 fname
= mangled_name
;
1019 got_match
= mask_match(fname
, mask
,
1020 state
->case_sensitive
);
1022 if(!got_match
&& state
->check_mangled_names
&&
1023 !mangle_is_8_3(fname
, false, state
->conn
->params
)) {
1025 * It turns out that NT matches wildcards against
1026 * both long *and* short names. This may explain some
1027 * of the wildcard weirdness from old DOS clients
1028 * that some people have been seeing.... JRA.
1030 /* Force the mangling into 8.3. */
1031 ok
= name_to_8_3(fname
, mangled_name
,
1032 false, state
->conn
->params
);
1037 got_match
= mask_match(mangled_name
, mask
,
1038 state
->case_sensitive
);
1045 *_fname
= talloc_strdup(ctx
, fname
);
1046 if (*_fname
== NULL
) {
1053 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX
*ctx
,
1055 struct files_struct
*dirfsp
,
1056 struct smb_filename
*smb_fname
,
1061 SMB_ASSERT(smb_fname
!= NULL
);
1062 *_mode
= fdos_mode(smb_fname
->fsp
);
1063 if (smb_fname
->fsp
!= NULL
) {
1064 smb_fname
->st
= smb_fname
->fsp
->fsp_name
->st
;
1070 static uint32_t get_dirent_ea_size(uint32_t mode
, files_struct
*fsp
)
1072 if (!(mode
& FILE_ATTRIBUTE_REPARSE_POINT
)) {
1073 unsigned ea_size
= estimate_ea_size(fsp
);
1076 return IO_REPARSE_TAG_DFS
;
1079 static NTSTATUS
smbd_marshall_dir_entry(TALLOC_CTX
*ctx
,
1080 connection_struct
*conn
,
1082 uint32_t info_level
,
1083 struct ea_list
*name_list
,
1084 bool check_mangled_names
,
1085 bool requires_resume_key
,
1088 const struct smb_filename
*smb_fname
,
1089 int space_remaining
,
1095 uint64_t *last_entry_off
)
1097 char *p
, *q
, *pdata
= *ppdata
;
1099 uint64_t file_size
= 0;
1100 uint64_t allocation_size
= 0;
1101 uint64_t file_id
= 0;
1103 struct timespec mdate_ts
= {0};
1104 struct timespec adate_ts
= {0};
1105 struct timespec cdate_ts
= {0};
1106 struct timespec create_date_ts
= {0};
1107 time_t mdate
= (time_t)0, adate
= (time_t)0, create_date
= (time_t)0;
1109 char *last_entry_ptr
;
1114 struct readdir_attr_data
*readdir_attr_data
= NULL
;
1117 if (!(mode
& FILE_ATTRIBUTE_DIRECTORY
)) {
1118 file_size
= get_file_size_stat(&smb_fname
->st
);
1120 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
, NULL
, &smb_fname
->st
);
1123 * Skip SMB_VFS_FREADDIR_ATTR if the directory entry is a symlink or
1126 if (smb_fname
->fsp
!= NULL
&&
1127 !(mode
& FILE_ATTRIBUTE_REPARSE_POINT
)) {
1128 status
= SMB_VFS_FREADDIR_ATTR(smb_fname
->fsp
,
1130 &readdir_attr_data
);
1131 if (!NT_STATUS_IS_OK(status
)) {
1132 if (!NT_STATUS_EQUAL(NT_STATUS_NOT_SUPPORTED
,
1139 file_id
= SMB_VFS_FS_FILE_ID(conn
, &smb_fname
->st
);
1141 mdate_ts
= smb_fname
->st
.st_ex_mtime
;
1142 adate_ts
= smb_fname
->st
.st_ex_atime
;
1143 create_date_ts
= get_create_timespec(conn
, NULL
, smb_fname
);
1144 cdate_ts
= get_change_timespec(conn
, NULL
, smb_fname
);
1146 if (lp_dos_filetime_resolution(SNUM(conn
))) {
1147 dos_filetime_timespec(&create_date_ts
);
1148 dos_filetime_timespec(&mdate_ts
);
1149 dos_filetime_timespec(&adate_ts
);
1150 dos_filetime_timespec(&cdate_ts
);
1153 create_date
= convert_timespec_to_time_t(create_date_ts
);
1154 mdate
= convert_timespec_to_time_t(mdate_ts
);
1155 adate
= convert_timespec_to_time_t(adate_ts
);
1157 /* align the record */
1158 SMB_ASSERT(align
>= 1);
1160 off
= (int)PTR_DIFF(pdata
, base_data
);
1161 pad
= (off
+ (align
-1)) & ~(align
-1);
1164 if (pad
&& pad
> space_remaining
) {
1165 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1166 "for padding (wanted %u, had %d)\n",
1169 return STATUS_MORE_ENTRIES
; /* Not finished - just out of space */
1173 /* initialize padding to 0 */
1175 memset(pdata
, 0, pad
);
1177 space_remaining
-= pad
;
1179 DEBUG(10,("smbd_marshall_dir_entry: space_remaining = %d\n",
1189 switch (info_level
) {
1190 case SMB_FIND_INFO_STANDARD
:
1191 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1192 if(requires_resume_key
) {
1196 srv_put_dos_date2(p
,0,create_date
);
1197 srv_put_dos_date2(p
,4,adate
);
1198 srv_put_dos_date2(p
,8,mdate
);
1199 SIVAL(p
,12,(uint32_t)file_size
);
1200 SIVAL(p
,16,(uint32_t)allocation_size
);
1204 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1205 p
+= ucs2_align(base_data
, p
, 0);
1207 status
= srvstr_push(base_data
, flags2
, p
,
1208 fname
, PTR_DIFF(end_data
, p
),
1209 STR_TERMINATE
, &len
);
1210 if (!NT_STATUS_IS_OK(status
)) {
1213 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1215 SCVAL(nameptr
, -1, len
- 2);
1217 SCVAL(nameptr
, -1, 0);
1221 SCVAL(nameptr
, -1, len
- 1);
1223 SCVAL(nameptr
, -1, 0);
1229 case SMB_FIND_EA_SIZE
:
1230 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
1231 if (requires_resume_key
) {
1235 srv_put_dos_date2(p
,0,create_date
);
1236 srv_put_dos_date2(p
,4,adate
);
1237 srv_put_dos_date2(p
,8,mdate
);
1238 SIVAL(p
,12,(uint32_t)file_size
);
1239 SIVAL(p
,16,(uint32_t)allocation_size
);
1242 ea_size
= estimate_ea_size(smb_fname
->fsp
);
1243 SIVAL(p
,22,ea_size
); /* Extended attributes */
1247 status
= srvstr_push(base_data
, flags2
,
1248 p
, fname
, PTR_DIFF(end_data
, p
),
1249 STR_TERMINATE
| STR_NOALIGN
, &len
);
1250 if (!NT_STATUS_IS_OK(status
)) {
1253 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1266 SCVAL(nameptr
,0,len
);
1268 SCVAL(p
,0,0); p
+= 1; /* Extra zero byte ? - why.. */
1271 case SMB_FIND_EA_LIST
:
1273 struct ea_list
*file_list
= NULL
;
1276 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
1278 return NT_STATUS_INVALID_PARAMETER
;
1280 if (requires_resume_key
) {
1284 srv_put_dos_date2(p
,0,create_date
);
1285 srv_put_dos_date2(p
,4,adate
);
1286 srv_put_dos_date2(p
,8,mdate
);
1287 SIVAL(p
,12,(uint32_t)file_size
);
1288 SIVAL(p
,16,(uint32_t)allocation_size
);
1290 p
+= 22; /* p now points to the EA area. */
1292 status
= get_ea_list_from_fsp(ctx
,
1294 &ea_len
, &file_list
);
1295 if (!NT_STATUS_IS_OK(status
)) {
1298 name_list
= ea_list_union(name_list
, file_list
, &ea_len
);
1300 /* We need to determine if this entry will fit in the space available. */
1301 /* Max string size is 255 bytes. */
1302 if (PTR_DIFF(p
+ 255 + ea_len
,pdata
) > space_remaining
) {
1303 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1304 "(wanted %u, had %d)\n",
1305 (unsigned int)PTR_DIFF(p
+ 255 + ea_len
,pdata
),
1307 return STATUS_MORE_ENTRIES
; /* Not finished - just out of space */
1310 /* Push the ea_data followed by the name. */
1311 p
+= fill_ea_buffer(ctx
, p
, space_remaining
, conn
, name_list
);
1313 status
= srvstr_push(base_data
, flags2
,
1314 p
+ 1, fname
, PTR_DIFF(end_data
, p
+1),
1315 STR_TERMINATE
| STR_NOALIGN
, &len
);
1316 if (!NT_STATUS_IS_OK(status
)) {
1319 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1332 SCVAL(nameptr
,0,len
);
1334 SCVAL(p
,0,0); p
+= 1; /* Extra zero byte ? - why.. */
1338 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
1339 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1340 was_8_3
= mangle_is_8_3(fname
, True
, conn
->params
);
1342 SIVAL(p
,0,reskey
); p
+= 4;
1343 put_long_date_full_timespec(conn
->ts_res
,p
,&create_date_ts
); p
+= 8;
1344 put_long_date_full_timespec(conn
->ts_res
,p
,&adate_ts
); p
+= 8;
1345 put_long_date_full_timespec(conn
->ts_res
,p
,&mdate_ts
); p
+= 8;
1346 put_long_date_full_timespec(conn
->ts_res
,p
,&cdate_ts
); p
+= 8;
1347 SOFF_T(p
,0,file_size
); p
+= 8;
1348 SOFF_T(p
,0,allocation_size
); p
+= 8;
1349 SIVAL(p
,0,mode
); p
+= 4;
1350 q
= p
; p
+= 4; /* q is placeholder for name length. */
1351 ea_size
= get_dirent_ea_size(mode
, smb_fname
->fsp
);
1352 SIVAL(p
, 0, ea_size
);
1354 /* Clear the short name buffer. This is
1355 * IMPORTANT as not doing so will trigger
1356 * a Win2k client bug. JRA.
1358 if (!was_8_3
&& check_mangled_names
) {
1359 char mangled_name
[13]; /* mangled 8.3 name. */
1360 if (!name_to_8_3(fname
,mangled_name
,True
,
1362 /* Error - mangle failed ! */
1363 memset(mangled_name
,'\0',12);
1365 mangled_name
[12] = 0;
1366 status
= srvstr_push(base_data
, flags2
,
1367 p
+2, mangled_name
, 24,
1368 STR_UPPER
|STR_UNICODE
, &len
);
1369 if (!NT_STATUS_IS_OK(status
)) {
1373 memset(p
+ 2 + len
,'\0',24 - len
);
1380 status
= srvstr_push(base_data
, flags2
, p
,
1381 fname
, PTR_DIFF(end_data
, p
),
1382 STR_TERMINATE_ASCII
, &len
);
1383 if (!NT_STATUS_IS_OK(status
)) {
1389 len
= PTR_DIFF(p
, pdata
);
1390 pad
= (len
+ (align
-1)) & ~(align
-1);
1392 * offset to the next entry, the caller
1393 * will overwrite it for the last entry
1394 * that's why we always include the padding
1398 * set padding to zero
1401 memset(p
, 0, pad
- len
);
1408 case SMB_FIND_FILE_DIRECTORY_INFO
:
1409 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1411 SIVAL(p
,0,reskey
); p
+= 4;
1412 put_long_date_full_timespec(conn
->ts_res
,p
,&create_date_ts
); p
+= 8;
1413 put_long_date_full_timespec(conn
->ts_res
,p
,&adate_ts
); p
+= 8;
1414 put_long_date_full_timespec(conn
->ts_res
,p
,&mdate_ts
); p
+= 8;
1415 put_long_date_full_timespec(conn
->ts_res
,p
,&cdate_ts
); p
+= 8;
1416 SOFF_T(p
,0,file_size
); p
+= 8;
1417 SOFF_T(p
,0,allocation_size
); p
+= 8;
1418 SIVAL(p
,0,mode
); p
+= 4;
1419 status
= srvstr_push(base_data
, flags2
,
1420 p
+ 4, fname
, PTR_DIFF(end_data
, p
+4),
1421 STR_TERMINATE_ASCII
, &len
);
1422 if (!NT_STATUS_IS_OK(status
)) {
1428 len
= PTR_DIFF(p
, pdata
);
1429 pad
= (len
+ (align
-1)) & ~(align
-1);
1431 * offset to the next entry, the caller
1432 * will overwrite it for the last entry
1433 * that's why we always include the padding
1437 * set padding to zero
1440 memset(p
, 0, pad
- len
);
1447 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
1448 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1450 SIVAL(p
,0,reskey
); p
+= 4;
1451 put_long_date_full_timespec(conn
->ts_res
,p
,&create_date_ts
); p
+= 8;
1452 put_long_date_full_timespec(conn
->ts_res
,p
,&adate_ts
); p
+= 8;
1453 put_long_date_full_timespec(conn
->ts_res
,p
,&mdate_ts
); p
+= 8;
1454 put_long_date_full_timespec(conn
->ts_res
,p
,&cdate_ts
); p
+= 8;
1455 SOFF_T(p
,0,file_size
); p
+= 8;
1456 SOFF_T(p
,0,allocation_size
); p
+= 8;
1457 SIVAL(p
,0,mode
); p
+= 4;
1458 q
= p
; p
+= 4; /* q is placeholder for name length. */
1459 ea_size
= get_dirent_ea_size(mode
, smb_fname
->fsp
);
1460 SIVAL(p
, 0, ea_size
);
1462 status
= srvstr_push(base_data
, flags2
, p
,
1463 fname
, PTR_DIFF(end_data
, p
),
1464 STR_TERMINATE_ASCII
, &len
);
1465 if (!NT_STATUS_IS_OK(status
)) {
1471 len
= PTR_DIFF(p
, pdata
);
1472 pad
= (len
+ (align
-1)) & ~(align
-1);
1474 * offset to the next entry, the caller
1475 * will overwrite it for the last entry
1476 * that's why we always include the padding
1480 * set padding to zero
1483 memset(p
, 0, pad
- len
);
1490 case SMB_FIND_FILE_NAMES_INFO
:
1491 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1493 SIVAL(p
,0,reskey
); p
+= 4;
1495 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1496 acl on a dir (tridge) */
1497 status
= srvstr_push(base_data
, flags2
, p
,
1498 fname
, PTR_DIFF(end_data
, p
),
1499 STR_TERMINATE_ASCII
, &len
);
1500 if (!NT_STATUS_IS_OK(status
)) {
1506 len
= PTR_DIFF(p
, pdata
);
1507 pad
= (len
+ (align
-1)) & ~(align
-1);
1509 * offset to the next entry, the caller
1510 * will overwrite it for the last entry
1511 * that's why we always include the padding
1515 * set padding to zero
1518 memset(p
, 0, pad
- len
);
1525 case SMB_FIND_ID_FULL_DIRECTORY_INFO
:
1526 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1528 SIVAL(p
,0,reskey
); p
+= 4;
1529 put_long_date_full_timespec(conn
->ts_res
,p
,&create_date_ts
); p
+= 8;
1530 put_long_date_full_timespec(conn
->ts_res
,p
,&adate_ts
); p
+= 8;
1531 put_long_date_full_timespec(conn
->ts_res
,p
,&mdate_ts
); p
+= 8;
1532 put_long_date_full_timespec(conn
->ts_res
,p
,&cdate_ts
); p
+= 8;
1533 SOFF_T(p
,0,file_size
); p
+= 8;
1534 SOFF_T(p
,0,allocation_size
); p
+= 8;
1535 SIVAL(p
,0,mode
); p
+= 4;
1536 q
= p
; p
+= 4; /* q is placeholder for name length. */
1537 ea_size
= get_dirent_ea_size(mode
, smb_fname
->fsp
);
1538 SIVAL(p
, 0, ea_size
);
1540 SIVAL(p
,0,0); p
+= 4; /* Unknown - reserved ? */
1541 SBVAL(p
,0,file_id
); p
+= 8;
1542 status
= srvstr_push(base_data
, flags2
, p
,
1543 fname
, PTR_DIFF(end_data
, p
),
1544 STR_TERMINATE_ASCII
, &len
);
1545 if (!NT_STATUS_IS_OK(status
)) {
1551 len
= PTR_DIFF(p
, pdata
);
1552 pad
= (len
+ (align
-1)) & ~(align
-1);
1554 * offset to the next entry, the caller
1555 * will overwrite it for the last entry
1556 * that's why we always include the padding
1560 * set padding to zero
1563 memset(p
, 0, pad
- len
);
1570 case SMB_FIND_ID_BOTH_DIRECTORY_INFO
:
1571 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1572 was_8_3
= mangle_is_8_3(fname
, True
, conn
->params
);
1574 SIVAL(p
,0,reskey
); p
+= 4;
1575 put_long_date_full_timespec(conn
->ts_res
,p
,&create_date_ts
); p
+= 8;
1576 put_long_date_full_timespec(conn
->ts_res
,p
,&adate_ts
); p
+= 8;
1577 put_long_date_full_timespec(conn
->ts_res
,p
,&mdate_ts
); p
+= 8;
1578 put_long_date_full_timespec(conn
->ts_res
,p
,&cdate_ts
); p
+= 8;
1579 SOFF_T(p
,0,file_size
); p
+= 8;
1580 SOFF_T(p
,0,allocation_size
); p
+= 8;
1581 SIVAL(p
,0,mode
); p
+= 4;
1582 q
= p
; p
+= 4; /* q is placeholder for name length */
1583 if (readdir_attr_data
&&
1584 readdir_attr_data
->type
== RDATTR_AAPL
) {
1586 * OS X specific SMB2 extension negotiated via
1587 * AAPL create context: return max_access in
1590 ea_size
= readdir_attr_data
->attr_data
.aapl
.max_access
;
1592 ea_size
= get_dirent_ea_size(mode
, smb_fname
->fsp
);
1594 SIVAL(p
,0,ea_size
); /* Extended attributes */
1597 if (readdir_attr_data
&&
1598 readdir_attr_data
->type
== RDATTR_AAPL
) {
1600 * OS X specific SMB2 extension negotiated via
1601 * AAPL create context: return resource fork
1602 * length and compressed FinderInfo in
1605 * According to documentation short_name_len
1606 * should be 0, but on the wire behaviour
1607 * shows its set to 24 by clients.
1611 /* Resourefork length */
1612 SBVAL(p
, 2, readdir_attr_data
->attr_data
.aapl
.rfork_size
);
1614 /* Compressed FinderInfo */
1615 memcpy(p
+ 10, &readdir_attr_data
->attr_data
.aapl
.finder_info
, 16);
1616 } else if (!was_8_3
&& check_mangled_names
) {
1617 char mangled_name
[13]; /* mangled 8.3 name. */
1618 if (!name_to_8_3(fname
,mangled_name
,True
,
1620 /* Error - mangle failed ! */
1621 memset(mangled_name
,'\0',12);
1623 mangled_name
[12] = 0;
1624 status
= srvstr_push(base_data
, flags2
,
1625 p
+2, mangled_name
, 24,
1626 STR_UPPER
|STR_UNICODE
, &len
);
1627 if (!NT_STATUS_IS_OK(status
)) {
1632 memset(p
+ 2 + len
,'\0',24 - len
);
1636 /* Clear the short name buffer. This is
1637 * IMPORTANT as not doing so will trigger
1638 * a Win2k client bug. JRA.
1645 if (readdir_attr_data
&&
1646 readdir_attr_data
->type
== RDATTR_AAPL
) {
1648 * OS X specific SMB2 extension negotiated via
1649 * AAPL create context: return UNIX mode in
1652 uint16_t aapl_mode
= (uint16_t)readdir_attr_data
->attr_data
.aapl
.unix_mode
;
1653 SSVAL(p
, 0, aapl_mode
);
1659 SBVAL(p
,0,file_id
); p
+= 8;
1660 status
= srvstr_push(base_data
, flags2
, p
,
1661 fname
, PTR_DIFF(end_data
, p
),
1662 STR_TERMINATE_ASCII
, &len
);
1663 if (!NT_STATUS_IS_OK(status
)) {
1669 len
= PTR_DIFF(p
, pdata
);
1670 pad
= (len
+ (align
-1)) & ~(align
-1);
1672 * offset to the next entry, the caller
1673 * will overwrite it for the last entry
1674 * that's why we always include the padding
1678 * set padding to zero
1681 memset(p
, 0, pad
- len
);
1688 /* CIFS UNIX Extension. */
1690 case SMB_FIND_FILE_UNIX
:
1691 case SMB_FIND_FILE_UNIX_INFO2
:
1693 SIVAL(p
,0,reskey
); p
+= 4; /* Used for continuing search. */
1695 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1697 if (info_level
== SMB_FIND_FILE_UNIX
) {
1698 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
1699 p
= store_file_unix_basic(conn
, p
,
1700 NULL
, &smb_fname
->st
);
1701 status
= srvstr_push(base_data
, flags2
, p
,
1702 fname
, PTR_DIFF(end_data
, p
),
1703 STR_TERMINATE
, &len
);
1704 if (!NT_STATUS_IS_OK(status
)) {
1708 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
1709 p
= store_file_unix_basic_info2(conn
, p
,
1710 NULL
, &smb_fname
->st
);
1713 status
= srvstr_push(base_data
, flags2
, p
, fname
,
1714 PTR_DIFF(end_data
, p
), 0, &len
);
1715 if (!NT_STATUS_IS_OK(status
)) {
1718 SIVAL(nameptr
, 0, len
);
1723 len
= PTR_DIFF(p
, pdata
);
1724 pad
= (len
+ (align
-1)) & ~(align
-1);
1726 * offset to the next entry, the caller
1727 * will overwrite it for the last entry
1728 * that's why we always include the padding
1732 * set padding to zero
1735 memset(p
, 0, pad
- len
);
1740 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1744 /* SMB2 UNIX Extension. */
1746 case SMB2_FILE_POSIX_INFORMATION
:
1748 uint8_t *buf
= NULL
;
1751 SIVAL(p
,0,reskey
); p
+= 4;
1753 DEBUG(10,("smbd_marshall_dir_entry: "
1754 "SMB2_FILE_POSIX_INFORMATION\n"));
1755 if (!(conn
->sconn
->using_smb2
)) {
1756 return NT_STATUS_INVALID_LEVEL
;
1758 if (!lp_smb3_unix_extensions()) {
1759 return NT_STATUS_INVALID_LEVEL
;
1762 /* Determine the size of the posix info context */
1763 plen
= store_smb2_posix_info(conn
,
1770 return NT_STATUS_INVALID_PARAMETER
;
1772 buf
= talloc_zero_size(ctx
, plen
);
1774 return NT_STATUS_NO_MEMORY
;
1777 /* Store the context in buf */
1778 store_smb2_posix_info(conn
,
1784 memcpy(p
, buf
, plen
);
1790 status
= srvstr_push(base_data
, flags2
, p
, fname
,
1791 PTR_DIFF(end_data
, p
), 0, &len
);
1792 if (!NT_STATUS_IS_OK(status
)) {
1795 SIVAL(nameptr
, 0, len
);
1799 len
= PTR_DIFF(p
, pdata
);
1800 pad
= (len
+ (align
-1)) & ~(align
-1);
1802 * offset to the next entry, the caller
1803 * will overwrite it for the last entry
1804 * that's why we always include the padding
1811 return NT_STATUS_INVALID_LEVEL
;
1814 if (PTR_DIFF(p
,pdata
) > space_remaining
) {
1815 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1816 "(wanted %u, had %d)\n",
1817 (unsigned int)PTR_DIFF(p
,pdata
),
1819 return STATUS_MORE_ENTRIES
; /* Not finished - just out of space */
1822 /* Setup the last entry pointer, as an offset from base_data */
1823 *last_entry_off
= PTR_DIFF(last_entry_ptr
,base_data
);
1824 /* Advance the data pointer to the next slot */
1827 return NT_STATUS_OK
;
1830 NTSTATUS
smbd_dirptr_lanman2_entry(TALLOC_CTX
*ctx
,
1831 connection_struct
*conn
,
1832 struct dptr_struct
*dirptr
,
1834 const char *path_mask
,
1837 int requires_resume_key
,
1846 int space_remaining
,
1847 struct smb_filename
**_smb_fname
,
1848 int *_last_entry_off
,
1849 struct ea_list
*name_list
,
1850 struct file_id
*file_id
)
1853 const char *mask
= NULL
;
1856 struct smb_filename
*smb_fname
= NULL
;
1857 struct smbd_dirptr_lanman2_state state
;
1859 uint64_t last_entry_off
= 0;
1861 enum mangled_names_options mangled_names
;
1862 bool marshall_with_83_names
;
1864 mangled_names
= lp_mangled_names(conn
->params
);
1868 state
.info_level
= info_level
;
1869 if (mangled_names
!= MANGLED_NAMES_NO
) {
1870 state
.check_mangled_names
= true;
1872 state
.case_sensitive
= dptr_case_sensitive(dirptr
);
1874 p
= strrchr_m(path_mask
,'/');
1885 ok
= smbd_dirptr_get_entry(ctx
,
1892 smbd_dirptr_lanman2_match_fn
,
1893 smbd_dirptr_lanman2_mode_fn
,
1899 return NT_STATUS_END_OF_FILE
;
1902 marshall_with_83_names
= (mangled_names
== MANGLED_NAMES_YES
);
1904 status
= smbd_marshall_dir_entry(ctx
,
1909 marshall_with_83_names
,
1910 requires_resume_key
,
1921 if (NT_STATUS_EQUAL(status
, NT_STATUS_ILLEGAL_CHARACTER
)) {
1922 DEBUG(1,("Conversion error: illegal character: %s\n",
1923 smb_fname_str_dbg(smb_fname
)));
1926 if (file_id
!= NULL
) {
1927 *file_id
= vfs_file_id_from_sbuf(conn
, &smb_fname
->st
);
1930 if (NT_STATUS_EQUAL(status
, STATUS_MORE_ENTRIES
)) {
1931 smbd_dirptr_push_overflow(dirptr
, &fname
, &smb_fname
, mode
);
1934 if (!NT_STATUS_IS_OK(status
)) {
1935 TALLOC_FREE(smb_fname
);
1940 smbd_dirptr_set_last_name_sent(dirptr
, &smb_fname
->base_name
);
1942 if (_smb_fname
!= NULL
) {
1944 * smb_fname is already talloc'ed off ctx.
1945 * We just need to make sure we don't return
1946 * any stream_name, and replace base_name
1947 * with fname in case base_name got mangled.
1948 * This allows us to preserve any smb_fname->fsp
1949 * for asynchronous handle lookups.
1951 TALLOC_FREE(smb_fname
->stream_name
);
1954 * smbd_dirptr_set_last_name_sent() above consumed
1957 smb_fname
->base_name
= talloc_strdup(smb_fname
, fname
);
1959 if (smb_fname
->base_name
== NULL
) {
1960 TALLOC_FREE(smb_fname
);
1962 return NT_STATUS_NO_MEMORY
;
1964 *_smb_fname
= smb_fname
;
1966 TALLOC_FREE(smb_fname
);
1970 *_last_entry_off
= last_entry_off
;
1971 return NT_STATUS_OK
;
1974 unsigned char *create_volume_objectid(connection_struct
*conn
, unsigned char objid
[16])
1976 const struct loadparm_substitution
*lp_sub
=
1977 loadparm_s3_global_substitution();
1979 E_md4hash(lp_servicename(talloc_tos(), lp_sub
, SNUM(conn
)),objid
);
1983 static void samba_extended_info_version(struct smb_extended_info
*extended_info
)
1985 SMB_ASSERT(extended_info
!= NULL
);
1987 extended_info
->samba_magic
= SAMBA_EXTENDED_INFO_MAGIC
;
1988 extended_info
->samba_version
= ((SAMBA_VERSION_MAJOR
& 0xff) << 24)
1989 | ((SAMBA_VERSION_MINOR
& 0xff) << 16)
1990 | ((SAMBA_VERSION_RELEASE
& 0xff) << 8);
1991 #ifdef SAMBA_VERSION_REVISION
1992 extended_info
->samba_version
|= (tolower(*SAMBA_VERSION_REVISION
) - 'a' + 1) & 0xff;
1994 extended_info
->samba_subversion
= 0;
1995 #ifdef SAMBA_VERSION_RC_RELEASE
1996 extended_info
->samba_subversion
|= (SAMBA_VERSION_RC_RELEASE
& 0xff) << 24;
1998 #ifdef SAMBA_VERSION_PRE_RELEASE
1999 extended_info
->samba_subversion
|= (SAMBA_VERSION_PRE_RELEASE
& 0xff) << 16;
2002 #ifdef SAMBA_VERSION_VENDOR_PATCH
2003 extended_info
->samba_subversion
|= (SAMBA_VERSION_VENDOR_PATCH
& 0xffff);
2005 extended_info
->samba_gitcommitdate
= 0;
2006 #ifdef SAMBA_VERSION_COMMIT_TIME
2007 unix_to_nt_time(&extended_info
->samba_gitcommitdate
, SAMBA_VERSION_COMMIT_TIME
);
2010 memset(extended_info
->samba_version_string
, 0,
2011 sizeof(extended_info
->samba_version_string
));
2013 snprintf (extended_info
->samba_version_string
,
2014 sizeof(extended_info
->samba_version_string
),
2015 "%s", samba_version_string());
2018 static bool fsinfo_unix_valid_level(connection_struct
*conn
,
2019 uint16_t info_level
)
2021 if (conn
->sconn
->using_smb2
&&
2022 lp_smb3_unix_extensions() &&
2023 info_level
== SMB2_FS_POSIX_INFORMATION_INTERNAL
) {
2026 #if defined(SMB1SERVER)
2027 if (lp_smb1_unix_extensions() &&
2028 info_level
== SMB_QUERY_POSIX_FS_INFO
) {
2035 NTSTATUS
smbd_do_qfsinfo(struct smbXsrv_connection
*xconn
,
2036 connection_struct
*conn
,
2037 TALLOC_CTX
*mem_ctx
,
2038 uint16_t info_level
,
2040 unsigned int max_data_bytes
,
2041 size_t *fixed_portion
,
2042 struct smb_filename
*fname
,
2046 const struct loadparm_substitution
*lp_sub
=
2047 loadparm_s3_global_substitution();
2048 char *pdata
, *end_data
;
2051 const char *vname
= volume_label(talloc_tos(), SNUM(conn
));
2052 int snum
= SNUM(conn
);
2053 const char *fstype
= lp_fstype(SNUM(conn
));
2054 const char *filename
= NULL
;
2055 const uint64_t bytes_per_sector
= 512;
2056 uint32_t additional_flags
= 0;
2057 struct smb_filename smb_fname
;
2059 NTSTATUS status
= NT_STATUS_OK
;
2063 if (fname
== NULL
|| fname
->base_name
== NULL
) {
2066 filename
= fname
->base_name
;
2070 if (info_level
!= SMB_QUERY_CIFS_UNIX_INFO
) {
2071 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
2072 "info level (0x%x) on IPC$.\n",
2073 (unsigned int)info_level
));
2074 return NT_STATUS_ACCESS_DENIED
;
2078 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level
));
2080 smb_fname
= (struct smb_filename
) {
2081 .base_name
= discard_const_p(char, filename
),
2082 .flags
= fname
? fname
->flags
: 0,
2083 .twrp
= fname
? fname
->twrp
: 0,
2086 if(info_level
!= SMB_FS_QUOTA_INFORMATION
2087 && SMB_VFS_STAT(conn
, &smb_fname
) != 0) {
2088 DEBUG(2,("stat of . failed (%s)\n", strerror(errno
)));
2089 return map_nt_error_from_unix(errno
);
2094 if (max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
< max_data_bytes
) {
2095 return NT_STATUS_INVALID_PARAMETER
;
2098 *ppdata
= (char *)SMB_REALLOC(
2099 *ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
2100 if (*ppdata
== NULL
) {
2101 return NT_STATUS_NO_MEMORY
;
2105 memset((char *)pdata
,'\0',max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
2106 end_data
= pdata
+ max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
- 1;
2110 switch (info_level
) {
2111 case SMB_INFO_ALLOCATION
:
2113 uint64_t dfree
,dsize
,bsize
,block_size
,sectors_per_unit
;
2115 df_ret
= get_dfree_info(conn
, &smb_fname
, &bsize
,
2117 if (df_ret
== (uint64_t)-1) {
2118 return map_nt_error_from_unix(errno
);
2121 block_size
= lp_block_size(snum
);
2122 if (bsize
< block_size
) {
2123 uint64_t factor
= block_size
/bsize
;
2128 if (bsize
> block_size
) {
2129 uint64_t factor
= bsize
/block_size
;
2134 sectors_per_unit
= bsize
/bytes_per_sector
;
2136 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2137 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st
.st_ex_dev
, (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
2138 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
2141 * For large drives, return max values and not modulo.
2143 dsize
= MIN(dsize
, UINT32_MAX
);
2144 dfree
= MIN(dfree
, UINT32_MAX
);
2146 SIVAL(pdata
,l1_idFileSystem
,st
.st_ex_dev
);
2147 SIVAL(pdata
,l1_cSectorUnit
,sectors_per_unit
);
2148 SIVAL(pdata
,l1_cUnit
,dsize
);
2149 SIVAL(pdata
,l1_cUnitAvail
,dfree
);
2150 SSVAL(pdata
,l1_cbSector
,bytes_per_sector
);
2154 case SMB_INFO_VOLUME
:
2155 /* Return volume name */
2157 * Add volume serial number - hash of a combination of
2158 * the called hostname and the service name.
2160 serial
= generate_volume_serial_number(lp_sub
, snum
);
2161 SIVAL(pdata
,0,serial
);
2163 * Win2k3 and previous mess this up by sending a name length
2164 * one byte short. I believe only older clients (OS/2 Win9x) use
2165 * this call so try fixing this by adding a terminating null to
2166 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2168 status
= srvstr_push(
2170 pdata
+l2_vol_szVolLabel
, vname
,
2171 PTR_DIFF(end_data
, pdata
+l2_vol_szVolLabel
),
2172 STR_NOALIGN
|STR_TERMINATE
, &len
);
2173 if (!NT_STATUS_IS_OK(status
)) {
2176 SCVAL(pdata
,l2_vol_cch
,len
);
2177 data_len
= l2_vol_szVolLabel
+ len
;
2178 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %u, "
2179 "name = %s serial = 0x%04"PRIx32
"\n",
2180 (unsigned)convert_timespec_to_time_t(st
.st_ex_ctime
),
2181 (unsigned)len
, vname
, serial
));
2184 case SMB_QUERY_FS_ATTRIBUTE_INFO
:
2185 case SMB_FS_ATTRIBUTE_INFORMATION
:
2187 additional_flags
= 0;
2188 #if defined(HAVE_SYS_QUOTAS)
2189 additional_flags
|= FILE_VOLUME_QUOTAS
;
2192 if(lp_nt_acl_support(SNUM(conn
))) {
2193 additional_flags
|= FILE_PERSISTENT_ACLS
;
2196 /* Capabilities are filled in at connection time through STATVFS call */
2197 additional_flags
|= conn
->fs_capabilities
;
2198 additional_flags
|= lp_parm_int(conn
->params
->service
,
2199 "share", "fake_fscaps",
2202 SIVAL(pdata
,0,FILE_CASE_PRESERVED_NAMES
|FILE_CASE_SENSITIVE_SEARCH
|
2203 FILE_SUPPORTS_OBJECT_IDS
|FILE_UNICODE_ON_DISK
|
2204 additional_flags
); /* FS ATTRIBUTES */
2206 SIVAL(pdata
,4,255); /* Max filename component length */
2207 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2208 and will think we can't do long filenames */
2209 status
= srvstr_push(pdata
, flags2
, pdata
+12, fstype
,
2210 PTR_DIFF(end_data
, pdata
+12),
2212 if (!NT_STATUS_IS_OK(status
)) {
2216 data_len
= 12 + len
;
2217 if (max_data_bytes
>= 16 && data_len
> max_data_bytes
) {
2218 /* the client only requested a portion of the
2220 data_len
= max_data_bytes
;
2221 status
= STATUS_BUFFER_OVERFLOW
;
2223 *fixed_portion
= 16;
2226 case SMB_QUERY_FS_LABEL_INFO
:
2227 case SMB_FS_LABEL_INFORMATION
:
2228 status
= srvstr_push(pdata
, flags2
, pdata
+4, vname
,
2229 PTR_DIFF(end_data
, pdata
+4), 0, &len
);
2230 if (!NT_STATUS_IS_OK(status
)) {
2237 case SMB_QUERY_FS_VOLUME_INFO
:
2238 case SMB_FS_VOLUME_INFORMATION
:
2239 put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER
,
2240 pdata
, &st
.st_ex_btime
);
2242 * Add volume serial number - hash of a combination of
2243 * the called hostname and the service name.
2245 serial
= generate_volume_serial_number(lp_sub
, snum
);
2246 SIVAL(pdata
,8,serial
);
2248 /* Max label len is 32 characters. */
2249 status
= srvstr_push(pdata
, flags2
, pdata
+18, vname
,
2250 PTR_DIFF(end_data
, pdata
+18),
2252 if (!NT_STATUS_IS_OK(status
)) {
2255 SIVAL(pdata
,12,len
);
2258 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO "
2259 "namelen = %d, vol=%s serv=%s "
2260 "serial=0x%04"PRIx32
"\n",
2261 (int)strlen(vname
),vname
,
2262 lp_servicename(talloc_tos(), lp_sub
, snum
),
2264 if (max_data_bytes
>= 24 && data_len
> max_data_bytes
) {
2265 /* the client only requested a portion of the
2267 data_len
= max_data_bytes
;
2268 status
= STATUS_BUFFER_OVERFLOW
;
2270 *fixed_portion
= 24;
2273 case SMB_QUERY_FS_SIZE_INFO
:
2274 case SMB_FS_SIZE_INFORMATION
:
2276 uint64_t dfree
,dsize
,bsize
,block_size
,sectors_per_unit
;
2278 df_ret
= get_dfree_info(conn
, &smb_fname
, &bsize
,
2280 if (df_ret
== (uint64_t)-1) {
2281 return map_nt_error_from_unix(errno
);
2283 block_size
= lp_block_size(snum
);
2284 if (bsize
< block_size
) {
2285 uint64_t factor
= block_size
/bsize
;
2290 if (bsize
> block_size
) {
2291 uint64_t factor
= bsize
/block_size
;
2296 sectors_per_unit
= bsize
/bytes_per_sector
;
2297 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2298 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
2299 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
2300 SBIG_UINT(pdata
,0,dsize
);
2301 SBIG_UINT(pdata
,8,dfree
);
2302 SIVAL(pdata
,16,sectors_per_unit
);
2303 SIVAL(pdata
,20,bytes_per_sector
);
2304 *fixed_portion
= 24;
2308 case SMB_FS_FULL_SIZE_INFORMATION
:
2310 uint64_t dfree
,dsize
,bsize
,block_size
,sectors_per_unit
;
2312 df_ret
= get_dfree_info(conn
, &smb_fname
, &bsize
,
2314 if (df_ret
== (uint64_t)-1) {
2315 return map_nt_error_from_unix(errno
);
2317 block_size
= lp_block_size(snum
);
2318 if (bsize
< block_size
) {
2319 uint64_t factor
= block_size
/bsize
;
2324 if (bsize
> block_size
) {
2325 uint64_t factor
= bsize
/block_size
;
2330 sectors_per_unit
= bsize
/bytes_per_sector
;
2331 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2332 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
2333 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
2334 SBIG_UINT(pdata
,0,dsize
); /* Total Allocation units. */
2335 SBIG_UINT(pdata
,8,dfree
); /* Caller available allocation units. */
2336 SBIG_UINT(pdata
,16,dfree
); /* Actual available allocation units. */
2337 SIVAL(pdata
,24,sectors_per_unit
); /* Sectors per allocation unit. */
2338 SIVAL(pdata
,28,bytes_per_sector
); /* Bytes per sector. */
2339 *fixed_portion
= 32;
2343 case SMB_QUERY_FS_DEVICE_INFO
:
2344 case SMB_FS_DEVICE_INFORMATION
:
2346 uint32_t characteristics
= FILE_DEVICE_IS_MOUNTED
;
2348 if (!CAN_WRITE(conn
)) {
2349 characteristics
|= FILE_READ_ONLY_DEVICE
;
2352 SIVAL(pdata
,0,FILE_DEVICE_DISK
); /* dev type */
2353 SIVAL(pdata
,4,characteristics
);
2358 #ifdef HAVE_SYS_QUOTAS
2359 case SMB_FS_QUOTA_INFORMATION
:
2361 * what we have to send --metze:
2363 * Unknown1: 24 NULL bytes
2364 * Soft Quota Threshold: 8 bytes seems like uint64_t or so
2365 * Hard Quota Limit: 8 bytes seems like uint64_t or so
2366 * Quota Flags: 2 byte :
2367 * Unknown3: 6 NULL bytes
2371 * details for Quota Flags:
2373 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2374 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2375 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2376 * 0x0001 Enable Quotas: enable quota for this fs
2380 /* we need to fake up a fsp here,
2381 * because its not send in this call
2384 SMB_NTQUOTA_STRUCT quotas
;
2387 ZERO_STRUCT(quotas
);
2390 fsp
.fnum
= FNUM_FIELD_INVALID
;
2393 if (get_current_uid(conn
) != 0) {
2394 DEBUG(0,("get_user_quota: access_denied "
2395 "service [%s] user [%s]\n",
2396 lp_servicename(talloc_tos(), lp_sub
, SNUM(conn
)),
2397 conn
->session_info
->unix_info
->unix_name
));
2398 return NT_STATUS_ACCESS_DENIED
;
2401 status
= vfs_get_ntquota(&fsp
, SMB_USER_FS_QUOTA_TYPE
,
2403 if (!NT_STATUS_IS_OK(status
)) {
2404 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), lp_sub
, SNUM(conn
))));
2410 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
2411 lp_servicename(talloc_tos(), lp_sub
, SNUM(conn
))));
2413 /* Unknown1 24 NULL bytes*/
2414 SBIG_UINT(pdata
,0,(uint64_t)0);
2415 SBIG_UINT(pdata
,8,(uint64_t)0);
2416 SBIG_UINT(pdata
,16,(uint64_t)0);
2418 /* Default Soft Quota 8 bytes */
2419 SBIG_UINT(pdata
,24,quotas
.softlim
);
2421 /* Default Hard Quota 8 bytes */
2422 SBIG_UINT(pdata
,32,quotas
.hardlim
);
2424 /* Quota flag 2 bytes */
2425 SSVAL(pdata
,40,quotas
.qflags
);
2427 /* Unknown3 6 NULL bytes */
2433 #endif /* HAVE_SYS_QUOTAS */
2434 case SMB_FS_OBJECTID_INFORMATION
:
2436 unsigned char objid
[16];
2437 struct smb_extended_info extended_info
;
2438 memcpy(pdata
,create_volume_objectid(conn
, objid
),16);
2439 samba_extended_info_version (&extended_info
);
2440 SIVAL(pdata
,16,extended_info
.samba_magic
);
2441 SIVAL(pdata
,20,extended_info
.samba_version
);
2442 SIVAL(pdata
,24,extended_info
.samba_subversion
);
2443 SBIG_UINT(pdata
,28,extended_info
.samba_gitcommitdate
);
2444 memcpy(pdata
+36,extended_info
.samba_version_string
,28);
2449 case SMB_FS_SECTOR_SIZE_INFORMATION
:
2453 * These values match a physical Windows Server 2012
2454 * share backed by NTFS atop spinning rust.
2456 DEBUG(5, ("SMB_FS_SECTOR_SIZE_INFORMATION:"));
2457 /* logical_bytes_per_sector */
2458 SIVAL(pdata
, 0, bytes_per_sector
);
2459 /* phys_bytes_per_sector_atomic */
2460 SIVAL(pdata
, 4, bytes_per_sector
);
2461 /* phys_bytes_per_sector_perf */
2462 SIVAL(pdata
, 8, bytes_per_sector
);
2463 /* fs_effective_phys_bytes_per_sector_atomic */
2464 SIVAL(pdata
, 12, bytes_per_sector
);
2466 SIVAL(pdata
, 16, SSINFO_FLAGS_ALIGNED_DEVICE
2467 | SSINFO_FLAGS_PARTITION_ALIGNED_ON_DEVICE
);
2468 /* byte_off_sector_align */
2469 SIVAL(pdata
, 20, 0);
2470 /* byte_off_partition_align */
2471 SIVAL(pdata
, 24, 0);
2472 *fixed_portion
= 28;
2477 #if defined(WITH_SMB1SERVER)
2479 * Query the version and capabilities of the CIFS UNIX extensions
2483 case SMB_QUERY_CIFS_UNIX_INFO
:
2485 bool large_write
= lp_min_receive_file_size() &&
2486 !smb1_srv_is_signing_active(xconn
);
2487 bool large_read
= !smb1_srv_is_signing_active(xconn
);
2488 int encrypt_caps
= 0;
2490 if (!lp_smb1_unix_extensions()) {
2491 return NT_STATUS_INVALID_LEVEL
;
2494 switch (conn
->encrypt_level
) {
2495 case SMB_SIGNING_OFF
:
2498 case SMB_SIGNING_DESIRED
:
2499 case SMB_SIGNING_IF_REQUIRED
:
2500 case SMB_SIGNING_DEFAULT
:
2501 encrypt_caps
= CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP
;
2503 case SMB_SIGNING_REQUIRED
:
2504 encrypt_caps
= CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP
|
2505 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP
;
2506 large_write
= false;
2512 SSVAL(pdata
,0,CIFS_UNIX_MAJOR_VERSION
);
2513 SSVAL(pdata
,2,CIFS_UNIX_MINOR_VERSION
);
2515 /* We have POSIX ACLs, pathname, encryption,
2516 * large read/write, and locking capability. */
2518 SBIG_UINT(pdata
,4,((uint64_t)(
2519 CIFS_UNIX_POSIX_ACLS_CAP
|
2520 CIFS_UNIX_POSIX_PATHNAMES_CAP
|
2521 CIFS_UNIX_FCNTL_LOCKS_CAP
|
2522 CIFS_UNIX_EXTATTR_CAP
|
2523 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP
|
2525 (large_read
? CIFS_UNIX_LARGE_READ_CAP
: 0) |
2527 CIFS_UNIX_LARGE_WRITE_CAP
: 0))));
2532 case SMB_QUERY_POSIX_FS_INFO
:
2533 case SMB2_FS_POSIX_INFORMATION_INTERNAL
:
2536 struct vfs_statvfs_struct svfs
;
2538 if (!fsinfo_unix_valid_level(conn
, info_level
)) {
2539 return NT_STATUS_INVALID_LEVEL
;
2542 rc
= SMB_VFS_STATVFS(conn
, &smb_fname
, &svfs
);
2546 SIVAL(pdata
,0,svfs
.OptimalTransferSize
);
2547 SIVAL(pdata
,4,svfs
.BlockSize
);
2548 SBIG_UINT(pdata
,8,svfs
.TotalBlocks
);
2549 SBIG_UINT(pdata
,16,svfs
.BlocksAvail
);
2550 SBIG_UINT(pdata
,24,svfs
.UserBlocksAvail
);
2551 SBIG_UINT(pdata
,32,svfs
.TotalFileNodes
);
2552 SBIG_UINT(pdata
,40,svfs
.FreeFileNodes
);
2553 SBIG_UINT(pdata
,48,svfs
.FsIdentifier
);
2554 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
2556 } else if (rc
== EOPNOTSUPP
) {
2557 return NT_STATUS_INVALID_LEVEL
;
2558 #endif /* EOPNOTSUPP */
2560 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(talloc_tos(), lp_sub
, SNUM(conn
))));
2561 return NT_STATUS_DOS(ERRSRV
, ERRerror
);
2566 case SMB_QUERY_POSIX_WHOAMI
:
2572 if (!lp_smb1_unix_extensions()) {
2573 return NT_STATUS_INVALID_LEVEL
;
2576 if (max_data_bytes
< 40) {
2577 return NT_STATUS_BUFFER_TOO_SMALL
;
2580 if (security_session_user_level(conn
->session_info
, NULL
) < SECURITY_USER
) {
2581 flags
|= SMB_WHOAMI_GUEST
;
2584 /* NOTE: 8 bytes for UID/GID, irrespective of native
2585 * platform size. This matches
2586 * SMB_QUERY_FILE_UNIX_BASIC and friends.
2588 data_len
= 4 /* flags */
2595 + 4 /* pad/reserved */
2596 + (conn
->session_info
->unix_token
->ngroups
* 8)
2598 + (conn
->session_info
->security_token
->num_sids
*
2602 SIVAL(pdata
, 0, flags
);
2603 SIVAL(pdata
, 4, SMB_WHOAMI_MASK
);
2605 (uint64_t)conn
->session_info
->unix_token
->uid
);
2606 SBIG_UINT(pdata
, 16,
2607 (uint64_t)conn
->session_info
->unix_token
->gid
);
2610 if (data_len
>= max_data_bytes
) {
2611 /* Potential overflow, skip the GIDs and SIDs. */
2613 SIVAL(pdata
, 24, 0); /* num_groups */
2614 SIVAL(pdata
, 28, 0); /* num_sids */
2615 SIVAL(pdata
, 32, 0); /* num_sid_bytes */
2616 SIVAL(pdata
, 36, 0); /* reserved */
2622 SIVAL(pdata
, 24, conn
->session_info
->unix_token
->ngroups
);
2623 SIVAL(pdata
, 28, conn
->session_info
->security_token
->num_sids
);
2625 /* We walk the SID list twice, but this call is fairly
2626 * infrequent, and I don't expect that it's performance
2627 * sensitive -- jpeach
2629 for (i
= 0, sid_bytes
= 0;
2630 i
< conn
->session_info
->security_token
->num_sids
; ++i
) {
2631 sid_bytes
+= ndr_size_dom_sid(
2632 &conn
->session_info
->security_token
->sids
[i
],
2636 /* SID list byte count */
2637 SIVAL(pdata
, 32, sid_bytes
);
2639 /* 4 bytes pad/reserved - must be zero */
2640 SIVAL(pdata
, 36, 0);
2644 for (i
= 0; i
< conn
->session_info
->unix_token
->ngroups
; ++i
) {
2645 SBIG_UINT(pdata
, data_len
,
2646 (uint64_t)conn
->session_info
->unix_token
->groups
[i
]);
2652 i
< conn
->session_info
->security_token
->num_sids
; ++i
) {
2653 int sid_len
= ndr_size_dom_sid(
2654 &conn
->session_info
->security_token
->sids
[i
],
2657 sid_linearize((uint8_t *)(pdata
+ data_len
),
2659 &conn
->session_info
->security_token
->sids
[i
]);
2660 data_len
+= sid_len
;
2666 case SMB_MAC_QUERY_FS_INFO
:
2668 * Thursby MAC extension... ONLY on NTFS filesystems
2669 * once we do streams then we don't need this
2671 if (strequal(lp_fstype(SNUM(conn
)),"NTFS")) {
2673 SIVAL(pdata
,84,0x100); /* Don't support mac... */
2679 return NT_STATUS_INVALID_LEVEL
;
2682 *ret_data_len
= data_len
;
2686 NTSTATUS
smb_set_fsquota(connection_struct
*conn
,
2687 struct smb_request
*req
,
2689 const DATA_BLOB
*qdata
)
2691 const struct loadparm_substitution
*lp_sub
=
2692 loadparm_s3_global_substitution();
2694 SMB_NTQUOTA_STRUCT quotas
;
2696 ZERO_STRUCT(quotas
);
2699 if ((get_current_uid(conn
) != 0) || !CAN_WRITE(conn
)) {
2700 DEBUG(3, ("set_fsquota: access_denied service [%s] user [%s]\n",
2701 lp_servicename(talloc_tos(), lp_sub
, SNUM(conn
)),
2702 conn
->session_info
->unix_info
->unix_name
));
2703 return NT_STATUS_ACCESS_DENIED
;
2706 if (!check_fsp_ntquota_handle(conn
, req
,
2708 DEBUG(1, ("set_fsquota: no valid QUOTA HANDLE\n"));
2709 return NT_STATUS_INVALID_HANDLE
;
2712 /* note: normally there're 48 bytes,
2713 * but we didn't use the last 6 bytes for now
2716 if (qdata
->length
< 42) {
2717 DEBUG(0,("set_fsquota: requires total_data(%u) >= 42 bytes!\n",
2718 (unsigned int)qdata
->length
));
2719 return NT_STATUS_INVALID_PARAMETER
;
2722 /* unknown_1 24 NULL bytes in pdata*/
2724 /* the soft quotas 8 bytes (uint64_t)*/
2725 quotas
.softlim
= BVAL(qdata
->data
,24);
2727 /* the hard quotas 8 bytes (uint64_t)*/
2728 quotas
.hardlim
= BVAL(qdata
->data
,32);
2730 /* quota_flags 2 bytes **/
2731 quotas
.qflags
= SVAL(qdata
->data
,40);
2733 /* unknown_2 6 NULL bytes follow*/
2735 /* now set the quotas */
2736 if (vfs_set_ntquota(fsp
, SMB_USER_FS_QUOTA_TYPE
, NULL
, "as
)!=0) {
2737 DEBUG(1, ("vfs_set_ntquota() failed for service [%s]\n",
2738 lp_servicename(talloc_tos(), lp_sub
, SNUM(conn
))));
2739 status
= map_nt_error_from_unix(errno
);
2741 status
= NT_STATUS_OK
;
2746 NTSTATUS
smbd_do_setfsinfo(connection_struct
*conn
,
2747 struct smb_request
*req
,
2748 TALLOC_CTX
*mem_ctx
,
2749 uint16_t info_level
,
2751 const DATA_BLOB
*pdata
)
2753 switch (info_level
) {
2754 case SMB_FS_QUOTA_INFORMATION
:
2756 return smb_set_fsquota(conn
,
2765 return NT_STATUS_INVALID_LEVEL
;
2768 /****************************************************************************
2769 Store the FILE_UNIX_BASIC info.
2770 ****************************************************************************/
2772 char *store_file_unix_basic(connection_struct
*conn
,
2775 const SMB_STRUCT_STAT
*psbuf
)
2779 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
2780 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf
->st_ex_mode
));
2782 SOFF_T(pdata
,0,get_file_size_stat(psbuf
)); /* File size 64 Bit */
2785 SOFF_T(pdata
,0,SMB_VFS_GET_ALLOC_SIZE(conn
,fsp
,psbuf
)); /* Number of bytes used on disk - 64 Bit */
2788 put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER
, pdata
, &psbuf
->st_ex_ctime
); /* Change Time 64 Bit */
2789 put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER
,pdata
+8, &psbuf
->st_ex_atime
); /* Last access time 64 Bit */
2790 put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER
, pdata
+16, &psbuf
->st_ex_mtime
); /* Last modification time 64 Bit */
2793 SIVAL(pdata
,0,psbuf
->st_ex_uid
); /* user id for the owner */
2797 SIVAL(pdata
,0,psbuf
->st_ex_gid
); /* group id of owner */
2801 SIVAL(pdata
,0,unix_filetype(psbuf
->st_ex_mode
));
2804 if (S_ISBLK(psbuf
->st_ex_mode
) || S_ISCHR(psbuf
->st_ex_mode
)) {
2805 devno
= psbuf
->st_ex_rdev
;
2807 devno
= psbuf
->st_ex_dev
;
2810 SIVAL(pdata
,0,unix_dev_major(devno
)); /* Major device number if type is device */
2814 SIVAL(pdata
,0,unix_dev_minor(devno
)); /* Minor device number if type is device */
2818 SINO_T_VAL(pdata
, 0, psbuf
->st_ex_ino
); /* inode number */
2821 SIVAL(pdata
,0, unix_perms_to_wire(psbuf
->st_ex_mode
)); /* Standard UNIX file permissions */
2825 SIVAL(pdata
,0,psbuf
->st_ex_nlink
); /* number of hard links */
2832 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
2833 * the chflags(2) (or equivalent) flags.
2835 * XXX: this really should be behind the VFS interface. To do this, we would
2836 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
2837 * Each VFS module could then implement its own mapping as appropriate for the
2838 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
2840 static const struct {unsigned stat_fflag
; unsigned smb_fflag
;}
2844 { UF_NODUMP
, EXT_DO_NOT_BACKUP
},
2848 { UF_IMMUTABLE
, EXT_IMMUTABLE
},
2852 { UF_APPEND
, EXT_OPEN_APPEND_ONLY
},
2856 { UF_HIDDEN
, EXT_HIDDEN
},
2859 /* Do not remove. We need to guarantee that this array has at least one
2860 * entry to build on HP-UX.
2866 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT
*psbuf
,
2867 uint32_t *smb_fflags
, uint32_t *smb_fmask
)
2871 for (i
= 0; i
< ARRAY_SIZE(info2_flags_map
); ++i
) {
2872 *smb_fmask
|= info2_flags_map
[i
].smb_fflag
;
2873 if (psbuf
->st_ex_flags
& info2_flags_map
[i
].stat_fflag
) {
2874 *smb_fflags
|= info2_flags_map
[i
].smb_fflag
;
2879 bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT
*psbuf
,
2880 const uint32_t smb_fflags
,
2881 const uint32_t smb_fmask
,
2884 uint32_t max_fmask
= 0;
2887 *stat_fflags
= psbuf
->st_ex_flags
;
2889 /* For each flags requested in smb_fmask, check the state of the
2890 * corresponding flag in smb_fflags and set or clear the matching
2894 for (i
= 0; i
< ARRAY_SIZE(info2_flags_map
); ++i
) {
2895 max_fmask
|= info2_flags_map
[i
].smb_fflag
;
2896 if (smb_fmask
& info2_flags_map
[i
].smb_fflag
) {
2897 if (smb_fflags
& info2_flags_map
[i
].smb_fflag
) {
2898 *stat_fflags
|= info2_flags_map
[i
].stat_fflag
;
2900 *stat_fflags
&= ~info2_flags_map
[i
].stat_fflag
;
2905 /* If smb_fmask is asking to set any bits that are not supported by
2906 * our flag mappings, we should fail.
2908 if ((smb_fmask
& max_fmask
) != smb_fmask
) {
2916 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
2917 * of file flags and birth (create) time.
2919 char *store_file_unix_basic_info2(connection_struct
*conn
,
2922 const SMB_STRUCT_STAT
*psbuf
)
2924 uint32_t file_flags
= 0;
2925 uint32_t flags_mask
= 0;
2927 pdata
= store_file_unix_basic(conn
, pdata
, fsp
, psbuf
);
2929 /* Create (birth) time 64 bit */
2930 put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER
,pdata
, &psbuf
->st_ex_btime
);
2933 map_info2_flags_from_sbuf(psbuf
, &file_flags
, &flags_mask
);
2934 SIVAL(pdata
, 0, file_flags
); /* flags */
2935 SIVAL(pdata
, 4, flags_mask
); /* mask */
2941 static NTSTATUS
marshall_stream_info(unsigned int num_streams
,
2942 const struct stream_struct
*streams
,
2944 unsigned int max_data_bytes
,
2945 unsigned int *data_size
)
2948 unsigned int ofs
= 0;
2950 if (max_data_bytes
< 32) {
2951 return NT_STATUS_INFO_LENGTH_MISMATCH
;
2954 for (i
= 0; i
< num_streams
; i
++) {
2955 unsigned int next_offset
;
2957 smb_ucs2_t
*namebuf
;
2959 if (!push_ucs2_talloc(talloc_tos(), &namebuf
,
2960 streams
[i
].name
, &namelen
) ||
2963 return NT_STATUS_INVALID_PARAMETER
;
2967 * name_buf is now null-terminated, we need to marshall as not
2974 * We cannot overflow ...
2976 if ((ofs
+ 24 + namelen
) > max_data_bytes
) {
2977 DEBUG(10, ("refusing to overflow reply at stream %u\n",
2979 TALLOC_FREE(namebuf
);
2980 return STATUS_BUFFER_OVERFLOW
;
2983 SIVAL(data
, ofs
+4, namelen
);
2984 SOFF_T(data
, ofs
+8, streams
[i
].size
);
2985 SOFF_T(data
, ofs
+16, streams
[i
].alloc_size
);
2986 memcpy(data
+ofs
+24, namebuf
, namelen
);
2987 TALLOC_FREE(namebuf
);
2989 next_offset
= ofs
+ 24 + namelen
;
2991 if (i
== num_streams
-1) {
2992 SIVAL(data
, ofs
, 0);
2995 unsigned int align
= ndr_align_size(next_offset
, 8);
2997 if ((next_offset
+ align
) > max_data_bytes
) {
2998 DEBUG(10, ("refusing to overflow align "
2999 "reply at stream %u\n",
3001 TALLOC_FREE(namebuf
);
3002 return STATUS_BUFFER_OVERFLOW
;
3005 memset(data
+next_offset
, 0, align
);
3006 next_offset
+= align
;
3008 SIVAL(data
, ofs
, next_offset
- ofs
);
3015 DEBUG(10, ("max_data: %u, data_size: %u\n", max_data_bytes
, ofs
));
3019 return NT_STATUS_OK
;
3022 NTSTATUS
smbd_do_qfilepathinfo(connection_struct
*conn
,
3023 TALLOC_CTX
*mem_ctx
,
3024 struct smb_request
*req
,
3025 uint16_t info_level
,
3027 struct smb_filename
*smb_fname
,
3028 bool delete_pending
,
3029 struct timespec write_time_ts
,
3030 struct ea_list
*ea_list
,
3032 unsigned int max_data_bytes
,
3033 size_t *fixed_portion
,
3035 unsigned int *pdata_size
)
3037 char *pdata
= *ppdata
;
3038 char *dstart
, *dend
;
3039 unsigned int data_size
;
3040 struct timespec create_time_ts
, mtime_ts
, atime_ts
, ctime_ts
;
3041 time_t create_time
, mtime
, atime
, c_time
;
3042 SMB_STRUCT_STAT
*psbuf
= NULL
;
3043 SMB_STRUCT_STAT
*base_sp
= NULL
;
3050 uint64_t file_size
= 0;
3052 uint64_t allocation_size
= 0;
3053 uint64_t file_id
= 0;
3054 uint32_t access_mask
= 0;
3057 if (INFO_LEVEL_IS_UNIX(info_level
)) {
3060 if (lp_smb1_unix_extensions() && req
->posix_pathnames
) {
3061 DBG_DEBUG("SMB1 unix extensions activated\n");
3065 if (lp_smb3_unix_extensions() &&
3067 (fsp
->posix_flags
& FSP_POSIX_FLAGS_OPEN
)) {
3068 DBG_DEBUG("SMB2 posix open\n");
3073 return NT_STATUS_INVALID_LEVEL
;
3077 DEBUG(5,("smbd_do_qfilepathinfo: %s (%s) level=%d max_data=%u\n",
3078 smb_fname_str_dbg(smb_fname
),
3080 info_level
, max_data_bytes
));
3083 * In case of querying a symlink in POSIX context,
3084 * fsp will be NULL. fdos_mode() deals with it.
3087 smb_fname
= fsp
->fsp_name
;
3089 mode
= fdos_mode(fsp
);
3090 psbuf
= &smb_fname
->st
;
3093 base_sp
= fsp
->base_fsp
?
3094 &fsp
->base_fsp
->fsp_name
->st
:
3097 base_sp
= &smb_fname
->st
;
3100 nlink
= psbuf
->st_ex_nlink
;
3102 if (nlink
&& (mode
&FILE_ATTRIBUTE_DIRECTORY
)) {
3106 if ((nlink
> 0) && delete_pending
) {
3110 if (max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
< max_data_bytes
) {
3111 return NT_STATUS_INVALID_PARAMETER
;
3114 data_size
= max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
;
3115 *ppdata
= (char *)SMB_REALLOC(*ppdata
, data_size
);
3116 if (*ppdata
== NULL
) {
3117 return NT_STATUS_NO_MEMORY
;
3121 dend
= dstart
+ data_size
- 1;
3123 if (!is_omit_timespec(&write_time_ts
) &&
3124 !INFO_LEVEL_IS_UNIX(info_level
))
3126 update_stat_ex_mtime(psbuf
, write_time_ts
);
3129 create_time_ts
= get_create_timespec(conn
, fsp
, smb_fname
);
3130 mtime_ts
= psbuf
->st_ex_mtime
;
3131 atime_ts
= psbuf
->st_ex_atime
;
3132 ctime_ts
= get_change_timespec(conn
, fsp
, smb_fname
);
3134 if (lp_dos_filetime_resolution(SNUM(conn
))) {
3135 dos_filetime_timespec(&create_time_ts
);
3136 dos_filetime_timespec(&mtime_ts
);
3137 dos_filetime_timespec(&atime_ts
);
3138 dos_filetime_timespec(&ctime_ts
);
3141 create_time
= convert_timespec_to_time_t(create_time_ts
);
3142 mtime
= convert_timespec_to_time_t(mtime_ts
);
3143 atime
= convert_timespec_to_time_t(atime_ts
);
3144 c_time
= convert_timespec_to_time_t(ctime_ts
);
3146 p
= strrchr_m(smb_fname
->base_name
,'/');
3148 base_name
= smb_fname
->base_name
;
3152 /* NT expects the name to be in an exact form of the *full*
3153 filename. See the trans2 torture test */
3154 if (ISDOT(base_name
)) {
3155 dos_fname
= talloc_strdup(mem_ctx
, "\\");
3157 return NT_STATUS_NO_MEMORY
;
3160 dos_fname
= talloc_asprintf(mem_ctx
,
3162 smb_fname
->base_name
);
3164 return NT_STATUS_NO_MEMORY
;
3166 if (is_named_stream(smb_fname
)) {
3167 dos_fname
= talloc_asprintf(dos_fname
, "%s",
3168 smb_fname
->stream_name
);
3170 return NT_STATUS_NO_MEMORY
;
3174 string_replace(dos_fname
, '/', '\\');
3177 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
, fsp
, psbuf
);
3179 if (fsp
== NULL
|| !fsp
->fsp_flags
.is_fsa
) {
3180 /* Do we have this path open ? */
3181 struct file_id fileid
= vfs_file_id_from_sbuf(conn
, psbuf
);
3182 files_struct
*fsp1
= file_find_di_first(
3183 conn
->sconn
, fileid
, true);
3184 if (fsp1
&& fsp1
->initial_allocation_size
) {
3185 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
, fsp1
, psbuf
);
3189 if (!(mode
& FILE_ATTRIBUTE_DIRECTORY
)) {
3190 file_size
= get_file_size_stat(psbuf
);
3194 pos
= fh_get_position_information(fsp
->fh
);
3198 access_mask
= fsp
->access_mask
;
3200 /* GENERIC_EXECUTE mapping from Windows */
3201 access_mask
= 0x12019F;
3204 /* This should be an index number - looks like
3207 I think this causes us to fail the IFSKIT
3208 BasicFileInformationTest. -tpot */
3209 file_id
= SMB_VFS_FS_FILE_ID(conn
, base_sp
);
3213 switch (info_level
) {
3214 case SMB_INFO_STANDARD
:
3215 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
3217 srv_put_dos_date2(pdata
,l1_fdateCreation
,create_time
);
3218 srv_put_dos_date2(pdata
,l1_fdateLastAccess
,atime
);
3219 srv_put_dos_date2(pdata
,l1_fdateLastWrite
,mtime
); /* write time */
3220 SIVAL(pdata
,l1_cbFile
,(uint32_t)file_size
);
3221 SIVAL(pdata
,l1_cbFileAlloc
,(uint32_t)allocation_size
);
3222 SSVAL(pdata
,l1_attrFile
,mode
);
3225 case SMB_INFO_QUERY_EA_SIZE
:
3227 unsigned int ea_size
=
3228 estimate_ea_size(smb_fname
->fsp
);
3229 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
3231 srv_put_dos_date2(pdata
,0,create_time
);
3232 srv_put_dos_date2(pdata
,4,atime
);
3233 srv_put_dos_date2(pdata
,8,mtime
); /* write time */
3234 SIVAL(pdata
,12,(uint32_t)file_size
);
3235 SIVAL(pdata
,16,(uint32_t)allocation_size
);
3236 SSVAL(pdata
,20,mode
);
3237 SIVAL(pdata
,22,ea_size
);
3241 case SMB_INFO_IS_NAME_VALID
:
3242 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
3244 /* os/2 needs this ? really ?*/
3245 return NT_STATUS_DOS(ERRDOS
, ERRbadfunc
);
3247 /* This is only reached for qpathinfo */
3251 case SMB_INFO_QUERY_EAS_FROM_LIST
:
3253 size_t total_ea_len
= 0;
3254 struct ea_list
*ea_file_list
= NULL
;
3255 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
3258 get_ea_list_from_fsp(mem_ctx
,
3260 &total_ea_len
, &ea_file_list
);
3261 if (!NT_STATUS_IS_OK(status
)) {
3265 ea_list
= ea_list_union(ea_list
, ea_file_list
, &total_ea_len
);
3267 if (!ea_list
|| (total_ea_len
> data_size
)) {
3269 SIVAL(pdata
,0,4); /* EA List Length must be set to 4 if no EA's. */
3273 data_size
= fill_ea_buffer(mem_ctx
, pdata
, data_size
, conn
, ea_list
);
3277 case SMB_INFO_QUERY_ALL_EAS
:
3279 /* We have data_size bytes to put EA's into. */
3280 size_t total_ea_len
= 0;
3281 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
3283 status
= get_ea_list_from_fsp(mem_ctx
,
3285 &total_ea_len
, &ea_list
);
3286 if (!NT_STATUS_IS_OK(status
)) {
3290 if (!ea_list
|| (total_ea_len
> data_size
)) {
3292 SIVAL(pdata
,0,4); /* EA List Length must be set to 4 if no EA's. */
3296 data_size
= fill_ea_buffer(mem_ctx
, pdata
, data_size
, conn
, ea_list
);
3300 case SMB2_FILE_FULL_EA_INFORMATION
:
3302 /* We have data_size bytes to put EA's into. */
3303 size_t total_ea_len
= 0;
3304 struct ea_list
*ea_file_list
= NULL
;
3306 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
3308 /*TODO: add filtering and index handling */
3311 get_ea_list_from_fsp(mem_ctx
,
3313 &total_ea_len
, &ea_file_list
);
3314 if (!NT_STATUS_IS_OK(status
)) {
3317 if (!ea_file_list
) {
3318 return NT_STATUS_NO_EAS_ON_FILE
;
3321 status
= fill_ea_chained_buffer(mem_ctx
,
3325 conn
, ea_file_list
);
3326 if (!NT_STATUS_IS_OK(status
)) {
3332 case SMB_FILE_BASIC_INFORMATION
:
3333 case SMB_QUERY_FILE_BASIC_INFO
:
3335 if (info_level
== SMB_QUERY_FILE_BASIC_INFO
) {
3336 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
3337 data_size
= 36; /* w95 returns 40 bytes not 36 - why ?. */
3339 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
3343 put_long_date_full_timespec(conn
->ts_res
,pdata
,&create_time_ts
);
3344 put_long_date_full_timespec(conn
->ts_res
,pdata
+8,&atime_ts
);
3345 put_long_date_full_timespec(conn
->ts_res
,pdata
+16,&mtime_ts
); /* write time */
3346 put_long_date_full_timespec(conn
->ts_res
,pdata
+24,&ctime_ts
); /* change time */
3347 SIVAL(pdata
,32,mode
);
3349 DEBUG(5,("SMB_QFBI - "));
3350 DEBUG(5,("create: %s ", ctime(&create_time
)));
3351 DEBUG(5,("access: %s ", ctime(&atime
)));
3352 DEBUG(5,("write: %s ", ctime(&mtime
)));
3353 DEBUG(5,("change: %s ", ctime(&c_time
)));
3354 DEBUG(5,("mode: %x\n", mode
));
3355 *fixed_portion
= data_size
;
3358 case SMB_FILE_STANDARD_INFORMATION
:
3359 case SMB_QUERY_FILE_STANDARD_INFO
:
3361 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
3363 SOFF_T(pdata
,0,allocation_size
);
3364 SOFF_T(pdata
,8,file_size
);
3365 SIVAL(pdata
,16,nlink
);
3366 SCVAL(pdata
,20,delete_pending
?1:0);
3367 SCVAL(pdata
,21,(mode
&FILE_ATTRIBUTE_DIRECTORY
)?1:0);
3368 SSVAL(pdata
,22,0); /* Padding. */
3369 *fixed_portion
= 24;
3372 case SMB_FILE_EA_INFORMATION
:
3373 case SMB_QUERY_FILE_EA_INFO
:
3375 unsigned int ea_size
=
3376 estimate_ea_size(smb_fname
->fsp
);
3377 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
3380 SIVAL(pdata
,0,ea_size
);
3384 /* Get the 8.3 name - used if NT SMB was negotiated. */
3385 case SMB_QUERY_FILE_ALT_NAME_INFO
:
3386 case SMB_FILE_ALTERNATE_NAME_INFORMATION
:
3388 char mangled_name
[13];
3389 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
3390 if (!name_to_8_3(base_name
,mangled_name
,
3391 True
,conn
->params
)) {
3392 return NT_STATUS_NO_MEMORY
;
3394 status
= srvstr_push(dstart
, flags2
,
3395 pdata
+4, mangled_name
,
3396 PTR_DIFF(dend
, pdata
+4),
3398 if (!NT_STATUS_IS_OK(status
)) {
3401 data_size
= 4 + len
;
3407 case SMB_QUERY_FILE_NAME_INFO
:
3410 this must be *exactly* right for ACLs on mapped drives to work
3412 status
= srvstr_push(dstart
, flags2
,
3414 PTR_DIFF(dend
, pdata
+4),
3416 if (!NT_STATUS_IS_OK(status
)) {
3419 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
3420 data_size
= 4 + len
;
3425 case SMB_FILE_NORMALIZED_NAME_INFORMATION
:
3427 char *nfname
= NULL
;
3429 if (fsp
== NULL
|| !fsp
->conn
->sconn
->using_smb2
) {
3430 return NT_STATUS_INVALID_LEVEL
;
3433 nfname
= talloc_strdup(mem_ctx
, smb_fname
->base_name
);
3434 if (nfname
== NULL
) {
3435 return NT_STATUS_NO_MEMORY
;
3438 if (ISDOT(nfname
)) {
3441 string_replace(nfname
, '/', '\\');
3443 if (fsp_is_alternate_stream(fsp
)) {
3444 const char *s
= smb_fname
->stream_name
;
3445 const char *e
= NULL
;
3448 SMB_ASSERT(s
[0] != '\0');
3451 * smb_fname->stream_name is in form
3452 * of ':StrEam:$DATA', but we should only
3453 * append ':StrEam' here.
3456 e
= strchr(&s
[1], ':');
3462 nfname
= talloc_strndup_append(nfname
, s
, n
);
3463 if (nfname
== NULL
) {
3464 return NT_STATUS_NO_MEMORY
;
3468 status
= srvstr_push(dstart
, flags2
,
3470 PTR_DIFF(dend
, pdata
+4),
3472 if (!NT_STATUS_IS_OK(status
)) {
3475 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NORMALIZED_NAME_INFORMATION\n"));
3476 data_size
= 4 + len
;
3482 case SMB_FILE_ALLOCATION_INFORMATION
:
3483 case SMB_QUERY_FILE_ALLOCATION_INFO
:
3484 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
3486 SOFF_T(pdata
,0,allocation_size
);
3489 case SMB_FILE_END_OF_FILE_INFORMATION
:
3490 case SMB_QUERY_FILE_END_OF_FILEINFO
:
3491 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
3493 SOFF_T(pdata
,0,file_size
);
3496 case SMB_QUERY_FILE_ALL_INFO
:
3497 case SMB_FILE_ALL_INFORMATION
:
3499 unsigned int ea_size
=
3500 estimate_ea_size(smb_fname
->fsp
);
3501 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
3502 put_long_date_full_timespec(conn
->ts_res
,pdata
,&create_time_ts
);
3503 put_long_date_full_timespec(conn
->ts_res
,pdata
+8,&atime_ts
);
3504 put_long_date_full_timespec(conn
->ts_res
,pdata
+16,&mtime_ts
); /* write time */
3505 put_long_date_full_timespec(conn
->ts_res
,pdata
+24,&ctime_ts
); /* change time */
3506 SIVAL(pdata
,32,mode
);
3507 SIVAL(pdata
,36,0); /* padding. */
3509 SOFF_T(pdata
,0,allocation_size
);
3510 SOFF_T(pdata
,8,file_size
);
3511 SIVAL(pdata
,16,nlink
);
3512 SCVAL(pdata
,20,delete_pending
);
3513 SCVAL(pdata
,21,(mode
&FILE_ATTRIBUTE_DIRECTORY
)?1:0);
3516 SIVAL(pdata
,0,ea_size
);
3517 pdata
+= 4; /* EA info */
3518 status
= srvstr_push(dstart
, flags2
,
3520 PTR_DIFF(dend
, pdata
+4),
3522 if (!NT_STATUS_IS_OK(status
)) {
3527 data_size
= PTR_DIFF(pdata
,(*ppdata
));
3528 *fixed_portion
= 10;
3532 case SMB2_FILE_ALL_INFORMATION
:
3534 unsigned int ea_size
=
3535 estimate_ea_size(smb_fname
->fsp
);
3536 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
3537 put_long_date_full_timespec(conn
->ts_res
,pdata
+0x00,&create_time_ts
);
3538 put_long_date_full_timespec(conn
->ts_res
,pdata
+0x08,&atime_ts
);
3539 put_long_date_full_timespec(conn
->ts_res
,pdata
+0x10,&mtime_ts
); /* write time */
3540 put_long_date_full_timespec(conn
->ts_res
,pdata
+0x18,&ctime_ts
); /* change time */
3541 SIVAL(pdata
, 0x20, mode
);
3542 SIVAL(pdata
, 0x24, 0); /* padding. */
3543 SBVAL(pdata
, 0x28, allocation_size
);
3544 SBVAL(pdata
, 0x30, file_size
);
3545 SIVAL(pdata
, 0x38, nlink
);
3546 SCVAL(pdata
, 0x3C, delete_pending
);
3547 SCVAL(pdata
, 0x3D, (mode
&FILE_ATTRIBUTE_DIRECTORY
)?1:0);
3548 SSVAL(pdata
, 0x3E, 0); /* padding */
3549 SBVAL(pdata
, 0x40, file_id
);
3550 SIVAL(pdata
, 0x48, ea_size
);
3551 SIVAL(pdata
, 0x4C, access_mask
);
3552 SBVAL(pdata
, 0x50, pos
);
3553 SIVAL(pdata
, 0x58, mode
); /*TODO: mode != mode fix this!!! */
3554 SIVAL(pdata
, 0x5C, 0); /* No alignment needed. */
3558 status
= srvstr_push(dstart
, flags2
,
3560 PTR_DIFF(dend
, pdata
+4),
3562 if (!NT_STATUS_IS_OK(status
)) {
3567 data_size
= PTR_DIFF(pdata
,(*ppdata
));
3568 *fixed_portion
= 104;
3571 case SMB_FILE_INTERNAL_INFORMATION
:
3573 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
3574 SBVAL(pdata
, 0, file_id
);
3579 case SMB_FILE_ACCESS_INFORMATION
:
3580 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
3581 SIVAL(pdata
, 0, access_mask
);
3586 case SMB_FILE_NAME_INFORMATION
:
3587 /* Pathname with leading '\'. */
3590 byte_len
= dos_PutUniCode(pdata
+4,dos_fname
,(size_t)max_data_bytes
,False
);
3591 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
3592 SIVAL(pdata
,0,byte_len
);
3593 data_size
= 4 + byte_len
;
3597 case SMB_FILE_DISPOSITION_INFORMATION
:
3598 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
3600 SCVAL(pdata
,0,delete_pending
);
3604 case SMB_FILE_POSITION_INFORMATION
:
3605 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
3607 SOFF_T(pdata
,0,pos
);
3611 case SMB_FILE_MODE_INFORMATION
:
3612 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
3613 SIVAL(pdata
,0,mode
);
3618 case SMB_FILE_ALIGNMENT_INFORMATION
:
3619 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
3620 SIVAL(pdata
,0,0); /* No alignment needed. */
3626 * NT4 server just returns "invalid query" to this - if we try
3627 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
3630 /* The first statement above is false - verified using Thursby
3631 * client against NT4 -- gcolley.
3633 case SMB_QUERY_FILE_STREAM_INFO
:
3634 case SMB_FILE_STREAM_INFORMATION
: {
3635 unsigned int num_streams
= 0;
3636 struct stream_struct
*streams
= NULL
;
3638 DEBUG(10,("smbd_do_qfilepathinfo: "
3639 "SMB_FILE_STREAM_INFORMATION\n"));
3641 if (is_ntfs_stream_smb_fname(smb_fname
)) {
3642 return NT_STATUS_INVALID_PARAMETER
;
3645 status
= vfs_fstreaminfo(fsp
,
3650 if (!NT_STATUS_IS_OK(status
)) {
3651 DEBUG(10, ("could not get stream info: %s\n",
3652 nt_errstr(status
)));
3656 status
= marshall_stream_info(num_streams
, streams
,
3657 pdata
, max_data_bytes
,
3660 if (!NT_STATUS_IS_OK(status
)) {
3661 DEBUG(10, ("marshall_stream_info failed: %s\n",
3662 nt_errstr(status
)));
3663 TALLOC_FREE(streams
);
3667 TALLOC_FREE(streams
);
3669 *fixed_portion
= 32;
3673 case SMB_QUERY_COMPRESSION_INFO
:
3674 case SMB_FILE_COMPRESSION_INFORMATION
:
3675 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
3676 SOFF_T(pdata
,0,file_size
);
3677 SIVAL(pdata
,8,0); /* ??? */
3678 SIVAL(pdata
,12,0); /* ??? */
3680 *fixed_portion
= 16;
3683 case SMB_FILE_NETWORK_OPEN_INFORMATION
:
3684 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
3685 put_long_date_full_timespec(conn
->ts_res
,pdata
,&create_time_ts
);
3686 put_long_date_full_timespec(conn
->ts_res
,pdata
+8,&atime_ts
);
3687 put_long_date_full_timespec(conn
->ts_res
,pdata
+16,&mtime_ts
); /* write time */
3688 put_long_date_full_timespec(conn
->ts_res
,pdata
+24,&ctime_ts
); /* change time */
3689 SOFF_T(pdata
,32,allocation_size
);
3690 SOFF_T(pdata
,40,file_size
);
3691 SIVAL(pdata
,48,mode
);
3692 SIVAL(pdata
,52,0); /* ??? */
3694 *fixed_portion
= 56;
3697 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION
:
3698 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
3699 SIVAL(pdata
,0,mode
);
3706 * SMB2 UNIX Extensions.
3708 case SMB2_FILE_POSIX_INFORMATION_INTERNAL
:
3710 uint8_t *buf
= NULL
;
3713 if (!(conn
->sconn
->using_smb2
)) {
3714 return NT_STATUS_INVALID_LEVEL
;
3716 if (!lp_smb3_unix_extensions()) {
3717 return NT_STATUS_INVALID_LEVEL
;
3720 return NT_STATUS_INVALID_HANDLE
;
3722 if (!(fsp
->posix_flags
& FSP_POSIX_FLAGS_OPEN
)) {
3723 return NT_STATUS_INVALID_LEVEL
;
3726 /* Determine the size of the posix info context */
3727 plen
= store_smb2_posix_info(conn
,
3733 if (plen
== -1 || data_size
< plen
) {
3734 return NT_STATUS_INVALID_PARAMETER
;
3736 buf
= talloc_zero_size(mem_ctx
, plen
);
3738 return NT_STATUS_NO_MEMORY
;
3741 /* Store the context in buf */
3742 store_smb2_posix_info(conn
,
3748 memcpy(pdata
, buf
, plen
);
3754 return NT_STATUS_INVALID_LEVEL
;
3757 *pdata_size
= data_size
;
3758 return NT_STATUS_OK
;
3761 /****************************************************************************
3762 Set a hard link (called by UNIX extensions and by NT rename with HARD link
3764 ****************************************************************************/
3766 NTSTATUS
hardlink_internals(TALLOC_CTX
*ctx
,
3767 connection_struct
*conn
,
3768 struct smb_request
*req
,
3769 bool overwrite_if_exists
,
3770 struct files_struct
*old_dirfsp
,
3771 const struct smb_filename
*smb_fname_old
,
3772 struct files_struct
*new_dirfsp
,
3773 struct smb_filename
*smb_fname_new
)
3775 NTSTATUS status
= NT_STATUS_OK
;
3778 struct smb_filename
*parent_fname_old
= NULL
;
3779 struct smb_filename
*base_name_old
= NULL
;
3780 struct smb_filename
*parent_fname_new
= NULL
;
3781 struct smb_filename
*base_name_new
= NULL
;
3783 /* source must already exist. */
3784 if (!VALID_STAT(smb_fname_old
->st
)) {
3785 status
= NT_STATUS_OBJECT_NAME_NOT_FOUND
;
3789 /* No links from a directory. */
3790 if (S_ISDIR(smb_fname_old
->st
.st_ex_mode
)) {
3791 status
= NT_STATUS_FILE_IS_A_DIRECTORY
;
3795 /* Setting a hardlink to/from a stream isn't currently supported. */
3796 ok
= is_ntfs_stream_smb_fname(smb_fname_old
);
3798 DBG_DEBUG("Old name has streams\n");
3799 status
= NT_STATUS_INVALID_PARAMETER
;
3802 ok
= is_ntfs_stream_smb_fname(smb_fname_new
);
3804 DBG_DEBUG("New name has streams\n");
3805 status
= NT_STATUS_INVALID_PARAMETER
;
3809 if (smb_fname_old
->twrp
!= 0) {
3810 status
= NT_STATUS_NOT_SAME_DEVICE
;
3814 status
= parent_pathref(talloc_tos(),
3819 if (!NT_STATUS_IS_OK(status
)) {
3823 status
= parent_pathref(talloc_tos(),
3828 if (!NT_STATUS_IS_OK(status
)) {
3832 if (VALID_STAT(smb_fname_new
->st
)) {
3833 if (overwrite_if_exists
) {
3834 if (S_ISDIR(smb_fname_new
->st
.st_ex_mode
)) {
3835 status
= NT_STATUS_FILE_IS_A_DIRECTORY
;
3838 status
= unlink_internals(conn
,
3840 FILE_ATTRIBUTE_NORMAL
,
3841 NULL
, /* new_dirfsp */
3843 if (!NT_STATUS_IS_OK(status
)) {
3847 /* Disallow if newname already exists. */
3848 status
= NT_STATUS_OBJECT_NAME_COLLISION
;
3853 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
3854 smb_fname_old
->base_name
, smb_fname_new
->base_name
));
3856 ret
= SMB_VFS_LINKAT(conn
,
3857 parent_fname_old
->fsp
,
3859 parent_fname_new
->fsp
,
3864 status
= map_nt_error_from_unix(errno
);
3865 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
3866 nt_errstr(status
), smb_fname_old
->base_name
,
3867 smb_fname_new
->base_name
));
3872 TALLOC_FREE(parent_fname_old
);
3873 TALLOC_FREE(parent_fname_new
);
3877 /****************************************************************************
3878 Deal with setting the time from any of the setfilepathinfo functions.
3879 NOTE !!!! The check for FILE_WRITE_ATTRIBUTES access must be done *before*
3880 calling this function.
3881 ****************************************************************************/
3883 NTSTATUS
smb_set_file_time(connection_struct
*conn
,
3885 struct smb_filename
*smb_fname
,
3886 struct smb_file_time
*ft
,
3887 bool setting_write_time
)
3889 struct files_struct
*set_fsp
= NULL
;
3890 struct timeval_buf tbuf
[4];
3892 FILE_NOTIFY_CHANGE_LAST_ACCESS
3893 |FILE_NOTIFY_CHANGE_LAST_WRITE
3894 |FILE_NOTIFY_CHANGE_CREATION
;
3897 if (!VALID_STAT(smb_fname
->st
)) {
3898 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
3903 return NT_STATUS_OK
;
3906 set_fsp
= metadata_fsp(fsp
);
3908 /* get some defaults (no modifications) if any info is zero or -1. */
3909 if (is_omit_timespec(&ft
->create_time
)) {
3910 action
&= ~FILE_NOTIFY_CHANGE_CREATION
;
3913 if (is_omit_timespec(&ft
->atime
)) {
3914 action
&= ~FILE_NOTIFY_CHANGE_LAST_ACCESS
;
3917 if (is_omit_timespec(&ft
->mtime
)) {
3918 action
&= ~FILE_NOTIFY_CHANGE_LAST_WRITE
;
3921 if (!setting_write_time
) {
3922 /* ft->mtime comes from change time, not write time. */
3923 action
&= ~FILE_NOTIFY_CHANGE_LAST_WRITE
;
3926 /* Ensure the resolution is the correct for
3927 * what we can store on this filesystem. */
3929 round_timespec(conn
->ts_res
, &ft
->create_time
);
3930 round_timespec(conn
->ts_res
, &ft
->ctime
);
3931 round_timespec(conn
->ts_res
, &ft
->atime
);
3932 round_timespec(conn
->ts_res
, &ft
->mtime
);
3934 DBG_DEBUG("smb_set_filetime: actime: %s\n ",
3935 timespec_string_buf(&ft
->atime
, true, &tbuf
[0]));
3936 DBG_DEBUG("smb_set_filetime: modtime: %s\n ",
3937 timespec_string_buf(&ft
->mtime
, true, &tbuf
[1]));
3938 DBG_DEBUG("smb_set_filetime: ctime: %s\n ",
3939 timespec_string_buf(&ft
->ctime
, true, &tbuf
[2]));
3940 DBG_DEBUG("smb_set_file_time: createtime: %s\n ",
3941 timespec_string_buf(&ft
->create_time
, true, &tbuf
[3]));
3943 if (setting_write_time
) {
3945 * This was a Windows setfileinfo on an open file.
3946 * NT does this a lot. We also need to
3947 * set the time here, as it can be read by
3948 * FindFirst/FindNext and with the patch for bug #2045
3949 * in smbd/fileio.c it ensures that this timestamp is
3950 * kept sticky even after a write. We save the request
3951 * away and will set it on file close and after a write. JRA.
3954 DBG_DEBUG("setting pending modtime to %s\n",
3955 timespec_string_buf(&ft
->mtime
, true, &tbuf
[0]));
3957 if (set_fsp
!= NULL
) {
3958 set_sticky_write_time_fsp(set_fsp
, ft
->mtime
);
3960 set_sticky_write_time_path(
3961 vfs_file_id_from_sbuf(conn
, &smb_fname
->st
),
3966 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
3968 ret
= file_ntimes(conn
, set_fsp
, ft
);
3970 return map_nt_error_from_unix(errno
);
3973 notify_fname(conn
, NOTIFY_ACTION_MODIFIED
, action
,
3974 smb_fname
->base_name
);
3975 return NT_STATUS_OK
;
3978 /****************************************************************************
3979 Deal with setting the dosmode from any of the setfilepathinfo functions.
3980 NB. The check for FILE_WRITE_ATTRIBUTES access on this path must have been
3981 done before calling this function.
3982 ****************************************************************************/
3984 static NTSTATUS
smb_set_file_dosmode(connection_struct
*conn
,
3985 struct files_struct
*fsp
,
3988 struct files_struct
*dos_fsp
= NULL
;
3989 uint32_t current_dosmode
;
3992 if (!VALID_STAT(fsp
->fsp_name
->st
)) {
3993 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
3996 dos_fsp
= metadata_fsp(fsp
);
3999 if (S_ISDIR(fsp
->fsp_name
->st
.st_ex_mode
)) {
4000 dosmode
|= FILE_ATTRIBUTE_DIRECTORY
;
4002 dosmode
&= ~FILE_ATTRIBUTE_DIRECTORY
;
4006 DBG_DEBUG("dosmode: 0x%" PRIx32
"\n", dosmode
);
4008 /* check the mode isn't different, before changing it */
4010 return NT_STATUS_OK
;
4012 current_dosmode
= fdos_mode(dos_fsp
);
4013 if (dosmode
== current_dosmode
) {
4014 return NT_STATUS_OK
;
4017 DBG_DEBUG("file %s : setting dos mode 0x%" PRIx32
"\n",
4018 fsp_str_dbg(dos_fsp
), dosmode
);
4020 ret
= file_set_dosmode(conn
, dos_fsp
->fsp_name
, dosmode
, NULL
, false);
4022 DBG_WARNING("file_set_dosmode of %s failed: %s\n",
4023 fsp_str_dbg(dos_fsp
), strerror(errno
));
4024 return map_nt_error_from_unix(errno
);
4027 return NT_STATUS_OK
;
4030 /****************************************************************************
4031 Deal with setting the size from any of the setfilepathinfo functions.
4032 ****************************************************************************/
4034 NTSTATUS
smb_set_file_size(connection_struct
*conn
,
4035 struct smb_request
*req
,
4037 struct smb_filename
*smb_fname
,
4038 const SMB_STRUCT_STAT
*psbuf
,
4040 bool fail_after_createfile
)
4042 NTSTATUS status
= NT_STATUS_OK
;
4043 files_struct
*new_fsp
= NULL
;
4045 if (!VALID_STAT(*psbuf
)) {
4046 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
4049 DBG_INFO("size: %"PRIu64
", file_size_stat=%"PRIu64
"\n",
4051 get_file_size_stat(psbuf
));
4053 if (size
== get_file_size_stat(psbuf
)) {
4055 return NT_STATUS_OK
;
4057 if (!fsp
->fsp_flags
.modified
) {
4058 return NT_STATUS_OK
;
4060 trigger_write_time_update_immediate(fsp
);
4061 return NT_STATUS_OK
;
4064 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
4065 smb_fname_str_dbg(smb_fname
), (double)size
));
4068 !fsp
->fsp_flags
.is_pathref
&&
4069 fsp_get_io_fd(fsp
) != -1)
4071 /* Handle based call. */
4072 status
= check_any_access_fsp(fsp
, FILE_WRITE_DATA
);
4073 if (!NT_STATUS_IS_OK(status
)) {
4077 if (vfs_set_filelen(fsp
, size
) == -1) {
4078 return map_nt_error_from_unix(errno
);
4080 trigger_write_time_update_immediate(fsp
);
4081 return NT_STATUS_OK
;
4084 status
= SMB_VFS_CREATE_FILE(
4088 smb_fname
, /* fname */
4089 FILE_WRITE_DATA
, /* access_mask */
4090 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
4092 FILE_OPEN
, /* create_disposition*/
4093 0, /* create_options */
4094 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
4095 0, /* oplock_request */
4097 0, /* allocation_size */
4098 0, /* private_flags */
4101 &new_fsp
, /* result */
4103 NULL
, NULL
); /* create context */
4105 if (!NT_STATUS_IS_OK(status
)) {
4106 /* NB. We check for open_was_deferred in the caller. */
4110 /* See RAW-SFILEINFO-END-OF-FILE */
4111 if (fail_after_createfile
) {
4112 close_file_free(req
, &new_fsp
, NORMAL_CLOSE
);
4113 return NT_STATUS_INVALID_LEVEL
;
4116 if (vfs_set_filelen(new_fsp
, size
) == -1) {
4117 status
= map_nt_error_from_unix(errno
);
4118 close_file_free(req
, &new_fsp
, NORMAL_CLOSE
);
4122 trigger_write_time_update_immediate(new_fsp
);
4123 close_file_free(req
, &new_fsp
, NORMAL_CLOSE
);
4124 return NT_STATUS_OK
;
4127 /****************************************************************************
4128 Deal with SMB_INFO_SET_EA.
4129 ****************************************************************************/
4131 static NTSTATUS
smb_info_set_ea(connection_struct
*conn
,
4135 struct smb_filename
*smb_fname
)
4137 struct ea_list
*ea_list
= NULL
;
4138 TALLOC_CTX
*ctx
= NULL
;
4139 NTSTATUS status
= NT_STATUS_OK
;
4141 if (total_data
< 10) {
4143 /* OS/2 workplace shell seems to send SET_EA requests of "null"
4144 length. They seem to have no effect. Bug #3212. JRA */
4146 if ((total_data
== 4) && (IVAL(pdata
,0) == 4)) {
4147 /* We're done. We only get EA info in this call. */
4148 return NT_STATUS_OK
;
4151 return NT_STATUS_INVALID_PARAMETER
;
4154 if (IVAL(pdata
,0) > total_data
) {
4155 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
4156 IVAL(pdata
,0), (unsigned int)total_data
));
4157 return NT_STATUS_INVALID_PARAMETER
;
4161 ea_list
= read_ea_list(ctx
, pdata
+ 4, total_data
- 4);
4163 return NT_STATUS_INVALID_PARAMETER
;
4168 * The only way fsp can be NULL here is if
4169 * smb_fname points at a symlink and
4170 * and we're in POSIX context.
4171 * Ensure this is the case.
4173 * In this case we cannot set the EA.
4175 SMB_ASSERT(smb_fname
->flags
& SMB_FILENAME_POSIX_PATH
);
4176 return NT_STATUS_ACCESS_DENIED
;
4179 status
= set_ea(conn
, fsp
, ea_list
);
4184 /****************************************************************************
4185 Deal with SMB_FILE_FULL_EA_INFORMATION set.
4186 ****************************************************************************/
4188 static NTSTATUS
smb_set_file_full_ea_info(connection_struct
*conn
,
4193 struct ea_list
*ea_list
= NULL
;
4197 return NT_STATUS_INVALID_HANDLE
;
4200 if (!lp_ea_support(SNUM(conn
))) {
4201 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
4202 "EA's not supported.\n",
4203 (unsigned int)total_data
));
4204 return NT_STATUS_EAS_NOT_SUPPORTED
;
4207 if (total_data
< 10) {
4208 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
4210 (unsigned int)total_data
));
4211 return NT_STATUS_INVALID_PARAMETER
;
4214 ea_list
= read_nttrans_ea_list(talloc_tos(),
4219 return NT_STATUS_INVALID_PARAMETER
;
4222 status
= set_ea(conn
, fsp
, ea_list
);
4224 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
4225 smb_fname_str_dbg(fsp
->fsp_name
),
4226 nt_errstr(status
) ));
4232 /****************************************************************************
4233 Deal with SMB_SET_FILE_DISPOSITION_INFO.
4234 ****************************************************************************/
4236 NTSTATUS
smb_set_file_disposition_info(connection_struct
*conn
,
4240 struct smb_filename
*smb_fname
)
4242 NTSTATUS status
= NT_STATUS_OK
;
4243 bool delete_on_close
;
4244 uint32_t dosmode
= 0;
4246 if (total_data
< 1) {
4247 return NT_STATUS_INVALID_PARAMETER
;
4251 return NT_STATUS_INVALID_HANDLE
;
4254 delete_on_close
= (CVAL(pdata
,0) ? True
: False
);
4255 dosmode
= fdos_mode(fsp
);
4257 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
4258 "delete_on_close = %u\n",
4259 smb_fname_str_dbg(smb_fname
),
4260 (unsigned int)dosmode
,
4261 (unsigned int)delete_on_close
));
4263 if (delete_on_close
) {
4264 status
= can_set_delete_on_close(fsp
, dosmode
);
4265 if (!NT_STATUS_IS_OK(status
)) {
4270 /* The set is across all open files on this dev/inode pair. */
4271 if (!set_delete_on_close(fsp
, delete_on_close
,
4272 conn
->session_info
->security_token
,
4273 conn
->session_info
->unix_token
)) {
4274 return NT_STATUS_ACCESS_DENIED
;
4276 return NT_STATUS_OK
;
4279 /****************************************************************************
4280 Deal with SMB_FILE_POSITION_INFORMATION.
4281 ****************************************************************************/
4283 static NTSTATUS
smb_file_position_information(connection_struct
*conn
,
4288 uint64_t position_information
;
4290 if (total_data
< 8) {
4291 return NT_STATUS_INVALID_PARAMETER
;
4295 /* Ignore on pathname based set. */
4296 return NT_STATUS_OK
;
4299 position_information
= (uint64_t)IVAL(pdata
,0);
4300 position_information
|= (((uint64_t)IVAL(pdata
,4)) << 32);
4302 DEBUG(10,("smb_file_position_information: Set file position "
4303 "information for file %s to %.0f\n", fsp_str_dbg(fsp
),
4304 (double)position_information
));
4305 fh_set_position_information(fsp
->fh
, position_information
);
4306 return NT_STATUS_OK
;
4309 /****************************************************************************
4310 Deal with SMB_FILE_MODE_INFORMATION.
4311 ****************************************************************************/
4313 static NTSTATUS
smb_file_mode_information(connection_struct
*conn
,
4319 if (total_data
< 4) {
4320 return NT_STATUS_INVALID_PARAMETER
;
4322 mode
= IVAL(pdata
,0);
4323 if (mode
!= 0 && mode
!= 2 && mode
!= 4 && mode
!= 6) {
4324 return NT_STATUS_INVALID_PARAMETER
;
4326 return NT_STATUS_OK
;
4329 /****************************************************************************
4330 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
4331 ****************************************************************************/
4333 static NTSTATUS
smb2_file_rename_information(connection_struct
*conn
,
4334 struct smb_request
*req
,
4338 struct smb_filename
*smb_fname_src
)
4342 char *newname
= NULL
;
4343 struct files_struct
*dst_dirfsp
= NULL
;
4344 struct smb_filename
*smb_fname_dst
= NULL
;
4345 const char *dst_original_lcomp
= NULL
;
4346 uint32_t ucf_flags
= ucf_flags_from_smb_request(req
);
4347 NTSTATUS status
= NT_STATUS_OK
;
4348 TALLOC_CTX
*ctx
= talloc_tos();
4351 return NT_STATUS_INVALID_HANDLE
;
4354 if (total_data
< 20) {
4355 return NT_STATUS_INVALID_PARAMETER
;
4358 overwrite
= (CVAL(pdata
,0) ? True
: False
);
4359 len
= IVAL(pdata
,16);
4361 if (len
> (total_data
- 20) || (len
== 0)) {
4362 return NT_STATUS_INVALID_PARAMETER
;
4365 (void)srvstr_pull_talloc(ctx
,
4373 if (newname
== NULL
) {
4374 return NT_STATUS_INVALID_PARAMETER
;
4377 /* SMB2 rename paths are never DFS. */
4378 req
->flags2
&= ~FLAGS2_DFS_PATHNAMES
;
4379 ucf_flags
&= ~UCF_DFS_PATHNAME
;
4381 status
= check_path_syntax(newname
,
4382 fsp
->fsp_name
->flags
& SMB_FILENAME_POSIX_PATH
);
4383 if (!NT_STATUS_IS_OK(status
)) {
4387 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
4390 if (newname
[0] == ':') {
4391 /* Create an smb_fname to call rename_internals_fsp() with. */
4392 smb_fname_dst
= synthetic_smb_fname(talloc_tos(),
4393 fsp
->base_fsp
->fsp_name
->base_name
,
4396 fsp
->base_fsp
->fsp_name
->twrp
,
4397 fsp
->base_fsp
->fsp_name
->flags
);
4398 if (smb_fname_dst
== NULL
) {
4399 status
= NT_STATUS_NO_MEMORY
;
4403 status
= filename_convert_dirfsp(ctx
,
4407 0, /* Never a TWRP. */
4410 if (!NT_STATUS_IS_OK(status
)) {
4416 * Set the original last component, since
4417 * rename_internals_fsp() requires it.
4419 dst_original_lcomp
= get_original_lcomp(smb_fname_dst
,
4423 if (dst_original_lcomp
== NULL
) {
4424 status
= NT_STATUS_NO_MEMORY
;
4428 DEBUG(10,("smb2_file_rename_information: "
4429 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
4430 fsp_fnum_dbg(fsp
), fsp_str_dbg(fsp
),
4431 smb_fname_str_dbg(smb_fname_dst
)));
4432 status
= rename_internals_fsp(conn
,
4434 NULL
, /* dst_dirfsp */
4437 (FILE_ATTRIBUTE_HIDDEN
|FILE_ATTRIBUTE_SYSTEM
),
4441 TALLOC_FREE(smb_fname_dst
);
4445 static NTSTATUS
smb2_file_link_information(connection_struct
*conn
,
4446 struct smb_request
*req
,
4450 struct smb_filename
*smb_fname_src
)
4454 char *newname
= NULL
;
4455 struct files_struct
*dst_dirfsp
= NULL
;
4456 struct smb_filename
*smb_fname_dst
= NULL
;
4457 NTSTATUS status
= NT_STATUS_OK
;
4458 uint32_t ucf_flags
= ucf_flags_from_smb_request(req
);
4460 TALLOC_CTX
*ctx
= talloc_tos();
4463 return NT_STATUS_INVALID_HANDLE
;
4466 if (total_data
< 20) {
4467 return NT_STATUS_INVALID_PARAMETER
;
4470 overwrite
= (CVAL(pdata
,0) ? true : false);
4471 len
= IVAL(pdata
,16);
4473 if (len
> (total_data
- 20) || (len
== 0)) {
4474 return NT_STATUS_INVALID_PARAMETER
;
4477 ret
= srvstr_pull_talloc(ctx
,
4485 if (ret
== (size_t)-1 || newname
== NULL
) {
4486 return NT_STATUS_INVALID_PARAMETER
;
4489 /* SMB2 hardlink paths are never DFS. */
4490 req
->flags2
&= ~FLAGS2_DFS_PATHNAMES
;
4491 ucf_flags
&= ~UCF_DFS_PATHNAME
;
4493 status
= check_path_syntax(newname
,
4494 fsp
->fsp_name
->flags
& SMB_FILENAME_POSIX_PATH
);
4495 if (!NT_STATUS_IS_OK(status
)) {
4499 DBG_DEBUG("got name |%s|\n", newname
);
4501 status
= filename_convert_dirfsp(ctx
,
4508 if (!NT_STATUS_IS_OK(status
)) {
4512 if (fsp
->base_fsp
) {
4513 /* No stream names. */
4514 return NT_STATUS_NOT_SUPPORTED
;
4517 DBG_DEBUG("SMB_FILE_LINK_INFORMATION (%s) %s -> %s\n",
4518 fsp_fnum_dbg(fsp
), fsp_str_dbg(fsp
),
4519 smb_fname_str_dbg(smb_fname_dst
));
4520 status
= hardlink_internals(ctx
,
4524 NULL
, /* src_dirfsp */
4526 dst_dirfsp
, /* dst_dirfsp */
4529 TALLOC_FREE(smb_fname_dst
);
4533 static NTSTATUS
smb_file_link_information(connection_struct
*conn
,
4534 struct smb_request
*req
,
4538 struct smb_filename
*smb_fname_src
)
4542 char *newname
= NULL
;
4543 struct files_struct
*dst_dirfsp
= NULL
;
4544 struct smb_filename
*smb_fname_dst
= NULL
;
4545 NTSTATUS status
= NT_STATUS_OK
;
4546 uint32_t ucf_flags
= ucf_flags_from_smb_request(req
);
4547 NTTIME dst_twrp
= 0;
4548 TALLOC_CTX
*ctx
= talloc_tos();
4551 return NT_STATUS_INVALID_HANDLE
;
4554 if (total_data
< 20) {
4555 return NT_STATUS_INVALID_PARAMETER
;
4558 overwrite
= (CVAL(pdata
,0) ? true : false);
4559 len
= IVAL(pdata
,16);
4561 if (len
> (total_data
- 20) || (len
== 0)) {
4562 return NT_STATUS_INVALID_PARAMETER
;
4565 if (smb_fname_src
->flags
& SMB_FILENAME_POSIX_PATH
) {
4566 srvstr_get_path_posix(ctx
,
4574 ucf_flags
|= UCF_POSIX_PATHNAMES
;
4576 srvstr_get_path(ctx
,
4585 if (!NT_STATUS_IS_OK(status
)) {
4589 DEBUG(10,("smb_file_link_information: got name |%s|\n",
4592 if (ucf_flags
& UCF_GMT_PATHNAME
) {
4593 extract_snapshot_token(newname
, &dst_twrp
);
4595 /* hardlink paths are never DFS. */
4596 ucf_flags
&= ~UCF_DFS_PATHNAME
;
4598 status
= filename_convert_dirfsp(ctx
,
4605 if (!NT_STATUS_IS_OK(status
)) {
4609 if (fsp
->base_fsp
) {
4610 /* No stream names. */
4611 return NT_STATUS_NOT_SUPPORTED
;
4614 DEBUG(10,("smb_file_link_information: "
4615 "SMB_FILE_LINK_INFORMATION (%s) %s -> %s\n",
4616 fsp_fnum_dbg(fsp
), fsp_str_dbg(fsp
),
4617 smb_fname_str_dbg(smb_fname_dst
)));
4618 status
= hardlink_internals(ctx
,
4622 NULL
, /* src_dirfsp */
4624 dst_dirfsp
, /* dst_dirfsp */
4627 TALLOC_FREE(smb_fname_dst
);
4632 /****************************************************************************
4633 Deal with SMB_FILE_RENAME_INFORMATION.
4634 ****************************************************************************/
4636 static NTSTATUS
smb_file_rename_information(connection_struct
*conn
,
4637 struct smb_request
*req
,
4641 struct smb_filename
*smb_fname_src
)
4646 char *newname
= NULL
;
4647 struct files_struct
*dst_dirfsp
= NULL
;
4648 struct smb_filename
*smb_fname_dst
= NULL
;
4649 const char *dst_original_lcomp
= NULL
;
4650 NTSTATUS status
= NT_STATUS_OK
;
4652 TALLOC_CTX
*ctx
= talloc_tos();
4654 if (total_data
< 13) {
4655 return NT_STATUS_INVALID_PARAMETER
;
4658 overwrite
= (CVAL(pdata
,0) != 0);
4659 root_fid
= IVAL(pdata
,4);
4660 len
= IVAL(pdata
,8);
4662 if (len
> (total_data
- 12) || (len
== 0) || (root_fid
!= 0)) {
4663 return NT_STATUS_INVALID_PARAMETER
;
4666 if (req
->posix_pathnames
) {
4667 srvstr_get_path_posix(ctx
,
4676 srvstr_get_path(ctx
,
4685 if (!NT_STATUS_IS_OK(status
)) {
4689 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
4692 /* Check the new name has no '/' characters. */
4693 if (strchr_m(newname
, '/')) {
4694 return NT_STATUS_NOT_SUPPORTED
;
4697 if (fsp
&& fsp
->base_fsp
) {
4698 /* newname must be a stream name. */
4699 if (newname
[0] != ':') {
4700 return NT_STATUS_NOT_SUPPORTED
;
4703 /* Create an smb_fname to call rename_internals_fsp() with. */
4704 smb_fname_dst
= synthetic_smb_fname(talloc_tos(),
4705 fsp
->base_fsp
->fsp_name
->base_name
,
4708 fsp
->base_fsp
->fsp_name
->twrp
,
4709 fsp
->base_fsp
->fsp_name
->flags
);
4710 if (smb_fname_dst
== NULL
) {
4711 status
= NT_STATUS_NO_MEMORY
;
4716 * Get the original last component, since
4717 * rename_internals_fsp() requires it.
4719 dst_original_lcomp
= get_original_lcomp(smb_fname_dst
,
4723 if (dst_original_lcomp
== NULL
) {
4724 status
= NT_STATUS_NO_MEMORY
;
4730 * Build up an smb_fname_dst based on the filename passed in.
4731 * We basically just strip off the last component, and put on
4732 * the newname instead.
4734 char *base_name
= NULL
;
4735 uint32_t ucf_flags
= ucf_flags_from_smb_request(req
);
4736 NTTIME dst_twrp
= 0;
4738 /* newname must *not* be a stream name. */
4739 if (newname
[0] == ':') {
4740 return NT_STATUS_NOT_SUPPORTED
;
4744 * Strip off the last component (filename) of the path passed
4747 base_name
= talloc_strdup(ctx
, smb_fname_src
->base_name
);
4749 return NT_STATUS_NO_MEMORY
;
4751 p
= strrchr_m(base_name
, '/');
4755 base_name
= talloc_strdup(ctx
, "");
4757 return NT_STATUS_NO_MEMORY
;
4760 /* Append the new name. */
4761 base_name
= talloc_asprintf_append(base_name
,
4765 return NT_STATUS_NO_MEMORY
;
4768 if (ucf_flags
& UCF_GMT_PATHNAME
) {
4769 extract_snapshot_token(base_name
, &dst_twrp
);
4772 /* The newname is *not* a DFS path. */
4773 ucf_flags
&= ~UCF_DFS_PATHNAME
;
4775 status
= filename_convert_dirfsp(ctx
,
4783 if (!NT_STATUS_IS_OK(status
)) {
4786 dst_original_lcomp
= get_original_lcomp(smb_fname_dst
,
4790 if (dst_original_lcomp
== NULL
) {
4791 status
= NT_STATUS_NO_MEMORY
;
4796 if (fsp
!= NULL
&& fsp
->fsp_flags
.is_fsa
) {
4797 DEBUG(10,("smb_file_rename_information: "
4798 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
4799 fsp_fnum_dbg(fsp
), fsp_str_dbg(fsp
),
4800 smb_fname_str_dbg(smb_fname_dst
)));
4801 status
= rename_internals_fsp(conn
,
4809 DEBUG(10,("smb_file_rename_information: "
4810 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
4811 smb_fname_str_dbg(smb_fname_src
),
4812 smb_fname_str_dbg(smb_fname_dst
)));
4813 status
= rename_internals(ctx
,
4816 NULL
, /* src_dirfsp */
4823 FILE_WRITE_ATTRIBUTES
);
4826 TALLOC_FREE(smb_fname_dst
);
4830 /****************************************************************************
4831 Deal with SMB_SET_FILE_BASIC_INFO.
4832 ****************************************************************************/
4834 static NTSTATUS
smb_set_file_basic_info(connection_struct
*conn
,
4838 struct smb_filename
*smb_fname
)
4840 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
4841 struct smb_file_time ft
;
4842 uint32_t dosmode
= 0;
4843 NTSTATUS status
= NT_STATUS_OK
;
4845 init_smb_file_time(&ft
);
4847 if (total_data
< 36) {
4848 return NT_STATUS_INVALID_PARAMETER
;
4852 return NT_STATUS_INVALID_HANDLE
;
4855 status
= check_any_access_fsp(fsp
, FILE_WRITE_ATTRIBUTES
);
4856 if (!NT_STATUS_IS_OK(status
)) {
4860 /* Set the attributes */
4861 dosmode
= IVAL(pdata
,32);
4862 status
= smb_set_file_dosmode(conn
, fsp
, dosmode
);
4863 if (!NT_STATUS_IS_OK(status
)) {
4868 ft
.create_time
= pull_long_date_full_timespec(pdata
);
4871 ft
.atime
= pull_long_date_full_timespec(pdata
+8);
4874 ft
.mtime
= pull_long_date_full_timespec(pdata
+16);
4877 ft
.ctime
= pull_long_date_full_timespec(pdata
+24);
4879 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
4880 smb_fname_str_dbg(smb_fname
)));
4882 status
= smb_set_file_time(conn
, fsp
, smb_fname
, &ft
, true);
4883 if (!NT_STATUS_IS_OK(status
)) {
4887 if (fsp
->fsp_flags
.modified
) {
4888 trigger_write_time_update_immediate(fsp
);
4890 return NT_STATUS_OK
;
4893 /****************************************************************************
4894 Deal with SMB_INFO_STANDARD.
4895 ****************************************************************************/
4897 static NTSTATUS
smb_set_info_standard(connection_struct
*conn
,
4901 struct smb_filename
*smb_fname
)
4904 struct smb_file_time ft
;
4906 init_smb_file_time(&ft
);
4908 if (total_data
< 12) {
4909 return NT_STATUS_INVALID_PARAMETER
;
4913 return NT_STATUS_INVALID_HANDLE
;
4917 ft
.create_time
= time_t_to_full_timespec(srv_make_unix_date2(pdata
));
4919 ft
.atime
= time_t_to_full_timespec(srv_make_unix_date2(pdata
+4));
4921 ft
.mtime
= time_t_to_full_timespec(srv_make_unix_date2(pdata
+8));
4923 DEBUG(10,("smb_set_info_standard: file %s\n",
4924 smb_fname_str_dbg(smb_fname
)));
4926 status
= check_any_access_fsp(fsp
, FILE_WRITE_ATTRIBUTES
);
4927 if (!NT_STATUS_IS_OK(status
)) {
4931 status
= smb_set_file_time(conn
, fsp
, smb_fname
, &ft
, true);
4932 if (!NT_STATUS_IS_OK(status
)) {
4936 if (fsp
->fsp_flags
.modified
) {
4937 trigger_write_time_update_immediate(fsp
);
4939 return NT_STATUS_OK
;
4942 /****************************************************************************
4943 Deal with SMB_SET_FILE_ALLOCATION_INFO.
4944 ****************************************************************************/
4946 static NTSTATUS
smb_set_file_allocation_info(connection_struct
*conn
,
4947 struct smb_request
*req
,
4951 struct smb_filename
*smb_fname
)
4953 uint64_t allocation_size
= 0;
4954 NTSTATUS status
= NT_STATUS_OK
;
4955 files_struct
*new_fsp
= NULL
;
4957 if (!VALID_STAT(smb_fname
->st
)) {
4958 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
4961 if (total_data
< 8) {
4962 return NT_STATUS_INVALID_PARAMETER
;
4965 allocation_size
= (uint64_t)IVAL(pdata
,0);
4966 allocation_size
|= (((uint64_t)IVAL(pdata
,4)) << 32);
4967 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
4968 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname
),
4969 (double)allocation_size
));
4971 if (allocation_size
) {
4972 allocation_size
= smb_roundup(conn
, allocation_size
);
4975 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
4976 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname
),
4977 (double)allocation_size
));
4980 !fsp
->fsp_flags
.is_pathref
&&
4981 fsp_get_io_fd(fsp
) != -1)
4983 /* Open file handle. */
4984 status
= check_any_access_fsp(fsp
, FILE_WRITE_DATA
);
4985 if (!NT_STATUS_IS_OK(status
)) {
4989 /* Only change if needed. */
4990 if (allocation_size
!= get_file_size_stat(&smb_fname
->st
)) {
4991 if (vfs_allocate_file_space(fsp
, allocation_size
) == -1) {
4992 return map_nt_error_from_unix(errno
);
4995 /* But always update the time. */
4997 * This is equivalent to a write. Ensure it's seen immediately
4998 * if there are no pending writes.
5000 trigger_write_time_update_immediate(fsp
);
5001 return NT_STATUS_OK
;
5004 /* Pathname or stat or directory file. */
5005 status
= SMB_VFS_CREATE_FILE(
5009 smb_fname
, /* fname */
5010 FILE_WRITE_DATA
, /* access_mask */
5011 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
5013 FILE_OPEN
, /* create_disposition*/
5014 0, /* create_options */
5015 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
5016 0, /* oplock_request */
5018 0, /* allocation_size */
5019 0, /* private_flags */
5022 &new_fsp
, /* result */
5024 NULL
, NULL
); /* create context */
5026 if (!NT_STATUS_IS_OK(status
)) {
5027 /* NB. We check for open_was_deferred in the caller. */
5031 /* Only change if needed. */
5032 if (allocation_size
!= get_file_size_stat(&smb_fname
->st
)) {
5033 if (vfs_allocate_file_space(new_fsp
, allocation_size
) == -1) {
5034 status
= map_nt_error_from_unix(errno
);
5035 close_file_free(req
, &new_fsp
, NORMAL_CLOSE
);
5040 /* Changing the allocation size should set the last mod time. */
5042 * This is equivalent to a write. Ensure it's seen immediately
5043 * if there are no pending writes.
5045 trigger_write_time_update_immediate(new_fsp
);
5046 close_file_free(req
, &new_fsp
, NORMAL_CLOSE
);
5047 return NT_STATUS_OK
;
5050 /****************************************************************************
5051 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
5052 ****************************************************************************/
5054 static NTSTATUS
smb_set_file_end_of_file_info(connection_struct
*conn
,
5055 struct smb_request
*req
,
5059 struct smb_filename
*smb_fname
,
5060 bool fail_after_createfile
)
5064 if (total_data
< 8) {
5065 return NT_STATUS_INVALID_PARAMETER
;
5068 size
= IVAL(pdata
,0);
5069 size
|= (((off_t
)IVAL(pdata
,4)) << 32);
5070 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
5071 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname
),
5074 return smb_set_file_size(conn
, req
,
5079 fail_after_createfile
);
5082 NTSTATUS
smbd_do_setfilepathinfo(connection_struct
*conn
,
5083 struct smb_request
*req
,
5084 TALLOC_CTX
*mem_ctx
,
5085 uint16_t info_level
,
5087 struct smb_filename
*smb_fname
,
5088 char **ppdata
, int total_data
,
5091 char *pdata
= *ppdata
;
5092 NTSTATUS status
= NT_STATUS_OK
;
5093 int data_return_size
= 0;
5097 DEBUG(3,("smbd_do_setfilepathinfo: %s (%s) info_level=%d "
5098 "totdata=%d\n", smb_fname_str_dbg(smb_fname
),
5100 info_level
, total_data
));
5102 switch (info_level
) {
5104 case SMB_INFO_STANDARD
:
5106 status
= smb_set_info_standard(conn
,
5114 case SMB_INFO_SET_EA
:
5116 status
= smb_info_set_ea(conn
,
5124 case SMB_SET_FILE_BASIC_INFO
:
5125 case SMB_FILE_BASIC_INFORMATION
:
5127 status
= smb_set_file_basic_info(conn
,
5135 case SMB_FILE_ALLOCATION_INFORMATION
:
5136 case SMB_SET_FILE_ALLOCATION_INFO
:
5138 status
= smb_set_file_allocation_info(conn
, req
,
5146 case SMB_FILE_END_OF_FILE_INFORMATION
:
5147 case SMB_SET_FILE_END_OF_FILE_INFO
:
5150 * XP/Win7 both fail after the createfile with
5151 * SMB_SET_FILE_END_OF_FILE_INFO but not
5152 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
5153 * The level is known here, so pass it down
5157 (info_level
== SMB_SET_FILE_END_OF_FILE_INFO
);
5159 status
= smb_set_file_end_of_file_info(conn
, req
,
5168 case SMB_FILE_DISPOSITION_INFORMATION
:
5169 case SMB_SET_FILE_DISPOSITION_INFO
: /* Set delete on close for open file. */
5172 /* JRA - We used to just ignore this on a path ?
5173 * Shouldn't this be invalid level on a pathname
5176 if (tran_call
!= TRANSACT2_SETFILEINFO
) {
5177 return ERROR_NT(NT_STATUS_INVALID_LEVEL
);
5180 status
= smb_set_file_disposition_info(conn
,
5188 case SMB_FILE_POSITION_INFORMATION
:
5190 status
= smb_file_position_information(conn
,
5197 case SMB_FILE_FULL_EA_INFORMATION
:
5199 status
= smb_set_file_full_ea_info(conn
,
5206 /* From tridge Samba4 :
5207 * MODE_INFORMATION in setfileinfo (I have no
5208 * idea what "mode information" on a file is - it takes a value of 0,
5209 * 2, 4 or 6. What could it be?).
5212 case SMB_FILE_MODE_INFORMATION
:
5214 status
= smb_file_mode_information(conn
,
5220 /* [MS-SMB2] 3.3.5.21.1 states we MUST fail with STATUS_NOT_SUPPORTED. */
5221 case SMB_FILE_VALID_DATA_LENGTH_INFORMATION
:
5222 case SMB_FILE_SHORT_NAME_INFORMATION
:
5223 return NT_STATUS_NOT_SUPPORTED
;
5225 case SMB_FILE_RENAME_INFORMATION
:
5227 status
= smb_file_rename_information(conn
, req
,
5233 case SMB2_FILE_RENAME_INFORMATION_INTERNAL
:
5235 /* SMB2 rename information. */
5236 status
= smb2_file_rename_information(conn
, req
,
5242 case SMB_FILE_LINK_INFORMATION
:
5244 if (conn
->sconn
->using_smb2
) {
5245 status
= smb2_file_link_information(conn
,
5252 status
= smb_file_link_information(conn
,
5263 return NT_STATUS_INVALID_LEVEL
;
5266 if (!NT_STATUS_IS_OK(status
)) {
5270 *ret_data_size
= data_return_size
;
5271 return NT_STATUS_OK
;
5274 static uint32_t generate_volume_serial_number(
5275 const struct loadparm_substitution
*lp_sub
,
5278 int serial
= lp_volume_serial_number(snum
);
5279 return serial
!= -1 ? serial
:
5280 str_checksum(lp_servicename(talloc_tos(), lp_sub
, snum
)) ^
5281 (str_checksum(get_local_machine_name())<<16);