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 char *store_file_unix_basic(connection_struct
*conn
,
55 const SMB_STRUCT_STAT
*psbuf
);
57 static char *store_file_unix_basic_info2(connection_struct
*conn
,
60 const SMB_STRUCT_STAT
*psbuf
);
62 static uint32_t generate_volume_serial_number(
63 const struct loadparm_substitution
*lp_sub
,
66 /****************************************************************************
67 Check if an open file handle is a symlink.
68 ****************************************************************************/
70 NTSTATUS
refuse_symlink_fsp(const files_struct
*fsp
)
73 if (!VALID_STAT(fsp
->fsp_name
->st
)) {
74 return NT_STATUS_ACCESS_DENIED
;
76 if (S_ISLNK(fsp
->fsp_name
->st
.st_ex_mode
)) {
77 return NT_STATUS_ACCESS_DENIED
;
79 if (fsp_get_pathref_fd(fsp
) == -1) {
80 return NT_STATUS_ACCESS_DENIED
;
85 NTSTATUS
check_access_fsp(struct files_struct
*fsp
,
88 if (!fsp
->fsp_flags
.is_fsa
) {
89 return smbd_check_access_rights_fsp(fsp
->conn
->cwd_fsp
,
94 if (!(fsp
->access_mask
& access_mask
)) {
95 return NT_STATUS_ACCESS_DENIED
;
100 #if defined(HAVE_POSIX_ACLS)
101 /****************************************************************************
102 Utility function to open a fsp for a POSIX handle operation.
103 ****************************************************************************/
105 static NTSTATUS
get_posix_fsp(connection_struct
*conn
,
106 struct smb_request
*req
,
107 struct smb_filename
*smb_fname
,
108 uint32_t access_mask
,
109 files_struct
**ret_fsp
)
112 uint32_t create_disposition
= FILE_OPEN
;
113 uint32_t share_access
= FILE_SHARE_READ
|
116 struct smb2_create_blobs
*posx
= NULL
;
119 * Only FILE_FLAG_POSIX_SEMANTICS matters on existing files,
120 * but set reasonable defaults.
122 uint32_t file_attributes
= 0664;
123 uint32_t oplock
= NO_OPLOCK
;
124 uint32_t create_options
= FILE_NON_DIRECTORY_FILE
;
126 /* File or directory must exist. */
127 if (!VALID_STAT(smb_fname
->st
)) {
128 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
130 /* Cannot be a symlink. */
131 if (S_ISLNK(smb_fname
->st
.st_ex_mode
)) {
132 return NT_STATUS_ACCESS_DENIED
;
134 /* Set options correctly for directory open. */
135 if (S_ISDIR(smb_fname
->st
.st_ex_mode
)) {
137 * Only FILE_FLAG_POSIX_SEMANTICS matters on existing
138 * directories, but set reasonable defaults.
140 file_attributes
= 0775;
141 create_options
= FILE_DIRECTORY_FILE
;
144 status
= make_smb2_posix_create_ctx(
145 talloc_tos(), &posx
, file_attributes
);
146 if (!NT_STATUS_IS_OK(status
)) {
147 DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
152 status
= SMB_VFS_CREATE_FILE(
156 smb_fname
, /* fname */
157 access_mask
, /* access_mask */
158 share_access
, /* share_access */
159 create_disposition
,/* create_disposition*/
160 create_options
, /* create_options */
161 file_attributes
,/* file_attributes */
162 oplock
, /* oplock_request */
164 0, /* allocation_size */
165 0, /* private_flags */
168 ret_fsp
, /* result */
170 posx
, /* in_context */
171 NULL
); /* out_context */
179 /********************************************************************
180 Roundup a value to the nearest allocation roundup size boundary.
181 Only do this for Windows clients.
182 ********************************************************************/
184 uint64_t smb_roundup(connection_struct
*conn
, uint64_t val
)
186 uint64_t rval
= lp_allocation_roundup_size(SNUM(conn
));
188 /* Only roundup for Windows clients. */
189 enum remote_arch_types ra_type
= get_remote_arch();
190 if (rval
&& (ra_type
!= RA_SAMBA
) && (ra_type
!= RA_CIFSFS
)) {
191 val
= SMB_ROUNDUP(val
,rval
);
196 /****************************************************************************
197 Utility functions for dealing with extended attributes.
198 ****************************************************************************/
200 /****************************************************************************
201 Refuse to allow clients to overwrite our private xattrs.
202 ****************************************************************************/
204 bool samba_private_attr_name(const char *unix_ea_name
)
206 static const char * const prohibited_ea_names
[] = {
207 SAMBA_POSIX_INHERITANCE_EA_NAME
,
208 SAMBA_XATTR_DOS_ATTRIB
,
217 for (i
= 0; prohibited_ea_names
[i
]; i
++) {
218 if (strequal( prohibited_ea_names
[i
], unix_ea_name
))
221 if (strncasecmp_m(unix_ea_name
, SAMBA_XATTR_DOSSTREAM_PREFIX
,
222 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX
)) == 0) {
228 /****************************************************************************
229 Get one EA value. Fill in a struct ea_struct.
230 ****************************************************************************/
232 NTSTATUS
get_ea_value_fsp(TALLOC_CTX
*mem_ctx
,
235 struct ea_struct
*pea
)
237 /* Get the value of this xattr. Max size is 64k. */
238 size_t attr_size
= 256;
241 size_t max_xattr_size
= 0;
244 return NT_STATUS_INVALID_HANDLE
;
247 max_xattr_size
= lp_smbd_max_xattr_size(SNUM(fsp
->conn
));
251 val
= talloc_realloc(mem_ctx
, val
, char, attr_size
);
253 return NT_STATUS_NO_MEMORY
;
256 sizeret
= SMB_VFS_FGETXATTR(fsp
, ea_name
, val
, attr_size
);
257 if (sizeret
== -1 && errno
== ERANGE
&& attr_size
< max_xattr_size
) {
258 attr_size
= max_xattr_size
;
263 return map_nt_error_from_unix(errno
);
266 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name
, (unsigned int)sizeret
));
267 dump_data(10, (uint8_t *)val
, sizeret
);
270 if (strnequal(ea_name
, "user.", 5)) {
271 pea
->name
= talloc_strdup(mem_ctx
, &ea_name
[5]);
273 pea
->name
= talloc_strdup(mem_ctx
, ea_name
);
275 if (pea
->name
== NULL
) {
277 return NT_STATUS_NO_MEMORY
;
279 pea
->value
.data
= (unsigned char *)val
;
280 pea
->value
.length
= (size_t)sizeret
;
284 NTSTATUS
get_ea_names_from_fsp(TALLOC_CTX
*mem_ctx
,
290 /* Get a list of all xattrs. Max namesize is 64k. */
291 size_t ea_namelist_size
= 1024;
292 char *ea_namelist
= smallbuf
;
293 char *to_free
= NULL
;
298 ssize_t sizeret
= -1;
308 * Callers may pass fsp == NULL when passing smb_fname->fsp of a
309 * symlink. This is ok, handle it here, by just return no EA's
315 /* should be the case that fsp != NULL */
316 SMB_ASSERT(fsp
!= NULL
);
318 sizeret
= SMB_VFS_FLISTXATTR(fsp
, ea_namelist
,
321 if ((sizeret
== -1) && (errno
== ERANGE
)) {
322 ea_namelist_size
= 65536;
323 ea_namelist
= talloc_array(mem_ctx
, char, ea_namelist_size
);
324 if (ea_namelist
== NULL
) {
325 return NT_STATUS_NO_MEMORY
;
327 to_free
= ea_namelist
;
329 sizeret
= SMB_VFS_FLISTXATTR(fsp
, ea_namelist
,
334 status
= map_nt_error_from_unix(errno
);
335 TALLOC_FREE(to_free
);
339 DBG_DEBUG("ea_namelist size = %zd\n", sizeret
);
342 TALLOC_FREE(to_free
);
347 * Ensure the result is 0-terminated
350 if (ea_namelist
[sizeret
-1] != '\0') {
351 TALLOC_FREE(to_free
);
352 return NT_STATUS_INTERNAL_ERROR
;
360 for (p
= ea_namelist
; p
- ea_namelist
< sizeret
; p
+= strlen(p
)+1) {
364 *pnum_names
= num_names
;
366 if (pnames
== NULL
) {
367 TALLOC_FREE(to_free
);
371 names
= talloc_array(mem_ctx
, char *, num_names
);
373 DEBUG(0, ("talloc failed\n"));
374 TALLOC_FREE(to_free
);
375 return NT_STATUS_NO_MEMORY
;
378 if (ea_namelist
== smallbuf
) {
379 ea_namelist
= talloc_memdup(names
, smallbuf
, sizeret
);
380 if (ea_namelist
== NULL
) {
382 return NT_STATUS_NO_MEMORY
;
385 talloc_steal(names
, ea_namelist
);
387 ea_namelist
= talloc_realloc(names
, ea_namelist
, char,
389 if (ea_namelist
== NULL
) {
391 return NT_STATUS_NO_MEMORY
;
397 for (p
= ea_namelist
; p
- ea_namelist
< sizeret
; p
+= strlen(p
)+1) {
398 names
[num_names
++] = p
;
406 /****************************************************************************
407 Return a linked list of the total EA's. Plus the total size
408 ****************************************************************************/
410 static NTSTATUS
get_ea_list_from_fsp(TALLOC_CTX
*mem_ctx
,
412 size_t *pea_total_len
,
413 struct ea_list
**ea_list
)
415 /* Get a list of all xattrs. Max namesize is 64k. */
418 struct ea_list
*ea_list_head
= NULL
;
419 bool posix_pathnames
= false;
430 if (!lp_ea_support(SNUM(fsp
->conn
))) {
434 if (fsp_is_alternate_stream(fsp
)) {
435 return NT_STATUS_INVALID_PARAMETER
;
438 posix_pathnames
= (fsp
->fsp_name
->flags
& SMB_FILENAME_POSIX_PATH
);
440 status
= get_ea_names_from_fsp(talloc_tos(),
445 if (!NT_STATUS_IS_OK(status
)) {
449 if (num_names
== 0) {
453 for (i
=0; i
<num_names
; i
++) {
454 struct ea_list
*listp
;
458 * POSIX EA names are divided into several namespaces by
459 * means of string prefixes. Usually, the system controls
460 * semantics for each namespace, but the 'user' namespace is
461 * available for arbitrary use, which comes closest to
462 * Windows EA semantics. Hence, we map POSIX EAs from the
463 * 'user' namespace to Windows EAs, and just ignore all the
464 * other namespaces. Also, a few specific names in the 'user'
465 * namespace are used by Samba internally. Filter them out as
466 * well, and only present the EAs that are available for
469 if (!strnequal(names
[i
], "user.", 5)
470 || samba_private_attr_name(names
[i
]))
474 * Filter out any underlying POSIX EA names
475 * that a Windows client can't handle.
477 if (!posix_pathnames
&&
478 is_invalid_windows_ea_name(names
[i
])) {
482 listp
= talloc(mem_ctx
, struct ea_list
);
484 return NT_STATUS_NO_MEMORY
;
487 status
= get_ea_value_fsp(listp
,
492 if (!NT_STATUS_IS_OK(status
)) {
497 if (listp
->ea
.value
.length
== 0) {
499 * We can never return a zero length EA.
500 * Windows reports the EA's as corrupted.
504 } else if (listp
->ea
.value
.length
> 65536) {
506 * SMB clients may report error with file
507 * if large EA is presented to them.
509 DBG_ERR("EA [%s] on file [%s] exceeds "
510 "maximum permitted EA size of 64KiB: %zu\n.",
511 listp
->ea
.name
, fsp_str_dbg(fsp
),
512 listp
->ea
.value
.length
);
517 push_ascii_fstring(dos_ea_name
, listp
->ea
.name
);
520 4 + strlen(dos_ea_name
) + 1 + listp
->ea
.value
.length
;
522 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
523 "= %u\n", (unsigned int)*pea_total_len
, dos_ea_name
,
524 (unsigned int)listp
->ea
.value
.length
));
526 DLIST_ADD_END(ea_list_head
, listp
);
530 /* Add on 4 for total length. */
531 if (*pea_total_len
) {
535 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
536 (unsigned int)*pea_total_len
));
538 *ea_list
= ea_list_head
;
542 /****************************************************************************
543 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
545 ****************************************************************************/
547 static unsigned int fill_ea_buffer(TALLOC_CTX
*mem_ctx
, char *pdata
, unsigned int total_data_size
,
548 connection_struct
*conn
, struct ea_list
*ea_list
)
550 unsigned int ret_data_size
= 4;
553 SMB_ASSERT(total_data_size
>= 4);
555 if (!lp_ea_support(SNUM(conn
))) {
560 for (p
= pdata
+ 4; ea_list
; ea_list
= ea_list
->next
) {
563 push_ascii_fstring(dos_ea_name
, ea_list
->ea
.name
);
564 dos_namelen
= strlen(dos_ea_name
);
565 if (dos_namelen
> 255 || dos_namelen
== 0) {
568 if (ea_list
->ea
.value
.length
> 65535) {
571 if (4 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
> total_data_size
) {
575 /* We know we have room. */
576 SCVAL(p
,0,ea_list
->ea
.flags
);
577 SCVAL(p
,1,dos_namelen
);
578 SSVAL(p
,2,ea_list
->ea
.value
.length
);
579 strlcpy(p
+4, dos_ea_name
, dos_namelen
+1);
580 if (ea_list
->ea
.value
.length
> 0) {
581 memcpy(p
+ 4 + dos_namelen
+ 1,
582 ea_list
->ea
.value
.data
,
583 ea_list
->ea
.value
.length
);
586 total_data_size
-= 4 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
;
587 p
+= 4 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
;
590 ret_data_size
= PTR_DIFF(p
, pdata
);
591 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size
));
592 SIVAL(pdata
,0,ret_data_size
);
593 return ret_data_size
;
596 static NTSTATUS
fill_ea_chained_buffer(TALLOC_CTX
*mem_ctx
,
598 unsigned int total_data_size
,
599 unsigned int *ret_data_size
,
600 connection_struct
*conn
,
601 struct ea_list
*ea_list
)
603 uint8_t *p
= (uint8_t *)pdata
;
604 uint8_t *last_start
= NULL
;
605 bool do_store_data
= (pdata
!= NULL
);
609 if (!lp_ea_support(SNUM(conn
))) {
610 return NT_STATUS_NO_EAS_ON_FILE
;
613 for (; ea_list
; ea_list
= ea_list
->next
) {
619 if (last_start
!= NULL
&& do_store_data
) {
620 SIVAL(last_start
, 0, PTR_DIFF(p
, last_start
));
624 push_ascii_fstring(dos_ea_name
, ea_list
->ea
.name
);
625 dos_namelen
= strlen(dos_ea_name
);
626 if (dos_namelen
> 255 || dos_namelen
== 0) {
627 return NT_STATUS_INTERNAL_ERROR
;
629 if (ea_list
->ea
.value
.length
> 65535) {
630 return NT_STATUS_INTERNAL_ERROR
;
633 this_size
= 0x08 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
;
636 pad
= (4 - (this_size
% 4)) % 4;
641 if (this_size
> total_data_size
) {
642 return NT_STATUS_INFO_LENGTH_MISMATCH
;
645 /* We know we have room. */
646 SIVAL(p
, 0x00, 0); /* next offset */
647 SCVAL(p
, 0x04, ea_list
->ea
.flags
);
648 SCVAL(p
, 0x05, dos_namelen
);
649 SSVAL(p
, 0x06, ea_list
->ea
.value
.length
);
650 strlcpy((char *)(p
+0x08), dos_ea_name
, dos_namelen
+1);
651 memcpy(p
+ 0x08 + dos_namelen
+ 1, ea_list
->ea
.value
.data
, ea_list
->ea
.value
.length
);
653 memset(p
+ 0x08 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
,
657 total_data_size
-= this_size
;
663 *ret_data_size
= PTR_DIFF(p
, pdata
);
664 DEBUG(10,("fill_ea_chained_buffer: data_size = %u\n", *ret_data_size
));
668 unsigned int estimate_ea_size(files_struct
*fsp
)
670 size_t total_ea_len
= 0;
672 struct ea_list
*ea_list
= NULL
;
680 if (!lp_ea_support(SNUM(fsp
->conn
))) {
684 mem_ctx
= talloc_stackframe();
686 /* If this is a stream fsp, then we need to instead find the
687 * estimated ea len from the main file, not the stream
688 * (streams cannot have EAs), but the estimate isn't just 0 in
690 fsp
= metadata_fsp(fsp
);
691 (void)get_ea_list_from_fsp(mem_ctx
,
696 if(fsp
->conn
->sconn
->using_smb2
) {
697 unsigned int ret_data_size
;
699 * We're going to be using fill_ea_chained_buffer() to
700 * marshall EA's - this size is significantly larger
701 * than the SMB1 buffer. Re-calculate the size without
704 status
= fill_ea_chained_buffer(mem_ctx
,
710 if (!NT_STATUS_IS_OK(status
)) {
713 total_ea_len
= ret_data_size
;
715 TALLOC_FREE(mem_ctx
);
719 /****************************************************************************
720 Ensure the EA name is case insensitive by matching any existing EA name.
721 ****************************************************************************/
723 static void canonicalize_ea_name(files_struct
*fsp
,
724 fstring unix_ea_name
)
727 TALLOC_CTX
*mem_ctx
= talloc_tos();
728 struct ea_list
*ea_list
;
729 NTSTATUS status
= get_ea_list_from_fsp(mem_ctx
,
733 if (!NT_STATUS_IS_OK(status
)) {
737 for (; ea_list
; ea_list
= ea_list
->next
) {
738 if (strequal(&unix_ea_name
[5], ea_list
->ea
.name
)) {
739 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
740 &unix_ea_name
[5], ea_list
->ea
.name
));
741 strlcpy(&unix_ea_name
[5], ea_list
->ea
.name
, sizeof(fstring
)-5);
747 /****************************************************************************
748 Set or delete an extended attribute.
749 ****************************************************************************/
751 NTSTATUS
set_ea(connection_struct
*conn
, files_struct
*fsp
,
752 struct ea_list
*ea_list
)
755 bool posix_pathnames
= false;
757 if (!lp_ea_support(SNUM(conn
))) {
758 return NT_STATUS_EAS_NOT_SUPPORTED
;
762 return NT_STATUS_INVALID_HANDLE
;
765 posix_pathnames
= (fsp
->fsp_name
->flags
& SMB_FILENAME_POSIX_PATH
);
767 status
= refuse_symlink_fsp(fsp
);
768 if (!NT_STATUS_IS_OK(status
)) {
772 status
= check_access_fsp(fsp
, FILE_WRITE_EA
);
773 if (!NT_STATUS_IS_OK(status
)) {
777 /* Setting EAs on streams isn't supported. */
778 if (fsp_is_alternate_stream(fsp
)) {
779 return NT_STATUS_INVALID_PARAMETER
;
783 * Filter out invalid Windows EA names - before
784 * we set *any* of them.
787 if (!posix_pathnames
&& ea_list_has_invalid_name(ea_list
)) {
788 return STATUS_INVALID_EA_NAME
;
791 for (;ea_list
; ea_list
= ea_list
->next
) {
793 fstring unix_ea_name
;
796 * Complementing the forward mapping from POSIX EAs to
797 * Windows EAs in get_ea_list_from_fsp(), here we map in the
798 * opposite direction from Windows EAs to the 'user' namespace
799 * of POSIX EAs. Hence, all POSIX EA names the we set here must
800 * start with a 'user.' prefix.
802 fstrcpy(unix_ea_name
, "user.");
803 fstrcat(unix_ea_name
, ea_list
->ea
.name
);
805 canonicalize_ea_name(fsp
, unix_ea_name
);
807 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name
, (unsigned int)ea_list
->ea
.value
.length
));
809 if (samba_private_attr_name(unix_ea_name
)) {
810 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name
));
811 return NT_STATUS_ACCESS_DENIED
;
814 if (ea_list
->ea
.value
.length
== 0) {
815 /* Remove the attribute. */
816 DBG_DEBUG("deleting ea name %s on "
817 "file %s by file descriptor.\n",
818 unix_ea_name
, fsp_str_dbg(fsp
));
819 ret
= SMB_VFS_FREMOVEXATTR(fsp
, unix_ea_name
);
821 /* Removing a non existent attribute always succeeds. */
822 if (ret
== -1 && errno
== ENOATTR
) {
823 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
829 DEBUG(10,("set_ea: setting ea name %s on file "
830 "%s by file descriptor.\n",
831 unix_ea_name
, fsp_str_dbg(fsp
)));
832 ret
= SMB_VFS_FSETXATTR(fsp
, unix_ea_name
,
833 ea_list
->ea
.value
.data
, ea_list
->ea
.value
.length
, 0);
838 if (errno
== ENOTSUP
) {
839 return NT_STATUS_EAS_NOT_SUPPORTED
;
842 return map_nt_error_from_unix(errno
);
849 /****************************************************************************
850 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
851 ****************************************************************************/
853 struct ea_list
*read_ea_list(TALLOC_CTX
*ctx
, const char *pdata
, size_t data_size
)
855 struct ea_list
*ea_list_head
= NULL
;
857 size_t bytes_used
= 0;
859 while (offset
< data_size
) {
860 struct ea_list
*eal
= read_ea_list_entry(ctx
, pdata
+ offset
, data_size
- offset
, &bytes_used
);
866 DLIST_ADD_END(ea_list_head
, eal
);
867 offset
+= bytes_used
;
873 /****************************************************************************
874 Count the total EA size needed.
875 ****************************************************************************/
877 static size_t ea_list_size(struct ea_list
*ealist
)
880 struct ea_list
*listp
;
883 for (listp
= ealist
; listp
; listp
= listp
->next
) {
884 push_ascii_fstring(dos_ea_name
, listp
->ea
.name
);
885 ret
+= 4 + strlen(dos_ea_name
) + 1 + listp
->ea
.value
.length
;
887 /* Add on 4 for total length. */
895 /****************************************************************************
896 Return a union of EA's from a file list and a list of names.
897 The TALLOC context for the two lists *MUST* be identical as we steal
898 memory from one list to add to another. JRA.
899 ****************************************************************************/
901 static struct ea_list
*ea_list_union(struct ea_list
*name_list
, struct ea_list
*file_list
, size_t *total_ea_len
)
903 struct ea_list
*nlistp
, *flistp
;
905 for (nlistp
= name_list
; nlistp
; nlistp
= nlistp
->next
) {
906 for (flistp
= file_list
; flistp
; flistp
= flistp
->next
) {
907 if (strequal(nlistp
->ea
.name
, flistp
->ea
.name
)) {
913 /* Copy the data from this entry. */
914 nlistp
->ea
.flags
= flistp
->ea
.flags
;
915 nlistp
->ea
.value
= flistp
->ea
.value
;
918 nlistp
->ea
.flags
= 0;
919 ZERO_STRUCT(nlistp
->ea
.value
);
923 *total_ea_len
= ea_list_size(name_list
);
927 /*********************************************************
928 Routine to check if a given string matches exactly.
929 as a special case a mask of "." does NOT match. That
930 is required for correct wildcard semantics
931 Case can be significant or not.
932 **********************************************************/
934 static bool exact_match(bool has_wild
,
939 if (mask
[0] == '.' && mask
[1] == 0) {
947 if (case_sensitive
) {
948 return strcmp(str
,mask
)==0;
950 return strcasecmp_m(str
,mask
) == 0;
954 /****************************************************************************
955 Return the filetype for UNIX extensions.
956 ****************************************************************************/
958 static uint32_t unix_filetype(mode_t mode
)
961 return UNIX_TYPE_FILE
;
962 else if(S_ISDIR(mode
))
963 return UNIX_TYPE_DIR
;
965 else if(S_ISLNK(mode
))
966 return UNIX_TYPE_SYMLINK
;
969 else if(S_ISCHR(mode
))
970 return UNIX_TYPE_CHARDEV
;
973 else if(S_ISBLK(mode
))
974 return UNIX_TYPE_BLKDEV
;
977 else if(S_ISFIFO(mode
))
978 return UNIX_TYPE_FIFO
;
981 else if(S_ISSOCK(mode
))
982 return UNIX_TYPE_SOCKET
;
985 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode
));
986 return UNIX_TYPE_UNKNOWN
;
989 /****************************************************************************
990 Map wire perms onto standard UNIX permissions. Obey share restrictions.
991 ****************************************************************************/
993 NTSTATUS
unix_perms_from_wire(connection_struct
*conn
,
994 const SMB_STRUCT_STAT
*psbuf
,
996 enum perm_type ptype
,
1001 if (perms
== SMB_MODE_NO_CHANGE
) {
1002 if (!VALID_STAT(*psbuf
)) {
1003 return NT_STATUS_INVALID_PARAMETER
;
1005 *ret_perms
= psbuf
->st_ex_mode
;
1006 return NT_STATUS_OK
;
1010 ret
= wire_perms_to_unix(perms
);
1012 if (ptype
== PERM_NEW_FILE
) {
1014 * "create mask"/"force create mode" are
1015 * only applied to new files, not existing ones.
1017 ret
&= lp_create_mask(SNUM(conn
));
1018 /* Add in force bits */
1019 ret
|= lp_force_create_mode(SNUM(conn
));
1020 } else if (ptype
== PERM_NEW_DIR
) {
1022 * "directory mask"/"force directory mode" are
1023 * only applied to new directories, not existing ones.
1025 ret
&= lp_directory_mask(SNUM(conn
));
1026 /* Add in force bits */
1027 ret
|= lp_force_directory_mode(SNUM(conn
));
1031 return NT_STATUS_OK
;
1034 /****************************************************************************
1035 Needed to show the msdfs symlinks as directories. Modifies psbuf
1036 to be a directory if it's a msdfs link.
1037 ****************************************************************************/
1039 static bool check_msdfs_link(struct files_struct
*dirfsp
,
1040 struct smb_filename
*atname
,
1041 struct smb_filename
*smb_fname
)
1043 int saved_errno
= errno
;
1044 if(lp_host_msdfs() &&
1045 lp_msdfs_root(SNUM(dirfsp
->conn
)) &&
1046 is_msdfs_link(dirfsp
, atname
)) {
1049 * Copy the returned stat struct from the relative
1050 * to the full pathname.
1052 smb_fname
->st
= atname
->st
;
1054 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1056 smb_fname
->base_name
));
1057 smb_fname
->st
.st_ex_mode
=
1058 (smb_fname
->st
.st_ex_mode
& 0xFFF) | S_IFDIR
;
1059 errno
= saved_errno
;
1062 errno
= saved_errno
;
1067 /****************************************************************************
1068 Get a level dependent lanman2 dir entry.
1069 ****************************************************************************/
1071 struct smbd_dirptr_lanman2_state
{
1072 connection_struct
*conn
;
1073 uint32_t info_level
;
1074 bool check_mangled_names
;
1076 bool got_exact_match
;
1077 bool case_sensitive
;
1080 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX
*ctx
,
1086 struct smbd_dirptr_lanman2_state
*state
=
1087 (struct smbd_dirptr_lanman2_state
*)private_data
;
1089 char mangled_name
[13]; /* mangled 8.3 name. */
1093 /* Mangle fname if it's an illegal name. */
1094 if (mangle_must_mangle(dname
, state
->conn
->params
)) {
1096 * Slow path - ensure we can push the original name as UCS2. If
1097 * not, then just don't return this name.
1101 size_t len
= (strlen(dname
) + 2) * 4; /* Allow enough space. */
1102 uint8_t *tmp
= talloc_array(talloc_tos(),
1106 status
= srvstr_push(NULL
,
1107 FLAGS2_UNICODE_STRINGS
,
1116 if (!NT_STATUS_IS_OK(status
)) {
1120 ok
= name_to_8_3(dname
, mangled_name
,
1121 true, state
->conn
->params
);
1125 fname
= mangled_name
;
1130 got_match
= exact_match(state
->has_wild
,
1131 state
->case_sensitive
,
1133 state
->got_exact_match
= got_match
;
1135 got_match
= mask_match(fname
, mask
,
1136 state
->case_sensitive
);
1139 if(!got_match
&& state
->check_mangled_names
&&
1140 !mangle_is_8_3(fname
, false, state
->conn
->params
)) {
1142 * It turns out that NT matches wildcards against
1143 * both long *and* short names. This may explain some
1144 * of the wildcard wierdness from old DOS clients
1145 * that some people have been seeing.... JRA.
1147 /* Force the mangling into 8.3. */
1148 ok
= name_to_8_3(fname
, mangled_name
,
1149 false, state
->conn
->params
);
1154 got_match
= exact_match(state
->has_wild
,
1155 state
->case_sensitive
,
1156 mangled_name
, mask
);
1157 state
->got_exact_match
= got_match
;
1159 got_match
= mask_match(mangled_name
, mask
,
1160 state
->case_sensitive
);
1168 *_fname
= talloc_strdup(ctx
, fname
);
1169 if (*_fname
== NULL
) {
1176 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX
*ctx
,
1178 struct files_struct
*dirfsp
,
1179 struct smb_filename
*atname
,
1180 struct smb_filename
*smb_fname
,
1184 struct smbd_dirptr_lanman2_state
*state
=
1185 (struct smbd_dirptr_lanman2_state
*)private_data
;
1186 bool ms_dfs_link
= false;
1188 if (smb_fname
->flags
& SMB_FILENAME_POSIX_PATH
) {
1189 if (SMB_VFS_LSTAT(state
->conn
, smb_fname
) != 0) {
1190 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1191 "Couldn't lstat [%s] (%s)\n",
1192 smb_fname_str_dbg(smb_fname
),
1199 if (!VALID_STAT(smb_fname
->st
) &&
1200 SMB_VFS_STAT(state
->conn
, smb_fname
) != 0) {
1201 /* Needed to show the msdfs symlinks as
1204 ms_dfs_link
= check_msdfs_link(dirfsp
,
1208 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1209 "Couldn't stat [%s] (%s)\n",
1210 smb_fname_str_dbg(smb_fname
),
1215 *_mode
= dos_mode_msdfs(state
->conn
, smb_fname
);
1223 *_mode
= fdos_mode(smb_fname
->fsp
);
1224 smb_fname
->st
= smb_fname
->fsp
->fsp_name
->st
;
1229 static NTSTATUS
smbd_marshall_dir_entry(TALLOC_CTX
*ctx
,
1230 connection_struct
*conn
,
1232 uint32_t info_level
,
1233 struct ea_list
*name_list
,
1234 bool check_mangled_names
,
1235 bool requires_resume_key
,
1238 const struct smb_filename
*smb_fname
,
1239 int space_remaining
,
1245 uint64_t *last_entry_off
)
1247 char *p
, *q
, *pdata
= *ppdata
;
1249 uint64_t file_size
= 0;
1250 uint64_t allocation_size
= 0;
1251 uint64_t file_id
= 0;
1253 struct timespec mdate_ts
= {0};
1254 struct timespec adate_ts
= {0};
1255 struct timespec cdate_ts
= {0};
1256 struct timespec create_date_ts
= {0};
1257 time_t mdate
= (time_t)0, adate
= (time_t)0, create_date
= (time_t)0;
1259 char *last_entry_ptr
;
1264 struct readdir_attr_data
*readdir_attr_data
= NULL
;
1266 if (!(mode
& FILE_ATTRIBUTE_DIRECTORY
)) {
1267 file_size
= get_file_size_stat(&smb_fname
->st
);
1269 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
, NULL
, &smb_fname
->st
);
1272 * Skip SMB_VFS_FREADDIR_ATTR if the directory entry is a symlink or
1275 if (smb_fname
->fsp
!= NULL
&&
1276 !(mode
& FILE_ATTRIBUTE_REPARSE_POINT
)) {
1277 status
= SMB_VFS_FREADDIR_ATTR(smb_fname
->fsp
,
1279 &readdir_attr_data
);
1280 if (!NT_STATUS_IS_OK(status
)) {
1281 if (!NT_STATUS_EQUAL(NT_STATUS_NOT_SUPPORTED
,
1288 file_id
= SMB_VFS_FS_FILE_ID(conn
, &smb_fname
->st
);
1290 mdate_ts
= smb_fname
->st
.st_ex_mtime
;
1291 adate_ts
= smb_fname
->st
.st_ex_atime
;
1292 create_date_ts
= get_create_timespec(conn
, NULL
, smb_fname
);
1293 cdate_ts
= get_change_timespec(conn
, NULL
, smb_fname
);
1295 if (lp_dos_filetime_resolution(SNUM(conn
))) {
1296 dos_filetime_timespec(&create_date_ts
);
1297 dos_filetime_timespec(&mdate_ts
);
1298 dos_filetime_timespec(&adate_ts
);
1299 dos_filetime_timespec(&cdate_ts
);
1302 create_date
= convert_timespec_to_time_t(create_date_ts
);
1303 mdate
= convert_timespec_to_time_t(mdate_ts
);
1304 adate
= convert_timespec_to_time_t(adate_ts
);
1306 /* align the record */
1307 SMB_ASSERT(align
>= 1);
1309 off
= (int)PTR_DIFF(pdata
, base_data
);
1310 pad
= (off
+ (align
-1)) & ~(align
-1);
1313 if (pad
&& pad
> space_remaining
) {
1314 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1315 "for padding (wanted %u, had %d)\n",
1318 return STATUS_MORE_ENTRIES
; /* Not finished - just out of space */
1322 /* initialize padding to 0 */
1324 memset(pdata
, 0, pad
);
1326 space_remaining
-= pad
;
1328 DEBUG(10,("smbd_marshall_dir_entry: space_remaining = %d\n",
1338 switch (info_level
) {
1339 case SMB_FIND_INFO_STANDARD
:
1340 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1341 if(requires_resume_key
) {
1345 srv_put_dos_date2(p
,0,create_date
);
1346 srv_put_dos_date2(p
,4,adate
);
1347 srv_put_dos_date2(p
,8,mdate
);
1348 SIVAL(p
,12,(uint32_t)file_size
);
1349 SIVAL(p
,16,(uint32_t)allocation_size
);
1353 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1354 p
+= ucs2_align(base_data
, p
, 0);
1356 status
= srvstr_push(base_data
, flags2
, p
,
1357 fname
, PTR_DIFF(end_data
, p
),
1358 STR_TERMINATE
, &len
);
1359 if (!NT_STATUS_IS_OK(status
)) {
1362 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1364 SCVAL(nameptr
, -1, len
- 2);
1366 SCVAL(nameptr
, -1, 0);
1370 SCVAL(nameptr
, -1, len
- 1);
1372 SCVAL(nameptr
, -1, 0);
1378 case SMB_FIND_EA_SIZE
:
1379 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
1380 if (requires_resume_key
) {
1384 srv_put_dos_date2(p
,0,create_date
);
1385 srv_put_dos_date2(p
,4,adate
);
1386 srv_put_dos_date2(p
,8,mdate
);
1387 SIVAL(p
,12,(uint32_t)file_size
);
1388 SIVAL(p
,16,(uint32_t)allocation_size
);
1391 unsigned int ea_size
= estimate_ea_size(smb_fname
->fsp
);
1392 SIVAL(p
,22,ea_size
); /* Extended attributes */
1396 status
= srvstr_push(base_data
, flags2
,
1397 p
, fname
, PTR_DIFF(end_data
, p
),
1398 STR_TERMINATE
| STR_NOALIGN
, &len
);
1399 if (!NT_STATUS_IS_OK(status
)) {
1402 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1415 SCVAL(nameptr
,0,len
);
1417 SCVAL(p
,0,0); p
+= 1; /* Extra zero byte ? - why.. */
1420 case SMB_FIND_EA_LIST
:
1422 struct ea_list
*file_list
= NULL
;
1425 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
1427 return NT_STATUS_INVALID_PARAMETER
;
1429 if (requires_resume_key
) {
1433 srv_put_dos_date2(p
,0,create_date
);
1434 srv_put_dos_date2(p
,4,adate
);
1435 srv_put_dos_date2(p
,8,mdate
);
1436 SIVAL(p
,12,(uint32_t)file_size
);
1437 SIVAL(p
,16,(uint32_t)allocation_size
);
1439 p
+= 22; /* p now points to the EA area. */
1441 status
= get_ea_list_from_fsp(ctx
,
1443 &ea_len
, &file_list
);
1444 if (!NT_STATUS_IS_OK(status
)) {
1447 name_list
= ea_list_union(name_list
, file_list
, &ea_len
);
1449 /* We need to determine if this entry will fit in the space available. */
1450 /* Max string size is 255 bytes. */
1451 if (PTR_DIFF(p
+ 255 + ea_len
,pdata
) > space_remaining
) {
1452 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1453 "(wanted %u, had %d)\n",
1454 (unsigned int)PTR_DIFF(p
+ 255 + ea_len
,pdata
),
1456 return STATUS_MORE_ENTRIES
; /* Not finished - just out of space */
1459 /* Push the ea_data followed by the name. */
1460 p
+= fill_ea_buffer(ctx
, p
, space_remaining
, conn
, name_list
);
1462 status
= srvstr_push(base_data
, flags2
,
1463 p
+ 1, fname
, PTR_DIFF(end_data
, p
+1),
1464 STR_TERMINATE
| STR_NOALIGN
, &len
);
1465 if (!NT_STATUS_IS_OK(status
)) {
1468 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1481 SCVAL(nameptr
,0,len
);
1483 SCVAL(p
,0,0); p
+= 1; /* Extra zero byte ? - why.. */
1487 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
1488 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1489 was_8_3
= mangle_is_8_3(fname
, True
, conn
->params
);
1491 SIVAL(p
,0,reskey
); p
+= 4;
1492 put_long_date_full_timespec(conn
->ts_res
,p
,&create_date_ts
); p
+= 8;
1493 put_long_date_full_timespec(conn
->ts_res
,p
,&adate_ts
); p
+= 8;
1494 put_long_date_full_timespec(conn
->ts_res
,p
,&mdate_ts
); p
+= 8;
1495 put_long_date_full_timespec(conn
->ts_res
,p
,&cdate_ts
); p
+= 8;
1496 SOFF_T(p
,0,file_size
); p
+= 8;
1497 SOFF_T(p
,0,allocation_size
); p
+= 8;
1498 SIVAL(p
,0,mode
); p
+= 4;
1499 q
= p
; p
+= 4; /* q is placeholder for name length. */
1500 if (mode
& FILE_ATTRIBUTE_REPARSE_POINT
) {
1501 SIVAL(p
, 0, IO_REPARSE_TAG_DFS
);
1503 unsigned int ea_size
= estimate_ea_size(smb_fname
->fsp
);
1504 SIVAL(p
,0,ea_size
); /* Extended attributes */
1507 /* Clear the short name buffer. This is
1508 * IMPORTANT as not doing so will trigger
1509 * a Win2k client bug. JRA.
1511 if (!was_8_3
&& check_mangled_names
) {
1512 char mangled_name
[13]; /* mangled 8.3 name. */
1513 if (!name_to_8_3(fname
,mangled_name
,True
,
1515 /* Error - mangle failed ! */
1516 memset(mangled_name
,'\0',12);
1518 mangled_name
[12] = 0;
1519 status
= srvstr_push(base_data
, flags2
,
1520 p
+2, mangled_name
, 24,
1521 STR_UPPER
|STR_UNICODE
, &len
);
1522 if (!NT_STATUS_IS_OK(status
)) {
1526 memset(p
+ 2 + len
,'\0',24 - len
);
1533 status
= srvstr_push(base_data
, flags2
, p
,
1534 fname
, PTR_DIFF(end_data
, p
),
1535 STR_TERMINATE_ASCII
, &len
);
1536 if (!NT_STATUS_IS_OK(status
)) {
1542 len
= PTR_DIFF(p
, pdata
);
1543 pad
= (len
+ (align
-1)) & ~(align
-1);
1545 * offset to the next entry, the caller
1546 * will overwrite it for the last entry
1547 * that's why we always include the padding
1551 * set padding to zero
1554 memset(p
, 0, pad
- len
);
1561 case SMB_FIND_FILE_DIRECTORY_INFO
:
1562 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1564 SIVAL(p
,0,reskey
); p
+= 4;
1565 put_long_date_full_timespec(conn
->ts_res
,p
,&create_date_ts
); p
+= 8;
1566 put_long_date_full_timespec(conn
->ts_res
,p
,&adate_ts
); p
+= 8;
1567 put_long_date_full_timespec(conn
->ts_res
,p
,&mdate_ts
); p
+= 8;
1568 put_long_date_full_timespec(conn
->ts_res
,p
,&cdate_ts
); p
+= 8;
1569 SOFF_T(p
,0,file_size
); p
+= 8;
1570 SOFF_T(p
,0,allocation_size
); p
+= 8;
1571 SIVAL(p
,0,mode
); p
+= 4;
1572 status
= srvstr_push(base_data
, flags2
,
1573 p
+ 4, fname
, PTR_DIFF(end_data
, p
+4),
1574 STR_TERMINATE_ASCII
, &len
);
1575 if (!NT_STATUS_IS_OK(status
)) {
1581 len
= PTR_DIFF(p
, pdata
);
1582 pad
= (len
+ (align
-1)) & ~(align
-1);
1584 * offset to the next entry, the caller
1585 * will overwrite it for the last entry
1586 * that's why we always include the padding
1590 * set padding to zero
1593 memset(p
, 0, pad
- len
);
1600 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
1601 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1603 SIVAL(p
,0,reskey
); p
+= 4;
1604 put_long_date_full_timespec(conn
->ts_res
,p
,&create_date_ts
); p
+= 8;
1605 put_long_date_full_timespec(conn
->ts_res
,p
,&adate_ts
); p
+= 8;
1606 put_long_date_full_timespec(conn
->ts_res
,p
,&mdate_ts
); p
+= 8;
1607 put_long_date_full_timespec(conn
->ts_res
,p
,&cdate_ts
); p
+= 8;
1608 SOFF_T(p
,0,file_size
); p
+= 8;
1609 SOFF_T(p
,0,allocation_size
); p
+= 8;
1610 SIVAL(p
,0,mode
); p
+= 4;
1611 q
= p
; p
+= 4; /* q is placeholder for name length. */
1612 if (mode
& FILE_ATTRIBUTE_REPARSE_POINT
) {
1613 SIVAL(p
, 0, IO_REPARSE_TAG_DFS
);
1615 unsigned int ea_size
= estimate_ea_size(smb_fname
->fsp
);
1616 SIVAL(p
,0,ea_size
); /* Extended attributes */
1619 status
= srvstr_push(base_data
, flags2
, p
,
1620 fname
, PTR_DIFF(end_data
, p
),
1621 STR_TERMINATE_ASCII
, &len
);
1622 if (!NT_STATUS_IS_OK(status
)) {
1628 len
= PTR_DIFF(p
, pdata
);
1629 pad
= (len
+ (align
-1)) & ~(align
-1);
1631 * offset to the next entry, the caller
1632 * will overwrite it for the last entry
1633 * that's why we always include the padding
1637 * set padding to zero
1640 memset(p
, 0, pad
- len
);
1647 case SMB_FIND_FILE_NAMES_INFO
:
1648 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1650 SIVAL(p
,0,reskey
); p
+= 4;
1652 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1653 acl on a dir (tridge) */
1654 status
= srvstr_push(base_data
, flags2
, p
,
1655 fname
, PTR_DIFF(end_data
, p
),
1656 STR_TERMINATE_ASCII
, &len
);
1657 if (!NT_STATUS_IS_OK(status
)) {
1663 len
= PTR_DIFF(p
, pdata
);
1664 pad
= (len
+ (align
-1)) & ~(align
-1);
1666 * offset to the next entry, the caller
1667 * will overwrite it for the last entry
1668 * that's why we always include the padding
1672 * set padding to zero
1675 memset(p
, 0, pad
- len
);
1682 case SMB_FIND_ID_FULL_DIRECTORY_INFO
:
1683 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1685 SIVAL(p
,0,reskey
); p
+= 4;
1686 put_long_date_full_timespec(conn
->ts_res
,p
,&create_date_ts
); p
+= 8;
1687 put_long_date_full_timespec(conn
->ts_res
,p
,&adate_ts
); p
+= 8;
1688 put_long_date_full_timespec(conn
->ts_res
,p
,&mdate_ts
); p
+= 8;
1689 put_long_date_full_timespec(conn
->ts_res
,p
,&cdate_ts
); p
+= 8;
1690 SOFF_T(p
,0,file_size
); p
+= 8;
1691 SOFF_T(p
,0,allocation_size
); p
+= 8;
1692 SIVAL(p
,0,mode
); p
+= 4;
1693 q
= p
; p
+= 4; /* q is placeholder for name length. */
1694 if (mode
& FILE_ATTRIBUTE_REPARSE_POINT
) {
1695 SIVAL(p
, 0, IO_REPARSE_TAG_DFS
);
1697 unsigned int ea_size
= estimate_ea_size(smb_fname
->fsp
);
1698 SIVAL(p
,0,ea_size
); /* Extended attributes */
1701 SIVAL(p
,0,0); p
+= 4; /* Unknown - reserved ? */
1702 SBVAL(p
,0,file_id
); p
+= 8;
1703 status
= srvstr_push(base_data
, flags2
, p
,
1704 fname
, PTR_DIFF(end_data
, p
),
1705 STR_TERMINATE_ASCII
, &len
);
1706 if (!NT_STATUS_IS_OK(status
)) {
1712 len
= PTR_DIFF(p
, pdata
);
1713 pad
= (len
+ (align
-1)) & ~(align
-1);
1715 * offset to the next entry, the caller
1716 * will overwrite it for the last entry
1717 * that's why we always include the padding
1721 * set padding to zero
1724 memset(p
, 0, pad
- len
);
1731 case SMB_FIND_ID_BOTH_DIRECTORY_INFO
:
1732 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1733 was_8_3
= mangle_is_8_3(fname
, True
, conn
->params
);
1735 SIVAL(p
,0,reskey
); p
+= 4;
1736 put_long_date_full_timespec(conn
->ts_res
,p
,&create_date_ts
); p
+= 8;
1737 put_long_date_full_timespec(conn
->ts_res
,p
,&adate_ts
); p
+= 8;
1738 put_long_date_full_timespec(conn
->ts_res
,p
,&mdate_ts
); p
+= 8;
1739 put_long_date_full_timespec(conn
->ts_res
,p
,&cdate_ts
); p
+= 8;
1740 SOFF_T(p
,0,file_size
); p
+= 8;
1741 SOFF_T(p
,0,allocation_size
); p
+= 8;
1742 SIVAL(p
,0,mode
); p
+= 4;
1743 q
= p
; p
+= 4; /* q is placeholder for name length */
1744 if (mode
& FILE_ATTRIBUTE_REPARSE_POINT
) {
1745 SIVAL(p
, 0, IO_REPARSE_TAG_DFS
);
1746 } else if (readdir_attr_data
&&
1747 readdir_attr_data
->type
== RDATTR_AAPL
) {
1749 * OS X specific SMB2 extension negotiated via
1750 * AAPL create context: return max_access in
1753 SIVAL(p
, 0, readdir_attr_data
->attr_data
.aapl
.max_access
);
1755 unsigned int ea_size
= estimate_ea_size(smb_fname
->fsp
);
1756 SIVAL(p
,0,ea_size
); /* Extended attributes */
1760 if (readdir_attr_data
&&
1761 readdir_attr_data
->type
== RDATTR_AAPL
) {
1763 * OS X specific SMB2 extension negotiated via
1764 * AAPL create context: return resource fork
1765 * length and compressed FinderInfo in
1768 * According to documentation short_name_len
1769 * should be 0, but on the wire behaviour
1770 * shows its set to 24 by clients.
1774 /* Resourefork length */
1775 SBVAL(p
, 2, readdir_attr_data
->attr_data
.aapl
.rfork_size
);
1777 /* Compressed FinderInfo */
1778 memcpy(p
+ 10, &readdir_attr_data
->attr_data
.aapl
.finder_info
, 16);
1779 } else if (!was_8_3
&& check_mangled_names
) {
1780 char mangled_name
[13]; /* mangled 8.3 name. */
1781 if (!name_to_8_3(fname
,mangled_name
,True
,
1783 /* Error - mangle failed ! */
1784 memset(mangled_name
,'\0',12);
1786 mangled_name
[12] = 0;
1787 status
= srvstr_push(base_data
, flags2
,
1788 p
+2, mangled_name
, 24,
1789 STR_UPPER
|STR_UNICODE
, &len
);
1790 if (!NT_STATUS_IS_OK(status
)) {
1795 memset(p
+ 2 + len
,'\0',24 - len
);
1799 /* Clear the short name buffer. This is
1800 * IMPORTANT as not doing so will trigger
1801 * a Win2k client bug. JRA.
1808 if (readdir_attr_data
&&
1809 readdir_attr_data
->type
== RDATTR_AAPL
) {
1811 * OS X specific SMB2 extension negotiated via
1812 * AAPL create context: return UNIX mode in
1815 uint16_t aapl_mode
= (uint16_t)readdir_attr_data
->attr_data
.aapl
.unix_mode
;
1816 SSVAL(p
, 0, aapl_mode
);
1822 SBVAL(p
,0,file_id
); p
+= 8;
1823 status
= srvstr_push(base_data
, flags2
, p
,
1824 fname
, PTR_DIFF(end_data
, p
),
1825 STR_TERMINATE_ASCII
, &len
);
1826 if (!NT_STATUS_IS_OK(status
)) {
1832 len
= PTR_DIFF(p
, pdata
);
1833 pad
= (len
+ (align
-1)) & ~(align
-1);
1835 * offset to the next entry, the caller
1836 * will overwrite it for the last entry
1837 * that's why we always include the padding
1841 * set padding to zero
1844 memset(p
, 0, pad
- len
);
1851 /* CIFS UNIX Extension. */
1853 case SMB_FIND_FILE_UNIX
:
1854 case SMB_FIND_FILE_UNIX_INFO2
:
1856 SIVAL(p
,0,reskey
); p
+= 4; /* Used for continuing search. */
1858 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1860 if (info_level
== SMB_FIND_FILE_UNIX
) {
1861 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
1862 p
= store_file_unix_basic(conn
, p
,
1863 NULL
, &smb_fname
->st
);
1864 status
= srvstr_push(base_data
, flags2
, p
,
1865 fname
, PTR_DIFF(end_data
, p
),
1866 STR_TERMINATE
, &len
);
1867 if (!NT_STATUS_IS_OK(status
)) {
1871 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
1872 p
= store_file_unix_basic_info2(conn
, p
,
1873 NULL
, &smb_fname
->st
);
1876 status
= srvstr_push(base_data
, flags2
, p
, fname
,
1877 PTR_DIFF(end_data
, p
), 0, &len
);
1878 if (!NT_STATUS_IS_OK(status
)) {
1881 SIVAL(nameptr
, 0, len
);
1886 len
= PTR_DIFF(p
, pdata
);
1887 pad
= (len
+ (align
-1)) & ~(align
-1);
1889 * offset to the next entry, the caller
1890 * will overwrite it for the last entry
1891 * that's why we always include the padding
1895 * set padding to zero
1898 memset(p
, 0, pad
- len
);
1903 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1908 return NT_STATUS_INVALID_LEVEL
;
1911 if (PTR_DIFF(p
,pdata
) > space_remaining
) {
1912 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1913 "(wanted %u, had %d)\n",
1914 (unsigned int)PTR_DIFF(p
,pdata
),
1916 return STATUS_MORE_ENTRIES
; /* Not finished - just out of space */
1919 /* Setup the last entry pointer, as an offset from base_data */
1920 *last_entry_off
= PTR_DIFF(last_entry_ptr
,base_data
);
1921 /* Advance the data pointer to the next slot */
1924 return NT_STATUS_OK
;
1927 NTSTATUS
smbd_dirptr_lanman2_entry(TALLOC_CTX
*ctx
,
1928 connection_struct
*conn
,
1929 struct dptr_struct
*dirptr
,
1931 const char *path_mask
,
1934 int requires_resume_key
,
1943 int space_remaining
,
1944 struct smb_filename
**_smb_fname
,
1945 bool *got_exact_match
,
1946 int *_last_entry_off
,
1947 struct ea_list
*name_list
,
1948 struct file_id
*file_id
)
1951 const char *mask
= NULL
;
1952 long prev_dirpos
= 0;
1955 struct smb_filename
*smb_fname
= NULL
;
1956 struct smbd_dirptr_lanman2_state state
;
1958 uint64_t last_entry_off
= 0;
1960 enum mangled_names_options mangled_names
;
1961 bool marshall_with_83_names
;
1963 mangled_names
= lp_mangled_names(conn
->params
);
1967 state
.info_level
= info_level
;
1968 if (mangled_names
!= MANGLED_NAMES_NO
) {
1969 state
.check_mangled_names
= true;
1971 state
.has_wild
= dptr_has_wild(dirptr
);
1972 state
.got_exact_match
= false;
1973 state
.case_sensitive
= dptr_case_sensitive(dirptr
);
1975 *got_exact_match
= false;
1977 p
= strrchr_m(path_mask
,'/');
1988 ok
= smbd_dirptr_get_entry(ctx
,
1995 smbd_dirptr_lanman2_match_fn
,
1996 smbd_dirptr_lanman2_mode_fn
,
2003 return NT_STATUS_END_OF_FILE
;
2006 *got_exact_match
= state
.got_exact_match
;
2008 marshall_with_83_names
= (mangled_names
== MANGLED_NAMES_YES
);
2010 status
= smbd_marshall_dir_entry(ctx
,
2015 marshall_with_83_names
,
2016 requires_resume_key
,
2027 if (NT_STATUS_EQUAL(status
, NT_STATUS_ILLEGAL_CHARACTER
)) {
2028 DEBUG(1,("Conversion error: illegal character: %s\n",
2029 smb_fname_str_dbg(smb_fname
)));
2032 if (file_id
!= NULL
) {
2033 *file_id
= vfs_file_id_from_sbuf(conn
, &smb_fname
->st
);
2036 if (!NT_STATUS_IS_OK(status
) &&
2037 !NT_STATUS_EQUAL(status
, STATUS_MORE_ENTRIES
))
2039 TALLOC_FREE(smb_fname
);
2044 if (_smb_fname
!= NULL
) {
2046 * smb_fname is already talloc'ed off ctx.
2047 * We just need to make sure we don't return
2048 * any stream_name, and replace base_name
2049 * with fname in case base_name got mangled.
2050 * This allows us to preserve any smb_fname->fsp
2051 * for asynchronous handle lookups.
2053 TALLOC_FREE(smb_fname
->stream_name
);
2054 TALLOC_FREE(smb_fname
->base_name
);
2055 smb_fname
->base_name
= talloc_strdup(smb_fname
, fname
);
2057 if (smb_fname
->base_name
== NULL
) {
2058 TALLOC_FREE(smb_fname
);
2060 return NT_STATUS_NO_MEMORY
;
2062 *_smb_fname
= smb_fname
;
2064 TALLOC_FREE(smb_fname
);
2068 if (NT_STATUS_EQUAL(status
, STATUS_MORE_ENTRIES
)) {
2069 dptr_SeekDir(dirptr
, prev_dirpos
);
2073 *_last_entry_off
= last_entry_off
;
2074 return NT_STATUS_OK
;
2077 unsigned char *create_volume_objectid(connection_struct
*conn
, unsigned char objid
[16])
2079 const struct loadparm_substitution
*lp_sub
=
2080 loadparm_s3_global_substitution();
2082 E_md4hash(lp_servicename(talloc_tos(), lp_sub
, SNUM(conn
)),objid
);
2086 static void samba_extended_info_version(struct smb_extended_info
*extended_info
)
2088 SMB_ASSERT(extended_info
!= NULL
);
2090 extended_info
->samba_magic
= SAMBA_EXTENDED_INFO_MAGIC
;
2091 extended_info
->samba_version
= ((SAMBA_VERSION_MAJOR
& 0xff) << 24)
2092 | ((SAMBA_VERSION_MINOR
& 0xff) << 16)
2093 | ((SAMBA_VERSION_RELEASE
& 0xff) << 8);
2094 #ifdef SAMBA_VERSION_REVISION
2095 extended_info
->samba_version
|= (tolower(*SAMBA_VERSION_REVISION
) - 'a' + 1) & 0xff;
2097 extended_info
->samba_subversion
= 0;
2098 #ifdef SAMBA_VERSION_RC_RELEASE
2099 extended_info
->samba_subversion
|= (SAMBA_VERSION_RC_RELEASE
& 0xff) << 24;
2101 #ifdef SAMBA_VERSION_PRE_RELEASE
2102 extended_info
->samba_subversion
|= (SAMBA_VERSION_PRE_RELEASE
& 0xff) << 16;
2105 #ifdef SAMBA_VERSION_VENDOR_PATCH
2106 extended_info
->samba_subversion
|= (SAMBA_VERSION_VENDOR_PATCH
& 0xffff);
2108 extended_info
->samba_gitcommitdate
= 0;
2109 #ifdef SAMBA_VERSION_COMMIT_TIME
2110 unix_to_nt_time(&extended_info
->samba_gitcommitdate
, SAMBA_VERSION_COMMIT_TIME
);
2113 memset(extended_info
->samba_version_string
, 0,
2114 sizeof(extended_info
->samba_version_string
));
2116 snprintf (extended_info
->samba_version_string
,
2117 sizeof(extended_info
->samba_version_string
),
2118 "%s", samba_version_string());
2121 NTSTATUS
smbd_do_qfsinfo(struct smbXsrv_connection
*xconn
,
2122 connection_struct
*conn
,
2123 TALLOC_CTX
*mem_ctx
,
2124 uint16_t info_level
,
2126 unsigned int max_data_bytes
,
2127 size_t *fixed_portion
,
2128 struct smb_filename
*fname
,
2132 const struct loadparm_substitution
*lp_sub
=
2133 loadparm_s3_global_substitution();
2134 char *pdata
, *end_data
;
2137 const char *vname
= volume_label(talloc_tos(), SNUM(conn
));
2138 int snum
= SNUM(conn
);
2139 const char *fstype
= lp_fstype(SNUM(conn
));
2140 const char *filename
= NULL
;
2141 const uint64_t bytes_per_sector
= 512;
2142 uint32_t additional_flags
= 0;
2143 struct smb_filename smb_fname
;
2145 NTSTATUS status
= NT_STATUS_OK
;
2149 if (fname
== NULL
|| fname
->base_name
== NULL
) {
2152 filename
= fname
->base_name
;
2156 if (info_level
!= SMB_QUERY_CIFS_UNIX_INFO
) {
2157 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
2158 "info level (0x%x) on IPC$.\n",
2159 (unsigned int)info_level
));
2160 return NT_STATUS_ACCESS_DENIED
;
2164 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level
));
2166 smb_fname
= (struct smb_filename
) {
2167 .base_name
= discard_const_p(char, filename
),
2168 .flags
= fname
? fname
->flags
: 0,
2169 .twrp
= fname
? fname
->twrp
: 0,
2172 if(info_level
!= SMB_FS_QUOTA_INFORMATION
2173 && SMB_VFS_STAT(conn
, &smb_fname
) != 0) {
2174 DEBUG(2,("stat of . failed (%s)\n", strerror(errno
)));
2175 return map_nt_error_from_unix(errno
);
2180 if (max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
< max_data_bytes
) {
2181 return NT_STATUS_INVALID_PARAMETER
;
2184 *ppdata
= (char *)SMB_REALLOC(
2185 *ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
2186 if (*ppdata
== NULL
) {
2187 return NT_STATUS_NO_MEMORY
;
2191 memset((char *)pdata
,'\0',max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
2192 end_data
= pdata
+ max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
- 1;
2196 switch (info_level
) {
2197 case SMB_INFO_ALLOCATION
:
2199 uint64_t dfree
,dsize
,bsize
,block_size
,sectors_per_unit
;
2201 df_ret
= get_dfree_info(conn
, &smb_fname
, &bsize
,
2203 if (df_ret
== (uint64_t)-1) {
2204 return map_nt_error_from_unix(errno
);
2207 block_size
= lp_block_size(snum
);
2208 if (bsize
< block_size
) {
2209 uint64_t factor
= block_size
/bsize
;
2214 if (bsize
> block_size
) {
2215 uint64_t factor
= bsize
/block_size
;
2220 sectors_per_unit
= bsize
/bytes_per_sector
;
2222 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2223 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st
.st_ex_dev
, (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
2224 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
2227 * For large drives, return max values and not modulo.
2229 dsize
= MIN(dsize
, UINT32_MAX
);
2230 dfree
= MIN(dfree
, UINT32_MAX
);
2232 SIVAL(pdata
,l1_idFileSystem
,st
.st_ex_dev
);
2233 SIVAL(pdata
,l1_cSectorUnit
,sectors_per_unit
);
2234 SIVAL(pdata
,l1_cUnit
,dsize
);
2235 SIVAL(pdata
,l1_cUnitAvail
,dfree
);
2236 SSVAL(pdata
,l1_cbSector
,bytes_per_sector
);
2240 case SMB_INFO_VOLUME
:
2241 /* Return volume name */
2243 * Add volume serial number - hash of a combination of
2244 * the called hostname and the service name.
2246 serial
= generate_volume_serial_number(lp_sub
, snum
);
2247 SIVAL(pdata
,0,serial
);
2249 * Win2k3 and previous mess this up by sending a name length
2250 * one byte short. I believe only older clients (OS/2 Win9x) use
2251 * this call so try fixing this by adding a terminating null to
2252 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2254 status
= srvstr_push(
2256 pdata
+l2_vol_szVolLabel
, vname
,
2257 PTR_DIFF(end_data
, pdata
+l2_vol_szVolLabel
),
2258 STR_NOALIGN
|STR_TERMINATE
, &len
);
2259 if (!NT_STATUS_IS_OK(status
)) {
2262 SCVAL(pdata
,l2_vol_cch
,len
);
2263 data_len
= l2_vol_szVolLabel
+ len
;
2264 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %u, "
2265 "name = %s serial = 0x%04"PRIx32
"\n",
2266 (unsigned)convert_timespec_to_time_t(st
.st_ex_ctime
),
2267 (unsigned)len
, vname
, serial
));
2270 case SMB_QUERY_FS_ATTRIBUTE_INFO
:
2271 case SMB_FS_ATTRIBUTE_INFORMATION
:
2273 additional_flags
= 0;
2274 #if defined(HAVE_SYS_QUOTAS)
2275 additional_flags
|= FILE_VOLUME_QUOTAS
;
2278 if(lp_nt_acl_support(SNUM(conn
))) {
2279 additional_flags
|= FILE_PERSISTENT_ACLS
;
2282 /* Capabilities are filled in at connection time through STATVFS call */
2283 additional_flags
|= conn
->fs_capabilities
;
2284 additional_flags
|= lp_parm_int(conn
->params
->service
,
2285 "share", "fake_fscaps",
2288 SIVAL(pdata
,0,FILE_CASE_PRESERVED_NAMES
|FILE_CASE_SENSITIVE_SEARCH
|
2289 FILE_SUPPORTS_OBJECT_IDS
|FILE_UNICODE_ON_DISK
|
2290 additional_flags
); /* FS ATTRIBUTES */
2292 SIVAL(pdata
,4,255); /* Max filename component length */
2293 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2294 and will think we can't do long filenames */
2295 status
= srvstr_push(pdata
, flags2
, pdata
+12, fstype
,
2296 PTR_DIFF(end_data
, pdata
+12),
2298 if (!NT_STATUS_IS_OK(status
)) {
2302 data_len
= 12 + len
;
2303 if (max_data_bytes
>= 16 && data_len
> max_data_bytes
) {
2304 /* the client only requested a portion of the
2306 data_len
= max_data_bytes
;
2307 status
= STATUS_BUFFER_OVERFLOW
;
2309 *fixed_portion
= 16;
2312 case SMB_QUERY_FS_LABEL_INFO
:
2313 case SMB_FS_LABEL_INFORMATION
:
2314 status
= srvstr_push(pdata
, flags2
, pdata
+4, vname
,
2315 PTR_DIFF(end_data
, pdata
+4), 0, &len
);
2316 if (!NT_STATUS_IS_OK(status
)) {
2323 case SMB_QUERY_FS_VOLUME_INFO
:
2324 case SMB_FS_VOLUME_INFORMATION
:
2325 put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER
,
2326 pdata
, &st
.st_ex_btime
);
2328 * Add volume serial number - hash of a combination of
2329 * the called hostname and the service name.
2331 serial
= generate_volume_serial_number(lp_sub
, snum
);
2332 SIVAL(pdata
,8,serial
);
2334 /* Max label len is 32 characters. */
2335 status
= srvstr_push(pdata
, flags2
, pdata
+18, vname
,
2336 PTR_DIFF(end_data
, pdata
+18),
2338 if (!NT_STATUS_IS_OK(status
)) {
2341 SIVAL(pdata
,12,len
);
2344 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO "
2345 "namelen = %d, vol=%s serv=%s "
2346 "serial=0x%04"PRIx32
"\n",
2347 (int)strlen(vname
),vname
,
2348 lp_servicename(talloc_tos(), lp_sub
, snum
),
2350 if (max_data_bytes
>= 24 && data_len
> max_data_bytes
) {
2351 /* the client only requested a portion of the
2353 data_len
= max_data_bytes
;
2354 status
= STATUS_BUFFER_OVERFLOW
;
2356 *fixed_portion
= 24;
2359 case SMB_QUERY_FS_SIZE_INFO
:
2360 case SMB_FS_SIZE_INFORMATION
:
2362 uint64_t dfree
,dsize
,bsize
,block_size
,sectors_per_unit
;
2364 df_ret
= get_dfree_info(conn
, &smb_fname
, &bsize
,
2366 if (df_ret
== (uint64_t)-1) {
2367 return map_nt_error_from_unix(errno
);
2369 block_size
= lp_block_size(snum
);
2370 if (bsize
< block_size
) {
2371 uint64_t factor
= block_size
/bsize
;
2376 if (bsize
> block_size
) {
2377 uint64_t factor
= bsize
/block_size
;
2382 sectors_per_unit
= bsize
/bytes_per_sector
;
2383 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2384 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
2385 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
2386 SBIG_UINT(pdata
,0,dsize
);
2387 SBIG_UINT(pdata
,8,dfree
);
2388 SIVAL(pdata
,16,sectors_per_unit
);
2389 SIVAL(pdata
,20,bytes_per_sector
);
2390 *fixed_portion
= 24;
2394 case SMB_FS_FULL_SIZE_INFORMATION
:
2396 uint64_t dfree
,dsize
,bsize
,block_size
,sectors_per_unit
;
2398 df_ret
= get_dfree_info(conn
, &smb_fname
, &bsize
,
2400 if (df_ret
== (uint64_t)-1) {
2401 return map_nt_error_from_unix(errno
);
2403 block_size
= lp_block_size(snum
);
2404 if (bsize
< block_size
) {
2405 uint64_t factor
= block_size
/bsize
;
2410 if (bsize
> block_size
) {
2411 uint64_t factor
= bsize
/block_size
;
2416 sectors_per_unit
= bsize
/bytes_per_sector
;
2417 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2418 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
2419 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
2420 SBIG_UINT(pdata
,0,dsize
); /* Total Allocation units. */
2421 SBIG_UINT(pdata
,8,dfree
); /* Caller available allocation units. */
2422 SBIG_UINT(pdata
,16,dfree
); /* Actual available allocation units. */
2423 SIVAL(pdata
,24,sectors_per_unit
); /* Sectors per allocation unit. */
2424 SIVAL(pdata
,28,bytes_per_sector
); /* Bytes per sector. */
2425 *fixed_portion
= 32;
2429 case SMB_QUERY_FS_DEVICE_INFO
:
2430 case SMB_FS_DEVICE_INFORMATION
:
2432 uint32_t characteristics
= FILE_DEVICE_IS_MOUNTED
;
2434 if (!CAN_WRITE(conn
)) {
2435 characteristics
|= FILE_READ_ONLY_DEVICE
;
2438 SIVAL(pdata
,0,FILE_DEVICE_DISK
); /* dev type */
2439 SIVAL(pdata
,4,characteristics
);
2444 #ifdef HAVE_SYS_QUOTAS
2445 case SMB_FS_QUOTA_INFORMATION
:
2447 * what we have to send --metze:
2449 * Unknown1: 24 NULL bytes
2450 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
2451 * Hard Quota Limit: 8 bytes seems like uint64_t or so
2452 * Quota Flags: 2 byte :
2453 * Unknown3: 6 NULL bytes
2457 * details for Quota Flags:
2459 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2460 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2461 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2462 * 0x0001 Enable Quotas: enable quota for this fs
2466 /* we need to fake up a fsp here,
2467 * because its not send in this call
2470 SMB_NTQUOTA_STRUCT quotas
;
2473 ZERO_STRUCT(quotas
);
2476 fsp
.fnum
= FNUM_FIELD_INVALID
;
2479 if (get_current_uid(conn
) != 0) {
2480 DEBUG(0,("get_user_quota: access_denied "
2481 "service [%s] user [%s]\n",
2482 lp_servicename(talloc_tos(), lp_sub
, SNUM(conn
)),
2483 conn
->session_info
->unix_info
->unix_name
));
2484 return NT_STATUS_ACCESS_DENIED
;
2487 status
= vfs_get_ntquota(&fsp
, SMB_USER_FS_QUOTA_TYPE
,
2489 if (!NT_STATUS_IS_OK(status
)) {
2490 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), lp_sub
, SNUM(conn
))));
2496 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
2497 lp_servicename(talloc_tos(), lp_sub
, SNUM(conn
))));
2499 /* Unknown1 24 NULL bytes*/
2500 SBIG_UINT(pdata
,0,(uint64_t)0);
2501 SBIG_UINT(pdata
,8,(uint64_t)0);
2502 SBIG_UINT(pdata
,16,(uint64_t)0);
2504 /* Default Soft Quota 8 bytes */
2505 SBIG_UINT(pdata
,24,quotas
.softlim
);
2507 /* Default Hard Quota 8 bytes */
2508 SBIG_UINT(pdata
,32,quotas
.hardlim
);
2510 /* Quota flag 2 bytes */
2511 SSVAL(pdata
,40,quotas
.qflags
);
2513 /* Unknown3 6 NULL bytes */
2519 #endif /* HAVE_SYS_QUOTAS */
2520 case SMB_FS_OBJECTID_INFORMATION
:
2522 unsigned char objid
[16];
2523 struct smb_extended_info extended_info
;
2524 memcpy(pdata
,create_volume_objectid(conn
, objid
),16);
2525 samba_extended_info_version (&extended_info
);
2526 SIVAL(pdata
,16,extended_info
.samba_magic
);
2527 SIVAL(pdata
,20,extended_info
.samba_version
);
2528 SIVAL(pdata
,24,extended_info
.samba_subversion
);
2529 SBIG_UINT(pdata
,28,extended_info
.samba_gitcommitdate
);
2530 memcpy(pdata
+36,extended_info
.samba_version_string
,28);
2535 case SMB_FS_SECTOR_SIZE_INFORMATION
:
2539 * These values match a physical Windows Server 2012
2540 * share backed by NTFS atop spinning rust.
2542 DEBUG(5, ("SMB_FS_SECTOR_SIZE_INFORMATION:"));
2543 /* logical_bytes_per_sector */
2544 SIVAL(pdata
, 0, bytes_per_sector
);
2545 /* phys_bytes_per_sector_atomic */
2546 SIVAL(pdata
, 4, bytes_per_sector
);
2547 /* phys_bytes_per_sector_perf */
2548 SIVAL(pdata
, 8, bytes_per_sector
);
2549 /* fs_effective_phys_bytes_per_sector_atomic */
2550 SIVAL(pdata
, 12, bytes_per_sector
);
2552 SIVAL(pdata
, 16, SSINFO_FLAGS_ALIGNED_DEVICE
2553 | SSINFO_FLAGS_PARTITION_ALIGNED_ON_DEVICE
);
2554 /* byte_off_sector_align */
2555 SIVAL(pdata
, 20, 0);
2556 /* byte_off_partition_align */
2557 SIVAL(pdata
, 24, 0);
2558 *fixed_portion
= 28;
2563 #if defined(WITH_SMB1SERVER)
2565 * Query the version and capabilities of the CIFS UNIX extensions
2569 case SMB_QUERY_CIFS_UNIX_INFO
:
2571 bool large_write
= lp_min_receive_file_size() &&
2572 !smb1_srv_is_signing_active(xconn
);
2573 bool large_read
= !smb1_srv_is_signing_active(xconn
);
2574 int encrypt_caps
= 0;
2576 if (!lp_smb1_unix_extensions()) {
2577 return NT_STATUS_INVALID_LEVEL
;
2580 switch (conn
->encrypt_level
) {
2581 case SMB_SIGNING_OFF
:
2584 case SMB_SIGNING_DESIRED
:
2585 case SMB_SIGNING_IF_REQUIRED
:
2586 case SMB_SIGNING_DEFAULT
:
2587 encrypt_caps
= CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP
;
2589 case SMB_SIGNING_REQUIRED
:
2590 encrypt_caps
= CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP
|
2591 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP
;
2592 large_write
= false;
2598 SSVAL(pdata
,0,CIFS_UNIX_MAJOR_VERSION
);
2599 SSVAL(pdata
,2,CIFS_UNIX_MINOR_VERSION
);
2601 /* We have POSIX ACLs, pathname, encryption,
2602 * large read/write, and locking capability. */
2604 SBIG_UINT(pdata
,4,((uint64_t)(
2605 CIFS_UNIX_POSIX_ACLS_CAP
|
2606 CIFS_UNIX_POSIX_PATHNAMES_CAP
|
2607 CIFS_UNIX_FCNTL_LOCKS_CAP
|
2608 CIFS_UNIX_EXTATTR_CAP
|
2609 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP
|
2611 (large_read
? CIFS_UNIX_LARGE_READ_CAP
: 0) |
2613 CIFS_UNIX_LARGE_WRITE_CAP
: 0))));
2618 case SMB_QUERY_POSIX_FS_INFO
:
2621 struct vfs_statvfs_struct svfs
;
2623 if (!lp_smb1_unix_extensions()) {
2624 return NT_STATUS_INVALID_LEVEL
;
2627 rc
= SMB_VFS_STATVFS(conn
, &smb_fname
, &svfs
);
2631 SIVAL(pdata
,0,svfs
.OptimalTransferSize
);
2632 SIVAL(pdata
,4,svfs
.BlockSize
);
2633 SBIG_UINT(pdata
,8,svfs
.TotalBlocks
);
2634 SBIG_UINT(pdata
,16,svfs
.BlocksAvail
);
2635 SBIG_UINT(pdata
,24,svfs
.UserBlocksAvail
);
2636 SBIG_UINT(pdata
,32,svfs
.TotalFileNodes
);
2637 SBIG_UINT(pdata
,40,svfs
.FreeFileNodes
);
2638 SBIG_UINT(pdata
,48,svfs
.FsIdentifier
);
2639 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
2641 } else if (rc
== EOPNOTSUPP
) {
2642 return NT_STATUS_INVALID_LEVEL
;
2643 #endif /* EOPNOTSUPP */
2645 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(talloc_tos(), lp_sub
, SNUM(conn
))));
2646 return NT_STATUS_DOS(ERRSRV
, ERRerror
);
2651 case SMB_QUERY_POSIX_WHOAMI
:
2657 if (!lp_smb1_unix_extensions()) {
2658 return NT_STATUS_INVALID_LEVEL
;
2661 if (max_data_bytes
< 40) {
2662 return NT_STATUS_BUFFER_TOO_SMALL
;
2665 if (security_session_user_level(conn
->session_info
, NULL
) < SECURITY_USER
) {
2666 flags
|= SMB_WHOAMI_GUEST
;
2669 /* NOTE: 8 bytes for UID/GID, irrespective of native
2670 * platform size. This matches
2671 * SMB_QUERY_FILE_UNIX_BASIC and friends.
2673 data_len
= 4 /* flags */
2680 + 4 /* pad/reserved */
2681 + (conn
->session_info
->unix_token
->ngroups
* 8)
2683 + (conn
->session_info
->security_token
->num_sids
*
2687 SIVAL(pdata
, 0, flags
);
2688 SIVAL(pdata
, 4, SMB_WHOAMI_MASK
);
2690 (uint64_t)conn
->session_info
->unix_token
->uid
);
2691 SBIG_UINT(pdata
, 16,
2692 (uint64_t)conn
->session_info
->unix_token
->gid
);
2695 if (data_len
>= max_data_bytes
) {
2696 /* Potential overflow, skip the GIDs and SIDs. */
2698 SIVAL(pdata
, 24, 0); /* num_groups */
2699 SIVAL(pdata
, 28, 0); /* num_sids */
2700 SIVAL(pdata
, 32, 0); /* num_sid_bytes */
2701 SIVAL(pdata
, 36, 0); /* reserved */
2707 SIVAL(pdata
, 24, conn
->session_info
->unix_token
->ngroups
);
2708 SIVAL(pdata
, 28, conn
->session_info
->security_token
->num_sids
);
2710 /* We walk the SID list twice, but this call is fairly
2711 * infrequent, and I don't expect that it's performance
2712 * sensitive -- jpeach
2714 for (i
= 0, sid_bytes
= 0;
2715 i
< conn
->session_info
->security_token
->num_sids
; ++i
) {
2716 sid_bytes
+= ndr_size_dom_sid(
2717 &conn
->session_info
->security_token
->sids
[i
],
2721 /* SID list byte count */
2722 SIVAL(pdata
, 32, sid_bytes
);
2724 /* 4 bytes pad/reserved - must be zero */
2725 SIVAL(pdata
, 36, 0);
2729 for (i
= 0; i
< conn
->session_info
->unix_token
->ngroups
; ++i
) {
2730 SBIG_UINT(pdata
, data_len
,
2731 (uint64_t)conn
->session_info
->unix_token
->groups
[i
]);
2737 i
< conn
->session_info
->security_token
->num_sids
; ++i
) {
2738 int sid_len
= ndr_size_dom_sid(
2739 &conn
->session_info
->security_token
->sids
[i
],
2742 sid_linearize((uint8_t *)(pdata
+ data_len
),
2744 &conn
->session_info
->security_token
->sids
[i
]);
2745 data_len
+= sid_len
;
2751 case SMB_MAC_QUERY_FS_INFO
:
2753 * Thursby MAC extension... ONLY on NTFS filesystems
2754 * once we do streams then we don't need this
2756 if (strequal(lp_fstype(SNUM(conn
)),"NTFS")) {
2758 SIVAL(pdata
,84,0x100); /* Don't support mac... */
2764 return NT_STATUS_INVALID_LEVEL
;
2767 *ret_data_len
= data_len
;
2771 NTSTATUS
smb_set_fsquota(connection_struct
*conn
,
2772 struct smb_request
*req
,
2774 const DATA_BLOB
*qdata
)
2776 const struct loadparm_substitution
*lp_sub
=
2777 loadparm_s3_global_substitution();
2779 SMB_NTQUOTA_STRUCT quotas
;
2781 ZERO_STRUCT(quotas
);
2784 if ((get_current_uid(conn
) != 0) || !CAN_WRITE(conn
)) {
2785 DEBUG(3, ("set_fsquota: access_denied service [%s] user [%s]\n",
2786 lp_servicename(talloc_tos(), lp_sub
, SNUM(conn
)),
2787 conn
->session_info
->unix_info
->unix_name
));
2788 return NT_STATUS_ACCESS_DENIED
;
2791 if (!check_fsp_ntquota_handle(conn
, req
,
2793 DEBUG(1, ("set_fsquota: no valid QUOTA HANDLE\n"));
2794 return NT_STATUS_INVALID_HANDLE
;
2797 /* note: normally there're 48 bytes,
2798 * but we didn't use the last 6 bytes for now
2801 if (qdata
->length
< 42) {
2802 DEBUG(0,("set_fsquota: requires total_data(%u) >= 42 bytes!\n",
2803 (unsigned int)qdata
->length
));
2804 return NT_STATUS_INVALID_PARAMETER
;
2807 /* unknown_1 24 NULL bytes in pdata*/
2809 /* the soft quotas 8 bytes (uint64_t)*/
2810 quotas
.softlim
= BVAL(qdata
->data
,24);
2812 /* the hard quotas 8 bytes (uint64_t)*/
2813 quotas
.hardlim
= BVAL(qdata
->data
,32);
2815 /* quota_flags 2 bytes **/
2816 quotas
.qflags
= SVAL(qdata
->data
,40);
2818 /* unknown_2 6 NULL bytes follow*/
2820 /* now set the quotas */
2821 if (vfs_set_ntquota(fsp
, SMB_USER_FS_QUOTA_TYPE
, NULL
, "as
)!=0) {
2822 DEBUG(1, ("vfs_set_ntquota() failed for service [%s]\n",
2823 lp_servicename(talloc_tos(), lp_sub
, SNUM(conn
))));
2824 status
= map_nt_error_from_unix(errno
);
2826 status
= NT_STATUS_OK
;
2831 NTSTATUS
smbd_do_setfsinfo(connection_struct
*conn
,
2832 struct smb_request
*req
,
2833 TALLOC_CTX
*mem_ctx
,
2834 uint16_t info_level
,
2836 const DATA_BLOB
*pdata
)
2838 switch (info_level
) {
2839 case SMB_FS_QUOTA_INFORMATION
:
2841 return smb_set_fsquota(conn
,
2850 return NT_STATUS_INVALID_LEVEL
;
2853 #if defined(HAVE_POSIX_ACLS)
2854 /****************************************************************************
2855 Utility function to count the number of entries in a POSIX acl.
2856 ****************************************************************************/
2858 static unsigned int count_acl_entries(connection_struct
*conn
, SMB_ACL_T posix_acl
)
2860 unsigned int ace_count
= 0;
2861 int entry_id
= SMB_ACL_FIRST_ENTRY
;
2862 SMB_ACL_ENTRY_T entry
;
2864 while ( posix_acl
&& (sys_acl_get_entry(posix_acl
, entry_id
, &entry
) == 1)) {
2866 if (entry_id
== SMB_ACL_FIRST_ENTRY
) {
2867 entry_id
= SMB_ACL_NEXT_ENTRY
;
2874 /****************************************************************************
2875 Utility function to marshall a POSIX acl into wire format.
2876 ****************************************************************************/
2878 static bool marshall_posix_acl(connection_struct
*conn
, char *pdata
, SMB_STRUCT_STAT
*pst
, SMB_ACL_T posix_acl
)
2880 int entry_id
= SMB_ACL_FIRST_ENTRY
;
2881 SMB_ACL_ENTRY_T entry
;
2883 while ( posix_acl
&& (sys_acl_get_entry(posix_acl
, entry_id
, &entry
) == 1)) {
2884 SMB_ACL_TAG_T tagtype
;
2885 SMB_ACL_PERMSET_T permset
;
2886 unsigned char perms
= 0;
2887 unsigned int own_grp
;
2890 if (entry_id
== SMB_ACL_FIRST_ENTRY
) {
2891 entry_id
= SMB_ACL_NEXT_ENTRY
;
2894 if (sys_acl_get_tag_type(entry
, &tagtype
) == -1) {
2895 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
2899 if (sys_acl_get_permset(entry
, &permset
) == -1) {
2900 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
2904 perms
|= (sys_acl_get_perm(permset
, SMB_ACL_READ
) ? SMB_POSIX_ACL_READ
: 0);
2905 perms
|= (sys_acl_get_perm(permset
, SMB_ACL_WRITE
) ? SMB_POSIX_ACL_WRITE
: 0);
2906 perms
|= (sys_acl_get_perm(permset
, SMB_ACL_EXECUTE
) ? SMB_POSIX_ACL_EXECUTE
: 0);
2908 SCVAL(pdata
,1,perms
);
2911 case SMB_ACL_USER_OBJ
:
2912 SCVAL(pdata
,0,SMB_POSIX_ACL_USER_OBJ
);
2913 own_grp
= (unsigned int)pst
->st_ex_uid
;
2914 SIVAL(pdata
,2,own_grp
);
2919 uid_t
*puid
= (uid_t
*)sys_acl_get_qualifier(entry
);
2921 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
2924 own_grp
= (unsigned int)*puid
;
2925 SCVAL(pdata
,0,SMB_POSIX_ACL_USER
);
2926 SIVAL(pdata
,2,own_grp
);
2930 case SMB_ACL_GROUP_OBJ
:
2931 SCVAL(pdata
,0,SMB_POSIX_ACL_GROUP_OBJ
);
2932 own_grp
= (unsigned int)pst
->st_ex_gid
;
2933 SIVAL(pdata
,2,own_grp
);
2938 gid_t
*pgid
= (gid_t
*)sys_acl_get_qualifier(entry
);
2940 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
2943 own_grp
= (unsigned int)*pgid
;
2944 SCVAL(pdata
,0,SMB_POSIX_ACL_GROUP
);
2945 SIVAL(pdata
,2,own_grp
);
2950 SCVAL(pdata
,0,SMB_POSIX_ACL_MASK
);
2951 SIVAL(pdata
,2,0xFFFFFFFF);
2952 SIVAL(pdata
,6,0xFFFFFFFF);
2955 SCVAL(pdata
,0,SMB_POSIX_ACL_OTHER
);
2956 SIVAL(pdata
,2,0xFFFFFFFF);
2957 SIVAL(pdata
,6,0xFFFFFFFF);
2960 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
2963 pdata
+= SMB_POSIX_ACL_ENTRY_SIZE
;
2970 /****************************************************************************
2971 Store the FILE_UNIX_BASIC info.
2972 ****************************************************************************/
2974 static char *store_file_unix_basic(connection_struct
*conn
,
2977 const SMB_STRUCT_STAT
*psbuf
)
2981 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
2982 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf
->st_ex_mode
));
2984 SOFF_T(pdata
,0,get_file_size_stat(psbuf
)); /* File size 64 Bit */
2987 SOFF_T(pdata
,0,SMB_VFS_GET_ALLOC_SIZE(conn
,fsp
,psbuf
)); /* Number of bytes used on disk - 64 Bit */
2990 put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER
, pdata
, &psbuf
->st_ex_ctime
); /* Change Time 64 Bit */
2991 put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER
,pdata
+8, &psbuf
->st_ex_atime
); /* Last access time 64 Bit */
2992 put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER
, pdata
+16, &psbuf
->st_ex_mtime
); /* Last modification time 64 Bit */
2995 SIVAL(pdata
,0,psbuf
->st_ex_uid
); /* user id for the owner */
2999 SIVAL(pdata
,0,psbuf
->st_ex_gid
); /* group id of owner */
3003 SIVAL(pdata
,0,unix_filetype(psbuf
->st_ex_mode
));
3006 if (S_ISBLK(psbuf
->st_ex_mode
) || S_ISCHR(psbuf
->st_ex_mode
)) {
3007 devno
= psbuf
->st_ex_rdev
;
3009 devno
= psbuf
->st_ex_dev
;
3012 SIVAL(pdata
,0,unix_dev_major(devno
)); /* Major device number if type is device */
3016 SIVAL(pdata
,0,unix_dev_minor(devno
)); /* Minor device number if type is device */
3020 SINO_T_VAL(pdata
, 0, psbuf
->st_ex_ino
); /* inode number */
3023 SIVAL(pdata
,0, unix_perms_to_wire(psbuf
->st_ex_mode
)); /* Standard UNIX file permissions */
3027 SIVAL(pdata
,0,psbuf
->st_ex_nlink
); /* number of hard links */
3034 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3035 * the chflags(2) (or equivalent) flags.
3037 * XXX: this really should be behind the VFS interface. To do this, we would
3038 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3039 * Each VFS module could then implement its own mapping as appropriate for the
3040 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3042 static const struct {unsigned stat_fflag
; unsigned smb_fflag
;}
3046 { UF_NODUMP
, EXT_DO_NOT_BACKUP
},
3050 { UF_IMMUTABLE
, EXT_IMMUTABLE
},
3054 { UF_APPEND
, EXT_OPEN_APPEND_ONLY
},
3058 { UF_HIDDEN
, EXT_HIDDEN
},
3061 /* Do not remove. We need to guarantee that this array has at least one
3062 * entry to build on HP-UX.
3068 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT
*psbuf
,
3069 uint32_t *smb_fflags
, uint32_t *smb_fmask
)
3073 for (i
= 0; i
< ARRAY_SIZE(info2_flags_map
); ++i
) {
3074 *smb_fmask
|= info2_flags_map
[i
].smb_fflag
;
3075 if (psbuf
->st_ex_flags
& info2_flags_map
[i
].stat_fflag
) {
3076 *smb_fflags
|= info2_flags_map
[i
].smb_fflag
;
3081 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT
*psbuf
,
3082 const uint32_t smb_fflags
,
3083 const uint32_t smb_fmask
,
3086 uint32_t max_fmask
= 0;
3089 *stat_fflags
= psbuf
->st_ex_flags
;
3091 /* For each flags requested in smb_fmask, check the state of the
3092 * corresponding flag in smb_fflags and set or clear the matching
3096 for (i
= 0; i
< ARRAY_SIZE(info2_flags_map
); ++i
) {
3097 max_fmask
|= info2_flags_map
[i
].smb_fflag
;
3098 if (smb_fmask
& info2_flags_map
[i
].smb_fflag
) {
3099 if (smb_fflags
& info2_flags_map
[i
].smb_fflag
) {
3100 *stat_fflags
|= info2_flags_map
[i
].stat_fflag
;
3102 *stat_fflags
&= ~info2_flags_map
[i
].stat_fflag
;
3107 /* If smb_fmask is asking to set any bits that are not supported by
3108 * our flag mappings, we should fail.
3110 if ((smb_fmask
& max_fmask
) != smb_fmask
) {
3118 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
3119 * of file flags and birth (create) time.
3121 static char *store_file_unix_basic_info2(connection_struct
*conn
,
3124 const SMB_STRUCT_STAT
*psbuf
)
3126 uint32_t file_flags
= 0;
3127 uint32_t flags_mask
= 0;
3129 pdata
= store_file_unix_basic(conn
, pdata
, fsp
, psbuf
);
3131 /* Create (birth) time 64 bit */
3132 put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER
,pdata
, &psbuf
->st_ex_btime
);
3135 map_info2_flags_from_sbuf(psbuf
, &file_flags
, &flags_mask
);
3136 SIVAL(pdata
, 0, file_flags
); /* flags */
3137 SIVAL(pdata
, 4, flags_mask
); /* mask */
3143 static NTSTATUS
marshall_stream_info(unsigned int num_streams
,
3144 const struct stream_struct
*streams
,
3146 unsigned int max_data_bytes
,
3147 unsigned int *data_size
)
3150 unsigned int ofs
= 0;
3152 if (max_data_bytes
< 32) {
3153 return NT_STATUS_INFO_LENGTH_MISMATCH
;
3156 for (i
= 0; i
< num_streams
; i
++) {
3157 unsigned int next_offset
;
3159 smb_ucs2_t
*namebuf
;
3161 if (!push_ucs2_talloc(talloc_tos(), &namebuf
,
3162 streams
[i
].name
, &namelen
) ||
3165 return NT_STATUS_INVALID_PARAMETER
;
3169 * name_buf is now null-terminated, we need to marshall as not
3176 * We cannot overflow ...
3178 if ((ofs
+ 24 + namelen
) > max_data_bytes
) {
3179 DEBUG(10, ("refusing to overflow reply at stream %u\n",
3181 TALLOC_FREE(namebuf
);
3182 return STATUS_BUFFER_OVERFLOW
;
3185 SIVAL(data
, ofs
+4, namelen
);
3186 SOFF_T(data
, ofs
+8, streams
[i
].size
);
3187 SOFF_T(data
, ofs
+16, streams
[i
].alloc_size
);
3188 memcpy(data
+ofs
+24, namebuf
, namelen
);
3189 TALLOC_FREE(namebuf
);
3191 next_offset
= ofs
+ 24 + namelen
;
3193 if (i
== num_streams
-1) {
3194 SIVAL(data
, ofs
, 0);
3197 unsigned int align
= ndr_align_size(next_offset
, 8);
3199 if ((next_offset
+ align
) > max_data_bytes
) {
3200 DEBUG(10, ("refusing to overflow align "
3201 "reply at stream %u\n",
3203 TALLOC_FREE(namebuf
);
3204 return STATUS_BUFFER_OVERFLOW
;
3207 memset(data
+next_offset
, 0, align
);
3208 next_offset
+= align
;
3210 SIVAL(data
, ofs
, next_offset
- ofs
);
3217 DEBUG(10, ("max_data: %u, data_size: %u\n", max_data_bytes
, ofs
));
3221 return NT_STATUS_OK
;
3224 static NTSTATUS
smb_unix_read_symlink(connection_struct
*conn
,
3225 struct smb_request
*req
,
3226 struct smb_filename
*smb_fname
,
3228 unsigned int data_size_in
,
3229 unsigned int *pdata_size_out
)
3234 struct smb_filename
*parent_fname
= NULL
;
3235 struct smb_filename
*base_name
= NULL
;
3237 char *buffer
= talloc_array(talloc_tos(), char, PATH_MAX
+1);
3240 return NT_STATUS_NO_MEMORY
;
3243 DBG_DEBUG("SMB_QUERY_FILE_UNIX_LINK for file %s\n",
3244 smb_fname_str_dbg(smb_fname
));
3246 if(!S_ISLNK(smb_fname
->st
.st_ex_mode
)) {
3247 TALLOC_FREE(buffer
);
3248 return NT_STATUS_DOS(ERRSRV
, ERRbadlink
);
3251 status
= parent_pathref(talloc_tos(),
3256 if (!NT_STATUS_IS_OK(status
)) {
3257 TALLOC_FREE(buffer
);
3261 link_len
= SMB_VFS_READLINKAT(conn
,
3267 TALLOC_FREE(parent_fname
);
3269 if (link_len
== -1) {
3270 TALLOC_FREE(buffer
);
3271 return map_nt_error_from_unix(errno
);
3274 buffer
[link_len
] = 0;
3275 status
= srvstr_push(pdata
,
3282 TALLOC_FREE(buffer
);
3283 if (!NT_STATUS_IS_OK(status
)) {
3286 *pdata_size_out
= len
;
3288 return NT_STATUS_OK
;
3291 #if defined(HAVE_POSIX_ACLS)
3292 static NTSTATUS
smb_query_posix_acl(connection_struct
*conn
,
3293 struct smb_request
*req
,
3295 struct smb_filename
*smb_fname
,
3297 unsigned int data_size_in
,
3298 unsigned int *pdata_size_out
)
3300 SMB_ACL_T file_acl
= NULL
;
3301 SMB_ACL_T def_acl
= NULL
;
3302 uint16_t num_file_acls
= 0;
3303 uint16_t num_def_acls
= 0;
3304 unsigned int size_needed
= 0;
3307 bool close_fsp
= false;
3310 * Ensure we always operate on a file descriptor, not just
3313 if (fsp
== NULL
|| !fsp
->fsp_flags
.is_fsa
) {
3314 uint32_t access_mask
= SEC_STD_READ_CONTROL
|
3315 FILE_READ_ATTRIBUTES
|
3316 FILE_WRITE_ATTRIBUTES
;
3318 status
= get_posix_fsp(conn
,
3324 if (!NT_STATUS_IS_OK(status
)) {
3330 SMB_ASSERT(fsp
!= NULL
);
3332 status
= refuse_symlink_fsp(fsp
);
3333 if (!NT_STATUS_IS_OK(status
)) {
3337 file_acl
= SMB_VFS_SYS_ACL_GET_FD(fsp
, SMB_ACL_TYPE_ACCESS
,
3340 if (file_acl
== NULL
&& no_acl_syscall_error(errno
)) {
3341 DBG_INFO("ACLs not implemented on "
3342 "filesystem containing %s\n",
3344 status
= NT_STATUS_NOT_IMPLEMENTED
;
3348 if (S_ISDIR(fsp
->fsp_name
->st
.st_ex_mode
)) {
3350 * We can only have default POSIX ACLs on
3353 if (!fsp
->fsp_flags
.is_directory
) {
3354 DBG_INFO("Non-directory open %s\n",
3356 status
= NT_STATUS_INVALID_HANDLE
;
3359 def_acl
= SMB_VFS_SYS_ACL_GET_FD(fsp
,
3360 SMB_ACL_TYPE_DEFAULT
,
3362 def_acl
= free_empty_sys_acl(conn
, def_acl
);
3365 num_file_acls
= count_acl_entries(conn
, file_acl
);
3366 num_def_acls
= count_acl_entries(conn
, def_acl
);
3369 if (num_file_acls
+ num_def_acls
< num_file_acls
) {
3370 status
= NT_STATUS_INVALID_PARAMETER
;
3374 size_needed
= num_file_acls
+ num_def_acls
;
3377 * (size_needed * SMB_POSIX_ACL_ENTRY_SIZE) must be less
3378 * than UINT_MAX, so check by division.
3380 if (size_needed
> (UINT_MAX
/SMB_POSIX_ACL_ENTRY_SIZE
)) {
3381 status
= NT_STATUS_INVALID_PARAMETER
;
3385 size_needed
= size_needed
*SMB_POSIX_ACL_ENTRY_SIZE
;
3386 if (size_needed
+ SMB_POSIX_ACL_HEADER_SIZE
< size_needed
) {
3387 status
= NT_STATUS_INVALID_PARAMETER
;
3390 size_needed
+= SMB_POSIX_ACL_HEADER_SIZE
;
3392 if ( data_size_in
< size_needed
) {
3393 DBG_INFO("data_size too small (%u) need %u\n",
3396 status
= NT_STATUS_BUFFER_TOO_SMALL
;
3400 SSVAL(pdata
,0,SMB_POSIX_ACL_VERSION
);
3401 SSVAL(pdata
,2,num_file_acls
);
3402 SSVAL(pdata
,4,num_def_acls
);
3403 pdata
+= SMB_POSIX_ACL_HEADER_SIZE
;
3405 ok
= marshall_posix_acl(conn
,
3410 status
= NT_STATUS_INTERNAL_ERROR
;
3413 pdata
+= (num_file_acls
*SMB_POSIX_ACL_ENTRY_SIZE
);
3415 ok
= marshall_posix_acl(conn
,
3420 status
= NT_STATUS_INTERNAL_ERROR
;
3424 *pdata_size_out
= size_needed
;
3425 status
= NT_STATUS_OK
;
3431 * Ensure the stat struct in smb_fname is up to
3432 * date. Structure copy.
3434 smb_fname
->st
= fsp
->fsp_name
->st
;
3435 (void)close_file_free(req
, &fsp
, NORMAL_CLOSE
);
3438 TALLOC_FREE(file_acl
);
3439 TALLOC_FREE(def_acl
);
3444 NTSTATUS
smbd_do_qfilepathinfo(connection_struct
*conn
,
3445 TALLOC_CTX
*mem_ctx
,
3446 struct smb_request
*req
,
3447 uint16_t info_level
,
3449 struct smb_filename
*smb_fname
,
3450 bool delete_pending
,
3451 struct timespec write_time_ts
,
3452 struct ea_list
*ea_list
,
3453 int lock_data_count
,
3456 unsigned int max_data_bytes
,
3457 size_t *fixed_portion
,
3459 unsigned int *pdata_size
)
3461 char *pdata
= *ppdata
;
3462 char *dstart
, *dend
;
3463 unsigned int data_size
;
3464 struct timespec create_time_ts
, mtime_ts
, atime_ts
, ctime_ts
;
3465 time_t create_time
, mtime
, atime
, c_time
;
3466 SMB_STRUCT_STAT
*psbuf
= NULL
;
3467 SMB_STRUCT_STAT
*base_sp
= NULL
;
3474 uint64_t file_size
= 0;
3476 uint64_t allocation_size
= 0;
3477 uint64_t file_id
= 0;
3478 uint32_t access_mask
= 0;
3481 if (INFO_LEVEL_IS_UNIX(info_level
)) {
3482 if (!lp_smb1_unix_extensions()) {
3483 return NT_STATUS_INVALID_LEVEL
;
3485 if (!req
->posix_pathnames
) {
3486 return NT_STATUS_INVALID_LEVEL
;
3490 DEBUG(5,("smbd_do_qfilepathinfo: %s (%s) level=%d max_data=%u\n",
3491 smb_fname_str_dbg(smb_fname
),
3493 info_level
, max_data_bytes
));
3496 * In case of querying a symlink in POSIX context,
3497 * fsp will be NULL. fdos_mode() deals with it.
3500 smb_fname
= fsp
->fsp_name
;
3502 mode
= fdos_mode(fsp
);
3503 psbuf
= &smb_fname
->st
;
3506 base_sp
= fsp
->base_fsp
?
3507 &fsp
->base_fsp
->fsp_name
->st
:
3510 base_sp
= &smb_fname
->st
;
3513 nlink
= psbuf
->st_ex_nlink
;
3515 if (nlink
&& (mode
&FILE_ATTRIBUTE_DIRECTORY
)) {
3519 if ((nlink
> 0) && delete_pending
) {
3523 if (max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
< max_data_bytes
) {
3524 return NT_STATUS_INVALID_PARAMETER
;
3527 data_size
= max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
;
3528 *ppdata
= (char *)SMB_REALLOC(*ppdata
, data_size
);
3529 if (*ppdata
== NULL
) {
3530 return NT_STATUS_NO_MEMORY
;
3534 dend
= dstart
+ data_size
- 1;
3536 if (!is_omit_timespec(&write_time_ts
) &&
3537 !INFO_LEVEL_IS_UNIX(info_level
))
3539 update_stat_ex_mtime(psbuf
, write_time_ts
);
3542 create_time_ts
= get_create_timespec(conn
, fsp
, smb_fname
);
3543 mtime_ts
= psbuf
->st_ex_mtime
;
3544 atime_ts
= psbuf
->st_ex_atime
;
3545 ctime_ts
= get_change_timespec(conn
, fsp
, smb_fname
);
3547 if (lp_dos_filetime_resolution(SNUM(conn
))) {
3548 dos_filetime_timespec(&create_time_ts
);
3549 dos_filetime_timespec(&mtime_ts
);
3550 dos_filetime_timespec(&atime_ts
);
3551 dos_filetime_timespec(&ctime_ts
);
3554 create_time
= convert_timespec_to_time_t(create_time_ts
);
3555 mtime
= convert_timespec_to_time_t(mtime_ts
);
3556 atime
= convert_timespec_to_time_t(atime_ts
);
3557 c_time
= convert_timespec_to_time_t(ctime_ts
);
3559 p
= strrchr_m(smb_fname
->base_name
,'/');
3561 base_name
= smb_fname
->base_name
;
3565 /* NT expects the name to be in an exact form of the *full*
3566 filename. See the trans2 torture test */
3567 if (ISDOT(base_name
)) {
3568 dos_fname
= talloc_strdup(mem_ctx
, "\\");
3570 return NT_STATUS_NO_MEMORY
;
3573 dos_fname
= talloc_asprintf(mem_ctx
,
3575 smb_fname
->base_name
);
3577 return NT_STATUS_NO_MEMORY
;
3579 if (is_named_stream(smb_fname
)) {
3580 dos_fname
= talloc_asprintf(dos_fname
, "%s",
3581 smb_fname
->stream_name
);
3583 return NT_STATUS_NO_MEMORY
;
3587 string_replace(dos_fname
, '/', '\\');
3590 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
, fsp
, psbuf
);
3592 if (fsp
== NULL
|| !fsp
->fsp_flags
.is_fsa
) {
3593 /* Do we have this path open ? */
3595 struct file_id fileid
= vfs_file_id_from_sbuf(conn
, psbuf
);
3596 fsp1
= file_find_di_first(conn
->sconn
, fileid
, true);
3597 if (fsp1
&& fsp1
->initial_allocation_size
) {
3598 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
, fsp1
, psbuf
);
3602 if (!(mode
& FILE_ATTRIBUTE_DIRECTORY
)) {
3603 file_size
= get_file_size_stat(psbuf
);
3607 pos
= fh_get_position_information(fsp
->fh
);
3611 access_mask
= fsp
->access_mask
;
3613 /* GENERIC_EXECUTE mapping from Windows */
3614 access_mask
= 0x12019F;
3617 /* This should be an index number - looks like
3620 I think this causes us to fail the IFSKIT
3621 BasicFileInformationTest. -tpot */
3622 file_id
= SMB_VFS_FS_FILE_ID(conn
, base_sp
);
3626 switch (info_level
) {
3627 case SMB_INFO_STANDARD
:
3628 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
3630 srv_put_dos_date2(pdata
,l1_fdateCreation
,create_time
);
3631 srv_put_dos_date2(pdata
,l1_fdateLastAccess
,atime
);
3632 srv_put_dos_date2(pdata
,l1_fdateLastWrite
,mtime
); /* write time */
3633 SIVAL(pdata
,l1_cbFile
,(uint32_t)file_size
);
3634 SIVAL(pdata
,l1_cbFileAlloc
,(uint32_t)allocation_size
);
3635 SSVAL(pdata
,l1_attrFile
,mode
);
3638 case SMB_INFO_QUERY_EA_SIZE
:
3640 unsigned int ea_size
=
3641 estimate_ea_size(smb_fname
->fsp
);
3642 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
3644 srv_put_dos_date2(pdata
,0,create_time
);
3645 srv_put_dos_date2(pdata
,4,atime
);
3646 srv_put_dos_date2(pdata
,8,mtime
); /* write time */
3647 SIVAL(pdata
,12,(uint32_t)file_size
);
3648 SIVAL(pdata
,16,(uint32_t)allocation_size
);
3649 SSVAL(pdata
,20,mode
);
3650 SIVAL(pdata
,22,ea_size
);
3654 case SMB_INFO_IS_NAME_VALID
:
3655 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
3657 /* os/2 needs this ? really ?*/
3658 return NT_STATUS_DOS(ERRDOS
, ERRbadfunc
);
3660 /* This is only reached for qpathinfo */
3664 case SMB_INFO_QUERY_EAS_FROM_LIST
:
3666 size_t total_ea_len
= 0;
3667 struct ea_list
*ea_file_list
= NULL
;
3668 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
3671 get_ea_list_from_fsp(mem_ctx
,
3673 &total_ea_len
, &ea_file_list
);
3674 if (!NT_STATUS_IS_OK(status
)) {
3678 ea_list
= ea_list_union(ea_list
, ea_file_list
, &total_ea_len
);
3680 if (!ea_list
|| (total_ea_len
> data_size
)) {
3682 SIVAL(pdata
,0,4); /* EA List Length must be set to 4 if no EA's. */
3686 data_size
= fill_ea_buffer(mem_ctx
, pdata
, data_size
, conn
, ea_list
);
3690 case SMB_INFO_QUERY_ALL_EAS
:
3692 /* We have data_size bytes to put EA's into. */
3693 size_t total_ea_len
= 0;
3694 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
3696 status
= get_ea_list_from_fsp(mem_ctx
,
3698 &total_ea_len
, &ea_list
);
3699 if (!NT_STATUS_IS_OK(status
)) {
3703 if (!ea_list
|| (total_ea_len
> data_size
)) {
3705 SIVAL(pdata
,0,4); /* EA List Length must be set to 4 if no EA's. */
3709 data_size
= fill_ea_buffer(mem_ctx
, pdata
, data_size
, conn
, ea_list
);
3713 case SMB2_FILE_FULL_EA_INFORMATION
:
3715 /* We have data_size bytes to put EA's into. */
3716 size_t total_ea_len
= 0;
3717 struct ea_list
*ea_file_list
= NULL
;
3719 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
3721 /*TODO: add filtering and index handling */
3724 get_ea_list_from_fsp(mem_ctx
,
3726 &total_ea_len
, &ea_file_list
);
3727 if (!NT_STATUS_IS_OK(status
)) {
3730 if (!ea_file_list
) {
3731 return NT_STATUS_NO_EAS_ON_FILE
;
3734 status
= fill_ea_chained_buffer(mem_ctx
,
3738 conn
, ea_file_list
);
3739 if (!NT_STATUS_IS_OK(status
)) {
3745 case SMB_FILE_BASIC_INFORMATION
:
3746 case SMB_QUERY_FILE_BASIC_INFO
:
3748 if (info_level
== SMB_QUERY_FILE_BASIC_INFO
) {
3749 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
3750 data_size
= 36; /* w95 returns 40 bytes not 36 - why ?. */
3752 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
3756 put_long_date_full_timespec(conn
->ts_res
,pdata
,&create_time_ts
);
3757 put_long_date_full_timespec(conn
->ts_res
,pdata
+8,&atime_ts
);
3758 put_long_date_full_timespec(conn
->ts_res
,pdata
+16,&mtime_ts
); /* write time */
3759 put_long_date_full_timespec(conn
->ts_res
,pdata
+24,&ctime_ts
); /* change time */
3760 SIVAL(pdata
,32,mode
);
3762 DEBUG(5,("SMB_QFBI - "));
3763 DEBUG(5,("create: %s ", ctime(&create_time
)));
3764 DEBUG(5,("access: %s ", ctime(&atime
)));
3765 DEBUG(5,("write: %s ", ctime(&mtime
)));
3766 DEBUG(5,("change: %s ", ctime(&c_time
)));
3767 DEBUG(5,("mode: %x\n", mode
));
3768 *fixed_portion
= data_size
;
3771 case SMB_FILE_STANDARD_INFORMATION
:
3772 case SMB_QUERY_FILE_STANDARD_INFO
:
3774 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
3776 SOFF_T(pdata
,0,allocation_size
);
3777 SOFF_T(pdata
,8,file_size
);
3778 SIVAL(pdata
,16,nlink
);
3779 SCVAL(pdata
,20,delete_pending
?1:0);
3780 SCVAL(pdata
,21,(mode
&FILE_ATTRIBUTE_DIRECTORY
)?1:0);
3781 SSVAL(pdata
,22,0); /* Padding. */
3782 *fixed_portion
= 24;
3785 case SMB_FILE_EA_INFORMATION
:
3786 case SMB_QUERY_FILE_EA_INFO
:
3788 unsigned int ea_size
=
3789 estimate_ea_size(smb_fname
->fsp
);
3790 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
3793 SIVAL(pdata
,0,ea_size
);
3797 /* Get the 8.3 name - used if NT SMB was negotiated. */
3798 case SMB_QUERY_FILE_ALT_NAME_INFO
:
3799 case SMB_FILE_ALTERNATE_NAME_INFORMATION
:
3801 char mangled_name
[13];
3802 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
3803 if (!name_to_8_3(base_name
,mangled_name
,
3804 True
,conn
->params
)) {
3805 return NT_STATUS_NO_MEMORY
;
3807 status
= srvstr_push(dstart
, flags2
,
3808 pdata
+4, mangled_name
,
3809 PTR_DIFF(dend
, pdata
+4),
3811 if (!NT_STATUS_IS_OK(status
)) {
3814 data_size
= 4 + len
;
3820 case SMB_QUERY_FILE_NAME_INFO
:
3823 this must be *exactly* right for ACLs on mapped drives to work
3825 status
= srvstr_push(dstart
, flags2
,
3827 PTR_DIFF(dend
, pdata
+4),
3829 if (!NT_STATUS_IS_OK(status
)) {
3832 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
3833 data_size
= 4 + len
;
3838 case SMB_FILE_NORMALIZED_NAME_INFORMATION
:
3840 char *nfname
= NULL
;
3842 if (fsp
== NULL
|| !fsp
->conn
->sconn
->using_smb2
) {
3843 return NT_STATUS_INVALID_LEVEL
;
3846 nfname
= talloc_strdup(mem_ctx
, smb_fname
->base_name
);
3847 if (nfname
== NULL
) {
3848 return NT_STATUS_NO_MEMORY
;
3851 if (ISDOT(nfname
)) {
3854 string_replace(nfname
, '/', '\\');
3856 if (fsp_is_alternate_stream(fsp
)) {
3857 const char *s
= smb_fname
->stream_name
;
3858 const char *e
= NULL
;
3861 SMB_ASSERT(s
[0] != '\0');
3864 * smb_fname->stream_name is in form
3865 * of ':StrEam:$DATA', but we should only
3866 * append ':StrEam' here.
3869 e
= strchr(&s
[1], ':');
3875 nfname
= talloc_strndup_append(nfname
, s
, n
);
3876 if (nfname
== NULL
) {
3877 return NT_STATUS_NO_MEMORY
;
3881 status
= srvstr_push(dstart
, flags2
,
3883 PTR_DIFF(dend
, pdata
+4),
3885 if (!NT_STATUS_IS_OK(status
)) {
3888 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NORMALIZED_NAME_INFORMATION\n"));
3889 data_size
= 4 + len
;
3895 case SMB_FILE_ALLOCATION_INFORMATION
:
3896 case SMB_QUERY_FILE_ALLOCATION_INFO
:
3897 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
3899 SOFF_T(pdata
,0,allocation_size
);
3902 case SMB_FILE_END_OF_FILE_INFORMATION
:
3903 case SMB_QUERY_FILE_END_OF_FILEINFO
:
3904 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
3906 SOFF_T(pdata
,0,file_size
);
3909 case SMB_QUERY_FILE_ALL_INFO
:
3910 case SMB_FILE_ALL_INFORMATION
:
3912 unsigned int ea_size
=
3913 estimate_ea_size(smb_fname
->fsp
);
3914 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
3915 put_long_date_full_timespec(conn
->ts_res
,pdata
,&create_time_ts
);
3916 put_long_date_full_timespec(conn
->ts_res
,pdata
+8,&atime_ts
);
3917 put_long_date_full_timespec(conn
->ts_res
,pdata
+16,&mtime_ts
); /* write time */
3918 put_long_date_full_timespec(conn
->ts_res
,pdata
+24,&ctime_ts
); /* change time */
3919 SIVAL(pdata
,32,mode
);
3920 SIVAL(pdata
,36,0); /* padding. */
3922 SOFF_T(pdata
,0,allocation_size
);
3923 SOFF_T(pdata
,8,file_size
);
3924 SIVAL(pdata
,16,nlink
);
3925 SCVAL(pdata
,20,delete_pending
);
3926 SCVAL(pdata
,21,(mode
&FILE_ATTRIBUTE_DIRECTORY
)?1:0);
3929 SIVAL(pdata
,0,ea_size
);
3930 pdata
+= 4; /* EA info */
3931 status
= srvstr_push(dstart
, flags2
,
3933 PTR_DIFF(dend
, pdata
+4),
3935 if (!NT_STATUS_IS_OK(status
)) {
3940 data_size
= PTR_DIFF(pdata
,(*ppdata
));
3941 *fixed_portion
= 10;
3945 case SMB2_FILE_ALL_INFORMATION
:
3947 unsigned int ea_size
=
3948 estimate_ea_size(smb_fname
->fsp
);
3949 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
3950 put_long_date_full_timespec(conn
->ts_res
,pdata
+0x00,&create_time_ts
);
3951 put_long_date_full_timespec(conn
->ts_res
,pdata
+0x08,&atime_ts
);
3952 put_long_date_full_timespec(conn
->ts_res
,pdata
+0x10,&mtime_ts
); /* write time */
3953 put_long_date_full_timespec(conn
->ts_res
,pdata
+0x18,&ctime_ts
); /* change time */
3954 SIVAL(pdata
, 0x20, mode
);
3955 SIVAL(pdata
, 0x24, 0); /* padding. */
3956 SBVAL(pdata
, 0x28, allocation_size
);
3957 SBVAL(pdata
, 0x30, file_size
);
3958 SIVAL(pdata
, 0x38, nlink
);
3959 SCVAL(pdata
, 0x3C, delete_pending
);
3960 SCVAL(pdata
, 0x3D, (mode
&FILE_ATTRIBUTE_DIRECTORY
)?1:0);
3961 SSVAL(pdata
, 0x3E, 0); /* padding */
3962 SBVAL(pdata
, 0x40, file_id
);
3963 SIVAL(pdata
, 0x48, ea_size
);
3964 SIVAL(pdata
, 0x4C, access_mask
);
3965 SBVAL(pdata
, 0x50, pos
);
3966 SIVAL(pdata
, 0x58, mode
); /*TODO: mode != mode fix this!!! */
3967 SIVAL(pdata
, 0x5C, 0); /* No alignment needed. */
3971 status
= srvstr_push(dstart
, flags2
,
3973 PTR_DIFF(dend
, pdata
+4),
3975 if (!NT_STATUS_IS_OK(status
)) {
3980 data_size
= PTR_DIFF(pdata
,(*ppdata
));
3981 *fixed_portion
= 104;
3984 case SMB_FILE_INTERNAL_INFORMATION
:
3986 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
3987 SBVAL(pdata
, 0, file_id
);
3992 case SMB_FILE_ACCESS_INFORMATION
:
3993 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
3994 SIVAL(pdata
, 0, access_mask
);
3999 case SMB_FILE_NAME_INFORMATION
:
4000 /* Pathname with leading '\'. */
4003 byte_len
= dos_PutUniCode(pdata
+4,dos_fname
,(size_t)max_data_bytes
,False
);
4004 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4005 SIVAL(pdata
,0,byte_len
);
4006 data_size
= 4 + byte_len
;
4010 case SMB_FILE_DISPOSITION_INFORMATION
:
4011 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4013 SCVAL(pdata
,0,delete_pending
);
4017 case SMB_FILE_POSITION_INFORMATION
:
4018 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4020 SOFF_T(pdata
,0,pos
);
4024 case SMB_FILE_MODE_INFORMATION
:
4025 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4026 SIVAL(pdata
,0,mode
);
4031 case SMB_FILE_ALIGNMENT_INFORMATION
:
4032 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4033 SIVAL(pdata
,0,0); /* No alignment needed. */
4039 * NT4 server just returns "invalid query" to this - if we try
4040 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4043 /* The first statement above is false - verified using Thursby
4044 * client against NT4 -- gcolley.
4046 case SMB_QUERY_FILE_STREAM_INFO
:
4047 case SMB_FILE_STREAM_INFORMATION
: {
4048 unsigned int num_streams
= 0;
4049 struct stream_struct
*streams
= NULL
;
4051 DEBUG(10,("smbd_do_qfilepathinfo: "
4052 "SMB_FILE_STREAM_INFORMATION\n"));
4054 if (is_ntfs_stream_smb_fname(smb_fname
)) {
4055 return NT_STATUS_INVALID_PARAMETER
;
4058 status
= vfs_fstreaminfo(fsp
,
4063 if (!NT_STATUS_IS_OK(status
)) {
4064 DEBUG(10, ("could not get stream info: %s\n",
4065 nt_errstr(status
)));
4069 status
= marshall_stream_info(num_streams
, streams
,
4070 pdata
, max_data_bytes
,
4073 if (!NT_STATUS_IS_OK(status
)) {
4074 DEBUG(10, ("marshall_stream_info failed: %s\n",
4075 nt_errstr(status
)));
4076 TALLOC_FREE(streams
);
4080 TALLOC_FREE(streams
);
4082 *fixed_portion
= 32;
4086 case SMB_QUERY_COMPRESSION_INFO
:
4087 case SMB_FILE_COMPRESSION_INFORMATION
:
4088 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4089 SOFF_T(pdata
,0,file_size
);
4090 SIVAL(pdata
,8,0); /* ??? */
4091 SIVAL(pdata
,12,0); /* ??? */
4093 *fixed_portion
= 16;
4096 case SMB_FILE_NETWORK_OPEN_INFORMATION
:
4097 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4098 put_long_date_full_timespec(conn
->ts_res
,pdata
,&create_time_ts
);
4099 put_long_date_full_timespec(conn
->ts_res
,pdata
+8,&atime_ts
);
4100 put_long_date_full_timespec(conn
->ts_res
,pdata
+16,&mtime_ts
); /* write time */
4101 put_long_date_full_timespec(conn
->ts_res
,pdata
+24,&ctime_ts
); /* change time */
4102 SOFF_T(pdata
,32,allocation_size
);
4103 SOFF_T(pdata
,40,file_size
);
4104 SIVAL(pdata
,48,mode
);
4105 SIVAL(pdata
,52,0); /* ??? */
4107 *fixed_portion
= 56;
4110 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION
:
4111 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4112 SIVAL(pdata
,0,mode
);
4119 * CIFS UNIX Extensions.
4122 case SMB_QUERY_FILE_UNIX_BASIC
:
4124 pdata
= store_file_unix_basic(conn
, pdata
, fsp
, psbuf
);
4125 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4127 DEBUG(4,("smbd_do_qfilepathinfo: "
4128 "SMB_QUERY_FILE_UNIX_BASIC\n"));
4129 dump_data(4, (uint8_t *)(*ppdata
), data_size
);
4133 case SMB_QUERY_FILE_UNIX_INFO2
:
4135 pdata
= store_file_unix_basic_info2(conn
, pdata
, fsp
, psbuf
);
4136 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4140 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4142 for (i
=0; i
<100; i
++)
4143 DEBUG(4,("%d=%x, ",i
, (*ppdata
)[i
]));
4149 case SMB_QUERY_FILE_UNIX_LINK
:
4151 status
= smb_unix_read_symlink(conn
,
4157 if (!NT_STATUS_IS_OK(status
)) {
4163 #if defined(HAVE_POSIX_ACLS)
4164 case SMB_QUERY_POSIX_ACL
:
4166 status
= smb_query_posix_acl(conn
,
4173 if (!NT_STATUS_IS_OK(status
)) {
4181 case SMB_QUERY_POSIX_LOCK
:
4186 enum brl_type lock_type
;
4188 /* We need an open file with a real fd for this. */
4190 fsp
->fsp_flags
.is_pathref
||
4191 fsp_get_io_fd(fsp
) == -1)
4193 return NT_STATUS_INVALID_LEVEL
;
4196 if (lock_data_count
!= POSIX_LOCK_DATA_SIZE
) {
4197 return NT_STATUS_INVALID_PARAMETER
;
4200 switch (SVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
)) {
4201 case POSIX_LOCK_TYPE_READ
:
4202 lock_type
= READ_LOCK
;
4204 case POSIX_LOCK_TYPE_WRITE
:
4205 lock_type
= WRITE_LOCK
;
4207 case POSIX_LOCK_TYPE_UNLOCK
:
4209 /* There's no point in asking for an unlock... */
4210 return NT_STATUS_INVALID_PARAMETER
;
4213 smblctx
= (uint64_t)IVAL(pdata
, POSIX_LOCK_PID_OFFSET
);
4214 offset
= BVAL(pdata
,POSIX_LOCK_START_OFFSET
);
4215 count
= BVAL(pdata
,POSIX_LOCK_LEN_OFFSET
);
4217 status
= query_lock(fsp
,
4224 if (ERROR_WAS_LOCK_DENIED(status
)) {
4225 /* Here we need to report who has it locked... */
4226 data_size
= POSIX_LOCK_DATA_SIZE
;
4228 SSVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
, lock_type
);
4229 SSVAL(pdata
, POSIX_LOCK_FLAGS_OFFSET
, 0);
4230 SIVAL(pdata
, POSIX_LOCK_PID_OFFSET
, (uint32_t)smblctx
);
4231 SBVAL(pdata
, POSIX_LOCK_START_OFFSET
, offset
);
4232 SBVAL(pdata
, POSIX_LOCK_LEN_OFFSET
, count
);
4234 } else if (NT_STATUS_IS_OK(status
)) {
4235 /* For success we just return a copy of what we sent
4236 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4237 data_size
= POSIX_LOCK_DATA_SIZE
;
4238 memcpy(pdata
, lock_data
, POSIX_LOCK_DATA_SIZE
);
4239 SSVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
, POSIX_LOCK_TYPE_UNLOCK
);
4247 return NT_STATUS_INVALID_LEVEL
;
4250 *pdata_size
= data_size
;
4251 return NT_STATUS_OK
;
4254 /****************************************************************************
4255 Set a hard link (called by UNIX extensions and by NT rename with HARD link
4257 ****************************************************************************/
4259 NTSTATUS
hardlink_internals(TALLOC_CTX
*ctx
,
4260 connection_struct
*conn
,
4261 struct smb_request
*req
,
4262 bool overwrite_if_exists
,
4263 struct files_struct
*old_dirfsp
,
4264 const struct smb_filename
*smb_fname_old
,
4265 struct files_struct
*new_dirfsp
,
4266 struct smb_filename
*smb_fname_new
)
4268 NTSTATUS status
= NT_STATUS_OK
;
4271 struct smb_filename
*parent_fname_old
= NULL
;
4272 struct smb_filename
*base_name_old
= NULL
;
4273 struct smb_filename
*parent_fname_new
= NULL
;
4274 struct smb_filename
*base_name_new
= NULL
;
4276 /* source must already exist. */
4277 if (!VALID_STAT(smb_fname_old
->st
)) {
4278 status
= NT_STATUS_OBJECT_NAME_NOT_FOUND
;
4282 /* No links from a directory. */
4283 if (S_ISDIR(smb_fname_old
->st
.st_ex_mode
)) {
4284 status
= NT_STATUS_FILE_IS_A_DIRECTORY
;
4288 /* Setting a hardlink to/from a stream isn't currently supported. */
4289 ok
= is_ntfs_stream_smb_fname(smb_fname_old
);
4291 DBG_DEBUG("Old name has streams\n");
4292 status
= NT_STATUS_INVALID_PARAMETER
;
4295 ok
= is_ntfs_stream_smb_fname(smb_fname_new
);
4297 DBG_DEBUG("New name has streams\n");
4298 status
= NT_STATUS_INVALID_PARAMETER
;
4302 status
= parent_pathref(talloc_tos(),
4307 if (!NT_STATUS_IS_OK(status
)) {
4311 status
= parent_pathref(talloc_tos(),
4316 if (!NT_STATUS_IS_OK(status
)) {
4320 if (VALID_STAT(smb_fname_new
->st
)) {
4321 if (overwrite_if_exists
) {
4322 if (S_ISDIR(smb_fname_new
->st
.st_ex_mode
)) {
4323 status
= NT_STATUS_FILE_IS_A_DIRECTORY
;
4326 status
= unlink_internals(conn
,
4328 FILE_ATTRIBUTE_NORMAL
,
4329 NULL
, /* new_dirfsp */
4331 if (!NT_STATUS_IS_OK(status
)) {
4335 /* Disallow if newname already exists. */
4336 status
= NT_STATUS_OBJECT_NAME_COLLISION
;
4341 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
4342 smb_fname_old
->base_name
, smb_fname_new
->base_name
));
4344 ret
= SMB_VFS_LINKAT(conn
,
4345 parent_fname_old
->fsp
,
4347 parent_fname_new
->fsp
,
4352 status
= map_nt_error_from_unix(errno
);
4353 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
4354 nt_errstr(status
), smb_fname_old
->base_name
,
4355 smb_fname_new
->base_name
));
4360 TALLOC_FREE(parent_fname_old
);
4361 TALLOC_FREE(parent_fname_new
);
4365 /****************************************************************************
4366 Deal with setting the time from any of the setfilepathinfo functions.
4367 NOTE !!!! The check for FILE_WRITE_ATTRIBUTES access must be done *before*
4368 calling this function.
4369 ****************************************************************************/
4371 NTSTATUS
smb_set_file_time(connection_struct
*conn
,
4373 struct smb_filename
*smb_fname
,
4374 struct smb_file_time
*ft
,
4375 bool setting_write_time
)
4377 struct files_struct
*set_fsp
= NULL
;
4378 struct timeval_buf tbuf
[4];
4380 FILE_NOTIFY_CHANGE_LAST_ACCESS
4381 |FILE_NOTIFY_CHANGE_LAST_WRITE
4382 |FILE_NOTIFY_CHANGE_CREATION
;
4385 if (!VALID_STAT(smb_fname
->st
)) {
4386 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
4391 return NT_STATUS_OK
;
4394 set_fsp
= metadata_fsp(fsp
);
4396 /* get some defaults (no modifications) if any info is zero or -1. */
4397 if (is_omit_timespec(&ft
->create_time
)) {
4398 action
&= ~FILE_NOTIFY_CHANGE_CREATION
;
4401 if (is_omit_timespec(&ft
->atime
)) {
4402 action
&= ~FILE_NOTIFY_CHANGE_LAST_ACCESS
;
4405 if (is_omit_timespec(&ft
->mtime
)) {
4406 action
&= ~FILE_NOTIFY_CHANGE_LAST_WRITE
;
4409 if (!setting_write_time
) {
4410 /* ft->mtime comes from change time, not write time. */
4411 action
&= ~FILE_NOTIFY_CHANGE_LAST_WRITE
;
4414 /* Ensure the resolution is the correct for
4415 * what we can store on this filesystem. */
4417 round_timespec(conn
->ts_res
, &ft
->create_time
);
4418 round_timespec(conn
->ts_res
, &ft
->ctime
);
4419 round_timespec(conn
->ts_res
, &ft
->atime
);
4420 round_timespec(conn
->ts_res
, &ft
->mtime
);
4422 DBG_DEBUG("smb_set_filetime: actime: %s\n ",
4423 timespec_string_buf(&ft
->atime
, true, &tbuf
[0]));
4424 DBG_DEBUG("smb_set_filetime: modtime: %s\n ",
4425 timespec_string_buf(&ft
->mtime
, true, &tbuf
[1]));
4426 DBG_DEBUG("smb_set_filetime: ctime: %s\n ",
4427 timespec_string_buf(&ft
->ctime
, true, &tbuf
[2]));
4428 DBG_DEBUG("smb_set_file_time: createtime: %s\n ",
4429 timespec_string_buf(&ft
->create_time
, true, &tbuf
[3]));
4431 if (setting_write_time
) {
4433 * This was a Windows setfileinfo on an open file.
4434 * NT does this a lot. We also need to
4435 * set the time here, as it can be read by
4436 * FindFirst/FindNext and with the patch for bug #2045
4437 * in smbd/fileio.c it ensures that this timestamp is
4438 * kept sticky even after a write. We save the request
4439 * away and will set it on file close and after a write. JRA.
4442 DBG_DEBUG("setting pending modtime to %s\n",
4443 timespec_string_buf(&ft
->mtime
, true, &tbuf
[0]));
4445 if (set_fsp
!= NULL
) {
4446 set_sticky_write_time_fsp(set_fsp
, ft
->mtime
);
4448 set_sticky_write_time_path(
4449 vfs_file_id_from_sbuf(conn
, &smb_fname
->st
),
4454 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
4456 ret
= file_ntimes(conn
, set_fsp
, ft
);
4458 return map_nt_error_from_unix(errno
);
4461 notify_fname(conn
, NOTIFY_ACTION_MODIFIED
, action
,
4462 smb_fname
->base_name
);
4463 return NT_STATUS_OK
;
4466 /****************************************************************************
4467 Deal with setting the dosmode from any of the setfilepathinfo functions.
4468 NB. The check for FILE_WRITE_ATTRIBUTES access on this path must have been
4469 done before calling this function.
4470 ****************************************************************************/
4472 static NTSTATUS
smb_set_file_dosmode(connection_struct
*conn
,
4473 struct files_struct
*fsp
,
4476 struct files_struct
*dos_fsp
= NULL
;
4477 uint32_t current_dosmode
;
4480 if (!VALID_STAT(fsp
->fsp_name
->st
)) {
4481 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
4484 dos_fsp
= metadata_fsp(fsp
);
4487 if (S_ISDIR(fsp
->fsp_name
->st
.st_ex_mode
)) {
4488 dosmode
|= FILE_ATTRIBUTE_DIRECTORY
;
4490 dosmode
&= ~FILE_ATTRIBUTE_DIRECTORY
;
4494 DBG_DEBUG("dosmode: 0x%" PRIx32
"\n", dosmode
);
4496 /* check the mode isn't different, before changing it */
4498 return NT_STATUS_OK
;
4500 current_dosmode
= fdos_mode(dos_fsp
);
4501 if (dosmode
== current_dosmode
) {
4502 return NT_STATUS_OK
;
4505 DBG_DEBUG("file %s : setting dos mode 0x%" PRIx32
"\n",
4506 fsp_str_dbg(dos_fsp
), dosmode
);
4508 ret
= file_set_dosmode(conn
, dos_fsp
->fsp_name
, dosmode
, NULL
, false);
4510 DBG_WARNING("file_set_dosmode of %s failed: %s\n",
4511 fsp_str_dbg(dos_fsp
), strerror(errno
));
4512 return map_nt_error_from_unix(errno
);
4515 return NT_STATUS_OK
;
4518 /****************************************************************************
4519 Deal with setting the size from any of the setfilepathinfo functions.
4520 ****************************************************************************/
4522 static NTSTATUS
smb_set_file_size(connection_struct
*conn
,
4523 struct smb_request
*req
,
4525 struct smb_filename
*smb_fname
,
4526 const SMB_STRUCT_STAT
*psbuf
,
4528 bool fail_after_createfile
)
4530 NTSTATUS status
= NT_STATUS_OK
;
4531 files_struct
*new_fsp
= NULL
;
4533 if (!VALID_STAT(*psbuf
)) {
4534 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
4537 DBG_INFO("size: %"PRIu64
", file_size_stat=%"PRIu64
"\n",
4539 get_file_size_stat(psbuf
));
4541 if (size
== get_file_size_stat(psbuf
)) {
4543 return NT_STATUS_OK
;
4545 if (!fsp
->fsp_flags
.modified
) {
4546 return NT_STATUS_OK
;
4548 trigger_write_time_update_immediate(fsp
);
4549 return NT_STATUS_OK
;
4552 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
4553 smb_fname_str_dbg(smb_fname
), (double)size
));
4556 !fsp
->fsp_flags
.is_pathref
&&
4557 fsp_get_io_fd(fsp
) != -1)
4559 /* Handle based call. */
4560 if (!(fsp
->access_mask
& FILE_WRITE_DATA
)) {
4561 return NT_STATUS_ACCESS_DENIED
;
4564 if (vfs_set_filelen(fsp
, size
) == -1) {
4565 return map_nt_error_from_unix(errno
);
4567 trigger_write_time_update_immediate(fsp
);
4568 return NT_STATUS_OK
;
4571 status
= SMB_VFS_CREATE_FILE(
4575 smb_fname
, /* fname */
4576 FILE_WRITE_DATA
, /* access_mask */
4577 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
4579 FILE_OPEN
, /* create_disposition*/
4580 0, /* create_options */
4581 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
4582 0, /* oplock_request */
4584 0, /* allocation_size */
4585 0, /* private_flags */
4588 &new_fsp
, /* result */
4590 NULL
, NULL
); /* create context */
4592 if (!NT_STATUS_IS_OK(status
)) {
4593 /* NB. We check for open_was_deferred in the caller. */
4597 /* See RAW-SFILEINFO-END-OF-FILE */
4598 if (fail_after_createfile
) {
4599 close_file_free(req
, &new_fsp
, NORMAL_CLOSE
);
4600 return NT_STATUS_INVALID_LEVEL
;
4603 if (vfs_set_filelen(new_fsp
, size
) == -1) {
4604 status
= map_nt_error_from_unix(errno
);
4605 close_file_free(req
, &new_fsp
, NORMAL_CLOSE
);
4609 trigger_write_time_update_immediate(new_fsp
);
4610 close_file_free(req
, &new_fsp
, NORMAL_CLOSE
);
4611 return NT_STATUS_OK
;
4614 /****************************************************************************
4615 Deal with SMB_INFO_SET_EA.
4616 ****************************************************************************/
4618 static NTSTATUS
smb_info_set_ea(connection_struct
*conn
,
4622 struct smb_filename
*smb_fname
)
4624 struct ea_list
*ea_list
= NULL
;
4625 TALLOC_CTX
*ctx
= NULL
;
4626 NTSTATUS status
= NT_STATUS_OK
;
4628 if (total_data
< 10) {
4630 /* OS/2 workplace shell seems to send SET_EA requests of "null"
4631 length. They seem to have no effect. Bug #3212. JRA */
4633 if ((total_data
== 4) && (IVAL(pdata
,0) == 4)) {
4634 /* We're done. We only get EA info in this call. */
4635 return NT_STATUS_OK
;
4638 return NT_STATUS_INVALID_PARAMETER
;
4641 if (IVAL(pdata
,0) > total_data
) {
4642 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
4643 IVAL(pdata
,0), (unsigned int)total_data
));
4644 return NT_STATUS_INVALID_PARAMETER
;
4648 ea_list
= read_ea_list(ctx
, pdata
+ 4, total_data
- 4);
4650 return NT_STATUS_INVALID_PARAMETER
;
4655 * The only way fsp can be NULL here is if
4656 * smb_fname points at a symlink and
4657 * and we're in POSIX context.
4658 * Ensure this is the case.
4660 * In this case we cannot set the EA.
4662 SMB_ASSERT(smb_fname
->flags
& SMB_FILENAME_POSIX_PATH
);
4663 return NT_STATUS_ACCESS_DENIED
;
4666 status
= set_ea(conn
, fsp
, ea_list
);
4671 /****************************************************************************
4672 Deal with SMB_FILE_FULL_EA_INFORMATION set.
4673 ****************************************************************************/
4675 static NTSTATUS
smb_set_file_full_ea_info(connection_struct
*conn
,
4680 struct ea_list
*ea_list
= NULL
;
4684 return NT_STATUS_INVALID_HANDLE
;
4687 if (!lp_ea_support(SNUM(conn
))) {
4688 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
4689 "EA's not supported.\n",
4690 (unsigned int)total_data
));
4691 return NT_STATUS_EAS_NOT_SUPPORTED
;
4694 if (total_data
< 10) {
4695 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
4697 (unsigned int)total_data
));
4698 return NT_STATUS_INVALID_PARAMETER
;
4701 ea_list
= read_nttrans_ea_list(talloc_tos(),
4706 return NT_STATUS_INVALID_PARAMETER
;
4709 status
= set_ea(conn
, fsp
, ea_list
);
4711 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
4712 smb_fname_str_dbg(fsp
->fsp_name
),
4713 nt_errstr(status
) ));
4719 /****************************************************************************
4720 Deal with SMB_SET_FILE_DISPOSITION_INFO.
4721 ****************************************************************************/
4723 static NTSTATUS
smb_set_file_disposition_info(connection_struct
*conn
,
4727 struct smb_filename
*smb_fname
)
4729 NTSTATUS status
= NT_STATUS_OK
;
4730 bool delete_on_close
;
4731 uint32_t dosmode
= 0;
4733 if (total_data
< 1) {
4734 return NT_STATUS_INVALID_PARAMETER
;
4738 return NT_STATUS_INVALID_HANDLE
;
4741 delete_on_close
= (CVAL(pdata
,0) ? True
: False
);
4742 dosmode
= fdos_mode(fsp
);
4744 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
4745 "delete_on_close = %u\n",
4746 smb_fname_str_dbg(smb_fname
),
4747 (unsigned int)dosmode
,
4748 (unsigned int)delete_on_close
));
4750 if (delete_on_close
) {
4751 status
= can_set_delete_on_close(fsp
, dosmode
);
4752 if (!NT_STATUS_IS_OK(status
)) {
4757 /* The set is across all open files on this dev/inode pair. */
4758 if (!set_delete_on_close(fsp
, delete_on_close
,
4759 conn
->session_info
->security_token
,
4760 conn
->session_info
->unix_token
)) {
4761 return NT_STATUS_ACCESS_DENIED
;
4763 return NT_STATUS_OK
;
4766 /****************************************************************************
4767 Deal with SMB_FILE_POSITION_INFORMATION.
4768 ****************************************************************************/
4770 static NTSTATUS
smb_file_position_information(connection_struct
*conn
,
4775 uint64_t position_information
;
4777 if (total_data
< 8) {
4778 return NT_STATUS_INVALID_PARAMETER
;
4782 /* Ignore on pathname based set. */
4783 return NT_STATUS_OK
;
4786 position_information
= (uint64_t)IVAL(pdata
,0);
4787 position_information
|= (((uint64_t)IVAL(pdata
,4)) << 32);
4789 DEBUG(10,("smb_file_position_information: Set file position "
4790 "information for file %s to %.0f\n", fsp_str_dbg(fsp
),
4791 (double)position_information
));
4792 fh_set_position_information(fsp
->fh
, position_information
);
4793 return NT_STATUS_OK
;
4796 /****************************************************************************
4797 Deal with SMB_FILE_MODE_INFORMATION.
4798 ****************************************************************************/
4800 static NTSTATUS
smb_file_mode_information(connection_struct
*conn
,
4806 if (total_data
< 4) {
4807 return NT_STATUS_INVALID_PARAMETER
;
4809 mode
= IVAL(pdata
,0);
4810 if (mode
!= 0 && mode
!= 2 && mode
!= 4 && mode
!= 6) {
4811 return NT_STATUS_INVALID_PARAMETER
;
4813 return NT_STATUS_OK
;
4816 /****************************************************************************
4817 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
4818 ****************************************************************************/
4820 static NTSTATUS
smb_set_file_unix_link(connection_struct
*conn
,
4821 struct smb_request
*req
,
4824 struct smb_filename
*new_smb_fname
)
4826 char *link_target
= NULL
;
4827 struct smb_filename target_fname
;
4828 TALLOC_CTX
*ctx
= talloc_tos();
4831 struct smb_filename
*parent_fname
= NULL
;
4832 struct smb_filename
*base_name
= NULL
;
4834 /* Set a symbolic link. */
4835 /* Don't allow this if follow links is false. */
4837 if (total_data
== 0) {
4838 return NT_STATUS_INVALID_PARAMETER
;
4841 if (!lp_follow_symlinks(SNUM(conn
))) {
4842 return NT_STATUS_ACCESS_DENIED
;
4845 srvstr_pull_talloc(ctx
, pdata
, req
->flags2
, &link_target
, pdata
,
4846 total_data
, STR_TERMINATE
);
4849 return NT_STATUS_INVALID_PARAMETER
;
4852 target_fname
= (struct smb_filename
) {
4853 .base_name
= link_target
,
4856 /* Removes @GMT tokens if any */
4857 status
= canonicalize_snapshot_path(&target_fname
, UCF_GMT_PATHNAME
, 0);
4858 if (!NT_STATUS_IS_OK(status
)) {
4862 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
4863 new_smb_fname
->base_name
, link_target
));
4865 status
= parent_pathref(talloc_tos(),
4870 if (!NT_STATUS_IS_OK(status
)) {
4874 ret
= SMB_VFS_SYMLINKAT(conn
,
4879 TALLOC_FREE(parent_fname
);
4880 return map_nt_error_from_unix(errno
);
4883 TALLOC_FREE(parent_fname
);
4884 return NT_STATUS_OK
;
4887 /****************************************************************************
4888 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
4889 ****************************************************************************/
4891 static NTSTATUS
smb_set_file_unix_hlink(connection_struct
*conn
,
4892 struct smb_request
*req
,
4893 const char *pdata
, int total_data
,
4894 struct smb_filename
*smb_fname_new
)
4896 char *oldname
= NULL
;
4897 struct files_struct
*src_dirfsp
= NULL
;
4898 struct smb_filename
*smb_fname_old
= NULL
;
4899 uint32_t ucf_flags
= ucf_flags_from_smb_request(req
);
4900 NTTIME old_twrp
= 0;
4901 TALLOC_CTX
*ctx
= talloc_tos();
4902 NTSTATUS status
= NT_STATUS_OK
;
4904 /* Set a hard link. */
4905 if (total_data
== 0) {
4906 return NT_STATUS_INVALID_PARAMETER
;
4909 if (req
->posix_pathnames
) {
4910 srvstr_get_path_posix(ctx
,
4919 srvstr_get_path(ctx
,
4928 if (!NT_STATUS_IS_OK(status
)) {
4932 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
4933 smb_fname_str_dbg(smb_fname_new
), oldname
));
4935 if (ucf_flags
& UCF_GMT_PATHNAME
) {
4936 extract_snapshot_token(oldname
, &old_twrp
);
4938 status
= filename_convert_dirfsp(ctx
,
4945 if (!NT_STATUS_IS_OK(status
)) {
4949 return hardlink_internals(ctx
,
4955 NULL
, /* new_dirfsp */
4959 /****************************************************************************
4960 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
4961 ****************************************************************************/
4963 static NTSTATUS
smb2_file_rename_information(connection_struct
*conn
,
4964 struct smb_request
*req
,
4968 struct smb_filename
*smb_fname_src
)
4972 char *newname
= NULL
;
4973 struct files_struct
*dst_dirfsp
= NULL
;
4974 struct smb_filename
*smb_fname_dst
= NULL
;
4975 const char *dst_original_lcomp
= NULL
;
4976 uint32_t ucf_flags
= ucf_flags_from_smb_request(req
);
4977 NTTIME dst_twrp
= 0;
4978 NTSTATUS status
= NT_STATUS_OK
;
4979 bool is_dfs
= (req
->flags2
& FLAGS2_DFS_PATHNAMES
);
4980 TALLOC_CTX
*ctx
= talloc_tos();
4983 return NT_STATUS_INVALID_HANDLE
;
4986 if (total_data
< 20) {
4987 return NT_STATUS_INVALID_PARAMETER
;
4990 overwrite
= (CVAL(pdata
,0) ? True
: False
);
4991 len
= IVAL(pdata
,16);
4993 if (len
> (total_data
- 20) || (len
== 0)) {
4994 return NT_STATUS_INVALID_PARAMETER
;
4997 (void)srvstr_pull_talloc(ctx
,
5005 if (newname
== NULL
) {
5006 return NT_STATUS_INVALID_PARAMETER
;
5008 status
= check_path_syntax_smb2(newname
, is_dfs
);
5009 if (!NT_STATUS_IS_OK(status
)) {
5013 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
5016 if (newname
[0] == ':') {
5017 /* Create an smb_fname to call rename_internals_fsp() with. */
5018 smb_fname_dst
= synthetic_smb_fname(talloc_tos(),
5019 fsp
->base_fsp
->fsp_name
->base_name
,
5022 fsp
->base_fsp
->fsp_name
->twrp
,
5023 fsp
->base_fsp
->fsp_name
->flags
);
5024 if (smb_fname_dst
== NULL
) {
5025 status
= NT_STATUS_NO_MEMORY
;
5029 if (ucf_flags
& UCF_GMT_PATHNAME
) {
5030 extract_snapshot_token(newname
, &dst_twrp
);
5032 status
= filename_convert_dirfsp(ctx
,
5039 if (!NT_STATUS_IS_OK(status
)) {
5045 * Set the original last component, since
5046 * rename_internals_fsp() requires it.
5048 dst_original_lcomp
= get_original_lcomp(smb_fname_dst
,
5052 if (dst_original_lcomp
== NULL
) {
5053 status
= NT_STATUS_NO_MEMORY
;
5057 DEBUG(10,("smb2_file_rename_information: "
5058 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
5059 fsp_fnum_dbg(fsp
), fsp_str_dbg(fsp
),
5060 smb_fname_str_dbg(smb_fname_dst
)));
5061 status
= rename_internals_fsp(conn
,
5063 NULL
, /* dst_dirfsp */
5066 (FILE_ATTRIBUTE_HIDDEN
|FILE_ATTRIBUTE_SYSTEM
),
5070 TALLOC_FREE(smb_fname_dst
);
5074 static NTSTATUS
smb_file_link_information(connection_struct
*conn
,
5075 struct smb_request
*req
,
5079 struct smb_filename
*smb_fname_src
)
5083 char *newname
= NULL
;
5084 struct files_struct
*dst_dirfsp
= NULL
;
5085 struct smb_filename
*smb_fname_dst
= NULL
;
5086 NTSTATUS status
= NT_STATUS_OK
;
5087 uint32_t ucf_flags
= ucf_flags_from_smb_request(req
);
5088 NTTIME dst_twrp
= 0;
5089 TALLOC_CTX
*ctx
= talloc_tos();
5092 return NT_STATUS_INVALID_HANDLE
;
5095 if (total_data
< 20) {
5096 return NT_STATUS_INVALID_PARAMETER
;
5099 overwrite
= (CVAL(pdata
,0) ? true : false);
5100 len
= IVAL(pdata
,16);
5102 if (len
> (total_data
- 20) || (len
== 0)) {
5103 return NT_STATUS_INVALID_PARAMETER
;
5106 if (smb_fname_src
->flags
& SMB_FILENAME_POSIX_PATH
) {
5107 srvstr_get_path_posix(ctx
,
5115 ucf_flags
|= UCF_POSIX_PATHNAMES
;
5117 srvstr_get_path(ctx
,
5126 if (!NT_STATUS_IS_OK(status
)) {
5130 DEBUG(10,("smb_file_link_information: got name |%s|\n",
5133 if (ucf_flags
& UCF_GMT_PATHNAME
) {
5134 extract_snapshot_token(newname
, &dst_twrp
);
5136 status
= filename_convert_dirfsp(ctx
,
5143 if (!NT_STATUS_IS_OK(status
)) {
5147 if (fsp
->base_fsp
) {
5148 /* No stream names. */
5149 return NT_STATUS_NOT_SUPPORTED
;
5152 DEBUG(10,("smb_file_link_information: "
5153 "SMB_FILE_LINK_INFORMATION (%s) %s -> %s\n",
5154 fsp_fnum_dbg(fsp
), fsp_str_dbg(fsp
),
5155 smb_fname_str_dbg(smb_fname_dst
)));
5156 status
= hardlink_internals(ctx
,
5160 NULL
, /* src_dirfsp */
5162 dst_dirfsp
, /* dst_dirfsp */
5165 TALLOC_FREE(smb_fname_dst
);
5169 /****************************************************************************
5170 Deal with SMB_FILE_RENAME_INFORMATION.
5171 ****************************************************************************/
5173 static NTSTATUS
smb_file_rename_information(connection_struct
*conn
,
5174 struct smb_request
*req
,
5178 struct smb_filename
*smb_fname_src
)
5183 char *newname
= NULL
;
5184 struct files_struct
*dst_dirfsp
= NULL
;
5185 struct smb_filename
*smb_fname_dst
= NULL
;
5186 const char *dst_original_lcomp
= NULL
;
5187 NTSTATUS status
= NT_STATUS_OK
;
5189 TALLOC_CTX
*ctx
= talloc_tos();
5191 if (total_data
< 13) {
5192 return NT_STATUS_INVALID_PARAMETER
;
5195 overwrite
= (CVAL(pdata
,0) != 0);
5196 root_fid
= IVAL(pdata
,4);
5197 len
= IVAL(pdata
,8);
5199 if (len
> (total_data
- 12) || (len
== 0) || (root_fid
!= 0)) {
5200 return NT_STATUS_INVALID_PARAMETER
;
5203 if (req
->posix_pathnames
) {
5204 srvstr_get_path_posix(ctx
,
5213 srvstr_get_path(ctx
,
5222 if (!NT_STATUS_IS_OK(status
)) {
5226 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
5229 /* Check the new name has no '/' characters. */
5230 if (strchr_m(newname
, '/')) {
5231 return NT_STATUS_NOT_SUPPORTED
;
5234 if (fsp
&& fsp
->base_fsp
) {
5235 /* newname must be a stream name. */
5236 if (newname
[0] != ':') {
5237 return NT_STATUS_NOT_SUPPORTED
;
5240 /* Create an smb_fname to call rename_internals_fsp() with. */
5241 smb_fname_dst
= synthetic_smb_fname(talloc_tos(),
5242 fsp
->base_fsp
->fsp_name
->base_name
,
5245 fsp
->base_fsp
->fsp_name
->twrp
,
5246 fsp
->base_fsp
->fsp_name
->flags
);
5247 if (smb_fname_dst
== NULL
) {
5248 status
= NT_STATUS_NO_MEMORY
;
5253 * Get the original last component, since
5254 * rename_internals_fsp() requires it.
5256 dst_original_lcomp
= get_original_lcomp(smb_fname_dst
,
5260 if (dst_original_lcomp
== NULL
) {
5261 status
= NT_STATUS_NO_MEMORY
;
5267 * Build up an smb_fname_dst based on the filename passed in.
5268 * We basically just strip off the last component, and put on
5269 * the newname instead.
5271 char *base_name
= NULL
;
5272 uint32_t ucf_flags
= ucf_flags_from_smb_request(req
);
5273 NTTIME dst_twrp
= 0;
5275 /* newname must *not* be a stream name. */
5276 if (newname
[0] == ':') {
5277 return NT_STATUS_NOT_SUPPORTED
;
5281 * Strip off the last component (filename) of the path passed
5284 base_name
= talloc_strdup(ctx
, smb_fname_src
->base_name
);
5286 return NT_STATUS_NO_MEMORY
;
5288 p
= strrchr_m(base_name
, '/');
5292 base_name
= talloc_strdup(ctx
, "");
5294 return NT_STATUS_NO_MEMORY
;
5297 /* Append the new name. */
5298 base_name
= talloc_asprintf_append(base_name
,
5302 return NT_STATUS_NO_MEMORY
;
5305 if (ucf_flags
& UCF_GMT_PATHNAME
) {
5306 extract_snapshot_token(base_name
, &dst_twrp
);
5308 status
= filename_convert_dirfsp(ctx
,
5316 if (!NT_STATUS_IS_OK(status
)) {
5319 dst_original_lcomp
= get_original_lcomp(smb_fname_dst
,
5323 if (dst_original_lcomp
== NULL
) {
5324 status
= NT_STATUS_NO_MEMORY
;
5329 if (fsp
!= NULL
&& fsp
->fsp_flags
.is_fsa
) {
5330 DEBUG(10,("smb_file_rename_information: "
5331 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
5332 fsp_fnum_dbg(fsp
), fsp_str_dbg(fsp
),
5333 smb_fname_str_dbg(smb_fname_dst
)));
5334 status
= rename_internals_fsp(conn
,
5342 DEBUG(10,("smb_file_rename_information: "
5343 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
5344 smb_fname_str_dbg(smb_fname_src
),
5345 smb_fname_str_dbg(smb_fname_dst
)));
5346 status
= rename_internals(ctx
,
5349 NULL
, /* src_dirfsp */
5356 FILE_WRITE_ATTRIBUTES
);
5359 TALLOC_FREE(smb_fname_dst
);
5363 /****************************************************************************
5364 Deal with SMB_SET_POSIX_ACL.
5365 ****************************************************************************/
5367 #if defined(HAVE_POSIX_ACLS)
5368 static NTSTATUS
smb_set_posix_acl(connection_struct
*conn
,
5369 struct smb_request
*req
,
5373 struct smb_filename
*smb_fname
)
5375 uint16_t posix_acl_version
;
5376 uint16_t num_file_acls
;
5377 uint16_t num_def_acls
;
5378 bool valid_file_acls
= true;
5379 bool valid_def_acls
= true;
5381 unsigned int size_needed
;
5382 unsigned int total_data
;
5383 bool close_fsp
= false;
5385 if (total_data_in
< 0) {
5386 status
= NT_STATUS_INVALID_PARAMETER
;
5390 total_data
= total_data_in
;
5392 if (total_data
< SMB_POSIX_ACL_HEADER_SIZE
) {
5393 status
= NT_STATUS_INVALID_PARAMETER
;
5396 posix_acl_version
= SVAL(pdata
,0);
5397 num_file_acls
= SVAL(pdata
,2);
5398 num_def_acls
= SVAL(pdata
,4);
5400 if (num_file_acls
== SMB_POSIX_IGNORE_ACE_ENTRIES
) {
5401 valid_file_acls
= false;
5405 if (num_def_acls
== SMB_POSIX_IGNORE_ACE_ENTRIES
) {
5406 valid_def_acls
= false;
5410 if (posix_acl_version
!= SMB_POSIX_ACL_VERSION
) {
5411 status
= NT_STATUS_INVALID_PARAMETER
;
5416 if (num_file_acls
+ num_def_acls
< num_file_acls
) {
5417 status
= NT_STATUS_INVALID_PARAMETER
;
5421 size_needed
= num_file_acls
+ num_def_acls
;
5424 * (size_needed * SMB_POSIX_ACL_ENTRY_SIZE) must be less
5425 * than UINT_MAX, so check by division.
5427 if (size_needed
> (UINT_MAX
/SMB_POSIX_ACL_ENTRY_SIZE
)) {
5428 status
= NT_STATUS_INVALID_PARAMETER
;
5432 size_needed
= size_needed
*SMB_POSIX_ACL_ENTRY_SIZE
;
5433 if (size_needed
+ SMB_POSIX_ACL_HEADER_SIZE
< size_needed
) {
5434 status
= NT_STATUS_INVALID_PARAMETER
;
5437 size_needed
+= SMB_POSIX_ACL_HEADER_SIZE
;
5439 if (total_data
< size_needed
) {
5440 status
= NT_STATUS_INVALID_PARAMETER
;
5445 * Ensure we always operate on a file descriptor, not just
5448 if (fsp
== NULL
|| !fsp
->fsp_flags
.is_fsa
) {
5449 uint32_t access_mask
= SEC_STD_WRITE_OWNER
|
5451 SEC_STD_READ_CONTROL
|
5452 FILE_READ_ATTRIBUTES
|
5453 FILE_WRITE_ATTRIBUTES
;
5455 status
= get_posix_fsp(conn
,
5461 if (!NT_STATUS_IS_OK(status
)) {
5467 /* Here we know fsp != NULL */
5468 SMB_ASSERT(fsp
!= NULL
);
5470 status
= refuse_symlink_fsp(fsp
);
5471 if (!NT_STATUS_IS_OK(status
)) {
5475 /* If we have a default acl, this *must* be a directory. */
5476 if (valid_def_acls
&& !fsp
->fsp_flags
.is_directory
) {
5477 DBG_INFO("Can't set default acls on "
5478 "non-directory %s\n",
5480 return NT_STATUS_INVALID_HANDLE
;
5483 DBG_DEBUG("file %s num_file_acls = %"PRIu16
", "
5484 "num_def_acls = %"PRIu16
"\n",
5489 /* Move pdata to the start of the file ACL entries. */
5490 pdata
+= SMB_POSIX_ACL_HEADER_SIZE
;
5492 if (valid_file_acls
) {
5493 status
= set_unix_posix_acl(conn
,
5497 if (!NT_STATUS_IS_OK(status
)) {
5502 /* Move pdata to the start of the default ACL entries. */
5503 pdata
+= (num_file_acls
*SMB_POSIX_ACL_ENTRY_SIZE
);
5505 if (valid_def_acls
) {
5506 status
= set_unix_posix_default_acl(conn
,
5510 if (!NT_STATUS_IS_OK(status
)) {
5515 status
= NT_STATUS_OK
;
5520 (void)close_file_free(req
, &fsp
, NORMAL_CLOSE
);
5526 /****************************************************************************
5527 Deal with SMB_SET_FILE_BASIC_INFO.
5528 ****************************************************************************/
5530 static NTSTATUS
smb_set_file_basic_info(connection_struct
*conn
,
5534 struct smb_filename
*smb_fname
)
5536 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
5537 struct smb_file_time ft
;
5538 uint32_t dosmode
= 0;
5539 NTSTATUS status
= NT_STATUS_OK
;
5541 init_smb_file_time(&ft
);
5543 if (total_data
< 36) {
5544 return NT_STATUS_INVALID_PARAMETER
;
5548 return NT_STATUS_INVALID_HANDLE
;
5551 status
= check_access_fsp(fsp
, FILE_WRITE_ATTRIBUTES
);
5552 if (!NT_STATUS_IS_OK(status
)) {
5556 /* Set the attributes */
5557 dosmode
= IVAL(pdata
,32);
5558 status
= smb_set_file_dosmode(conn
, fsp
, dosmode
);
5559 if (!NT_STATUS_IS_OK(status
)) {
5564 ft
.create_time
= pull_long_date_full_timespec(pdata
);
5567 ft
.atime
= pull_long_date_full_timespec(pdata
+8);
5570 ft
.mtime
= pull_long_date_full_timespec(pdata
+16);
5573 ft
.ctime
= pull_long_date_full_timespec(pdata
+24);
5575 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
5576 smb_fname_str_dbg(smb_fname
)));
5578 status
= smb_set_file_time(conn
, fsp
, smb_fname
, &ft
, true);
5579 if (!NT_STATUS_IS_OK(status
)) {
5583 if (fsp
->fsp_flags
.modified
) {
5584 trigger_write_time_update_immediate(fsp
);
5586 return NT_STATUS_OK
;
5589 /****************************************************************************
5590 Deal with SMB_INFO_STANDARD.
5591 ****************************************************************************/
5593 static NTSTATUS
smb_set_info_standard(connection_struct
*conn
,
5597 struct smb_filename
*smb_fname
)
5600 struct smb_file_time ft
;
5602 init_smb_file_time(&ft
);
5604 if (total_data
< 12) {
5605 return NT_STATUS_INVALID_PARAMETER
;
5609 return NT_STATUS_INVALID_HANDLE
;
5613 ft
.create_time
= time_t_to_full_timespec(srv_make_unix_date2(pdata
));
5615 ft
.atime
= time_t_to_full_timespec(srv_make_unix_date2(pdata
+4));
5617 ft
.mtime
= time_t_to_full_timespec(srv_make_unix_date2(pdata
+8));
5619 DEBUG(10,("smb_set_info_standard: file %s\n",
5620 smb_fname_str_dbg(smb_fname
)));
5622 status
= check_access_fsp(fsp
, FILE_WRITE_ATTRIBUTES
);
5623 if (!NT_STATUS_IS_OK(status
)) {
5627 status
= smb_set_file_time(conn
, fsp
, smb_fname
, &ft
, true);
5628 if (!NT_STATUS_IS_OK(status
)) {
5632 if (fsp
->fsp_flags
.modified
) {
5633 trigger_write_time_update_immediate(fsp
);
5635 return NT_STATUS_OK
;
5638 /****************************************************************************
5639 Deal with SMB_SET_FILE_ALLOCATION_INFO.
5640 ****************************************************************************/
5642 static NTSTATUS
smb_set_file_allocation_info(connection_struct
*conn
,
5643 struct smb_request
*req
,
5647 struct smb_filename
*smb_fname
)
5649 uint64_t allocation_size
= 0;
5650 NTSTATUS status
= NT_STATUS_OK
;
5651 files_struct
*new_fsp
= NULL
;
5653 if (!VALID_STAT(smb_fname
->st
)) {
5654 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5657 if (total_data
< 8) {
5658 return NT_STATUS_INVALID_PARAMETER
;
5661 allocation_size
= (uint64_t)IVAL(pdata
,0);
5662 allocation_size
|= (((uint64_t)IVAL(pdata
,4)) << 32);
5663 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
5664 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname
),
5665 (double)allocation_size
));
5667 if (allocation_size
) {
5668 allocation_size
= smb_roundup(conn
, allocation_size
);
5671 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
5672 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname
),
5673 (double)allocation_size
));
5676 !fsp
->fsp_flags
.is_pathref
&&
5677 fsp_get_io_fd(fsp
) != -1)
5679 /* Open file handle. */
5680 if (!(fsp
->access_mask
& FILE_WRITE_DATA
)) {
5681 return NT_STATUS_ACCESS_DENIED
;
5684 /* Only change if needed. */
5685 if (allocation_size
!= get_file_size_stat(&smb_fname
->st
)) {
5686 if (vfs_allocate_file_space(fsp
, allocation_size
) == -1) {
5687 return map_nt_error_from_unix(errno
);
5690 /* But always update the time. */
5692 * This is equivalent to a write. Ensure it's seen immediately
5693 * if there are no pending writes.
5695 trigger_write_time_update_immediate(fsp
);
5696 return NT_STATUS_OK
;
5699 /* Pathname or stat or directory file. */
5700 status
= SMB_VFS_CREATE_FILE(
5704 smb_fname
, /* fname */
5705 FILE_WRITE_DATA
, /* access_mask */
5706 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
5708 FILE_OPEN
, /* create_disposition*/
5709 0, /* create_options */
5710 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
5711 0, /* oplock_request */
5713 0, /* allocation_size */
5714 0, /* private_flags */
5717 &new_fsp
, /* result */
5719 NULL
, NULL
); /* create context */
5721 if (!NT_STATUS_IS_OK(status
)) {
5722 /* NB. We check for open_was_deferred in the caller. */
5726 /* Only change if needed. */
5727 if (allocation_size
!= get_file_size_stat(&smb_fname
->st
)) {
5728 if (vfs_allocate_file_space(new_fsp
, allocation_size
) == -1) {
5729 status
= map_nt_error_from_unix(errno
);
5730 close_file_free(req
, &new_fsp
, NORMAL_CLOSE
);
5735 /* Changing the allocation size should set the last mod time. */
5737 * This is equivalent to a write. Ensure it's seen immediately
5738 * if there are no pending writes.
5740 trigger_write_time_update_immediate(new_fsp
);
5741 close_file_free(req
, &new_fsp
, NORMAL_CLOSE
);
5742 return NT_STATUS_OK
;
5745 /****************************************************************************
5746 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
5747 ****************************************************************************/
5749 static NTSTATUS
smb_set_file_end_of_file_info(connection_struct
*conn
,
5750 struct smb_request
*req
,
5754 struct smb_filename
*smb_fname
,
5755 bool fail_after_createfile
)
5759 if (total_data
< 8) {
5760 return NT_STATUS_INVALID_PARAMETER
;
5763 size
= IVAL(pdata
,0);
5764 size
|= (((off_t
)IVAL(pdata
,4)) << 32);
5765 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
5766 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname
),
5769 return smb_set_file_size(conn
, req
,
5774 fail_after_createfile
);
5777 /****************************************************************************
5778 Allow a UNIX info mknod.
5779 ****************************************************************************/
5781 static NTSTATUS
smb_unix_mknod(connection_struct
*conn
,
5784 const struct smb_filename
*smb_fname
)
5786 uint32_t file_type
= IVAL(pdata
,56);
5787 #if defined(HAVE_MAKEDEV)
5788 uint32_t dev_major
= IVAL(pdata
,60);
5789 uint32_t dev_minor
= IVAL(pdata
,68);
5791 SMB_DEV_T dev
= (SMB_DEV_T
)0;
5792 uint32_t raw_unixmode
= IVAL(pdata
,84);
5796 struct smb_filename
*parent_fname
= NULL
;
5797 struct smb_filename
*base_name
= NULL
;
5799 if (total_data
< 100) {
5800 return NT_STATUS_INVALID_PARAMETER
;
5803 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
5804 PERM_NEW_FILE
, &unixmode
);
5805 if (!NT_STATUS_IS_OK(status
)) {
5809 #if defined(HAVE_MAKEDEV)
5810 dev
= makedev(dev_major
, dev_minor
);
5813 switch (file_type
) {
5814 /* We can't create other objects here. */
5815 case UNIX_TYPE_FILE
:
5817 case UNIX_TYPE_SYMLINK
:
5818 return NT_STATUS_ACCESS_DENIED
;
5819 #if defined(S_IFIFO)
5820 case UNIX_TYPE_FIFO
:
5821 unixmode
|= S_IFIFO
;
5824 #if defined(S_IFSOCK)
5825 case UNIX_TYPE_SOCKET
:
5826 unixmode
|= S_IFSOCK
;
5829 #if defined(S_IFCHR)
5830 case UNIX_TYPE_CHARDEV
:
5831 /* This is only allowed for root. */
5832 if (get_current_uid(conn
) != sec_initial_uid()) {
5833 return NT_STATUS_ACCESS_DENIED
;
5835 unixmode
|= S_IFCHR
;
5838 #if defined(S_IFBLK)
5839 case UNIX_TYPE_BLKDEV
:
5840 if (get_current_uid(conn
) != sec_initial_uid()) {
5841 return NT_STATUS_ACCESS_DENIED
;
5843 unixmode
|= S_IFBLK
;
5847 return NT_STATUS_INVALID_PARAMETER
;
5850 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
5851 "%.0f mode 0%o for file %s\n", (double)dev
,
5852 (unsigned int)unixmode
, smb_fname_str_dbg(smb_fname
)));
5854 status
= parent_pathref(talloc_tos(),
5859 if (!NT_STATUS_IS_OK(status
)) {
5863 /* Ok - do the mknod. */
5864 ret
= SMB_VFS_MKNODAT(conn
,
5871 TALLOC_FREE(parent_fname
);
5872 return map_nt_error_from_unix(errno
);
5875 /* If any of the other "set" calls fail we
5876 * don't want to end up with a half-constructed mknod.
5879 if (lp_inherit_permissions(SNUM(conn
))) {
5880 inherit_access_posix_acl(conn
,
5885 TALLOC_FREE(parent_fname
);
5887 return NT_STATUS_OK
;
5890 /****************************************************************************
5891 Deal with SMB_SET_FILE_UNIX_BASIC.
5892 ****************************************************************************/
5894 static NTSTATUS
smb_set_file_unix_basic(connection_struct
*conn
,
5895 struct smb_request
*req
,
5899 struct smb_filename
*smb_fname
)
5901 struct smb_file_time ft
;
5902 uint32_t raw_unixmode
;
5905 uid_t set_owner
= (uid_t
)SMB_UID_NO_CHANGE
;
5906 gid_t set_grp
= (uid_t
)SMB_GID_NO_CHANGE
;
5907 NTSTATUS status
= NT_STATUS_OK
;
5908 enum perm_type ptype
;
5909 files_struct
*all_fsps
= NULL
;
5910 bool modify_mtime
= true;
5912 SMB_STRUCT_STAT sbuf
;
5914 init_smb_file_time(&ft
);
5916 if (total_data
< 100) {
5917 return NT_STATUS_INVALID_PARAMETER
;
5920 if(IVAL(pdata
, 0) != SMB_SIZE_NO_CHANGE_LO
&&
5921 IVAL(pdata
, 4) != SMB_SIZE_NO_CHANGE_HI
) {
5922 size
=IVAL(pdata
,0); /* first 8 Bytes are size */
5923 size
|= (((off_t
)IVAL(pdata
,4)) << 32);
5926 ft
.atime
= pull_long_date_full_timespec(pdata
+24); /* access_time */
5927 ft
.mtime
= pull_long_date_full_timespec(pdata
+32); /* modification_time */
5928 set_owner
= (uid_t
)IVAL(pdata
,40);
5929 set_grp
= (gid_t
)IVAL(pdata
,48);
5930 raw_unixmode
= IVAL(pdata
,84);
5932 if (VALID_STAT(smb_fname
->st
)) {
5933 if (S_ISDIR(smb_fname
->st
.st_ex_mode
)) {
5934 ptype
= PERM_EXISTING_DIR
;
5936 ptype
= PERM_EXISTING_FILE
;
5939 ptype
= PERM_NEW_FILE
;
5942 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
5944 if (!NT_STATUS_IS_OK(status
)) {
5948 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
5949 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
5950 smb_fname_str_dbg(smb_fname
), (double)size
,
5951 (unsigned int)set_owner
, (unsigned int)set_grp
,
5952 (int)raw_unixmode
));
5954 sbuf
= smb_fname
->st
;
5956 if (!VALID_STAT(sbuf
)) {
5958 * The only valid use of this is to create character and block
5959 * devices, and named pipes. This is deprecated (IMHO) and
5960 * a new info level should be used for mknod. JRA.
5963 return smb_unix_mknod(conn
,
5970 /* Horrible backwards compatibility hack as an old server bug
5971 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
5975 size
= get_file_size_stat(&sbuf
);
5980 * Deal with the UNIX specific mode set.
5983 if (raw_unixmode
!= SMB_MODE_NO_CHANGE
) {
5986 if (fsp
== NULL
|| S_ISLNK(smb_fname
->st
.st_ex_mode
)) {
5987 DBG_WARNING("Can't set mode on symlink %s\n",
5988 smb_fname_str_dbg(smb_fname
));
5989 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5992 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
5993 "setting mode 0%o for file %s\n",
5994 (unsigned int)unixmode
,
5995 smb_fname_str_dbg(smb_fname
)));
5996 ret
= SMB_VFS_FCHMOD(fsp
, unixmode
);
5998 return map_nt_error_from_unix(errno
);
6003 * Deal with the UNIX specific uid set.
6006 if ((set_owner
!= (uid_t
)SMB_UID_NO_CHANGE
) &&
6007 (sbuf
.st_ex_uid
!= set_owner
)) {
6010 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6011 "changing owner %u for path %s\n",
6012 (unsigned int)set_owner
,
6013 smb_fname_str_dbg(smb_fname
)));
6016 !fsp
->fsp_flags
.is_pathref
&&
6017 fsp_get_io_fd(fsp
) != -1)
6019 ret
= SMB_VFS_FCHOWN(fsp
, set_owner
, (gid_t
)-1);
6022 * UNIX extensions calls must always operate
6025 ret
= SMB_VFS_LCHOWN(conn
, smb_fname
,
6026 set_owner
, (gid_t
)-1);
6030 status
= map_nt_error_from_unix(errno
);
6036 * Deal with the UNIX specific gid set.
6039 if ((set_grp
!= (uid_t
)SMB_GID_NO_CHANGE
) &&
6040 (sbuf
.st_ex_gid
!= set_grp
)) {
6043 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6044 "changing group %u for file %s\n",
6045 (unsigned int)set_grp
,
6046 smb_fname_str_dbg(smb_fname
)));
6048 !fsp
->fsp_flags
.is_pathref
&&
6049 fsp_get_io_fd(fsp
) != -1)
6051 ret
= SMB_VFS_FCHOWN(fsp
, (uid_t
)-1, set_grp
);
6054 * UNIX extensions calls must always operate
6057 ret
= SMB_VFS_LCHOWN(conn
, smb_fname
, (uid_t
)-1,
6061 status
= map_nt_error_from_unix(errno
);
6066 /* Deal with any size changes. */
6068 if (S_ISREG(sbuf
.st_ex_mode
)) {
6069 status
= smb_set_file_size(conn
, req
,
6075 if (!NT_STATUS_IS_OK(status
)) {
6080 /* Deal with any time changes. */
6081 if (is_omit_timespec(&ft
.mtime
) && is_omit_timespec(&ft
.atime
)) {
6082 /* No change, don't cancel anything. */
6086 id
= vfs_file_id_from_sbuf(conn
, &sbuf
);
6087 for(all_fsps
= file_find_di_first(conn
->sconn
, id
, true); all_fsps
;
6088 all_fsps
= file_find_di_next(all_fsps
, true)) {
6090 * We're setting the time explicitly for UNIX.
6091 * Cancel any pending changes over all handles.
6093 all_fsps
->fsp_flags
.update_write_time_on_close
= false;
6094 TALLOC_FREE(all_fsps
->update_write_time_event
);
6098 * Override the "setting_write_time"
6099 * parameter here as it almost does what
6100 * we need. Just remember if we modified
6101 * mtime and send the notify ourselves.
6103 if (is_omit_timespec(&ft
.mtime
)) {
6104 modify_mtime
= false;
6107 status
= smb_set_file_time(conn
,
6113 notify_fname(conn
, NOTIFY_ACTION_MODIFIED
,
6114 FILE_NOTIFY_CHANGE_LAST_WRITE
, smb_fname
->base_name
);
6119 /****************************************************************************
6120 Deal with SMB_SET_FILE_UNIX_INFO2.
6121 ****************************************************************************/
6123 static NTSTATUS
smb_set_file_unix_info2(connection_struct
*conn
,
6124 struct smb_request
*req
,
6128 struct smb_filename
*smb_fname
)
6131 uint32_t smb_fflags
;
6134 if (total_data
< 116) {
6135 return NT_STATUS_INVALID_PARAMETER
;
6138 /* Start by setting all the fields that are common between UNIX_BASIC
6141 status
= smb_set_file_unix_basic(conn
, req
, pdata
, total_data
,
6143 if (!NT_STATUS_IS_OK(status
)) {
6147 smb_fflags
= IVAL(pdata
, 108);
6148 smb_fmask
= IVAL(pdata
, 112);
6150 /* NB: We should only attempt to alter the file flags if the client
6151 * sends a non-zero mask.
6153 if (smb_fmask
!= 0) {
6154 int stat_fflags
= 0;
6156 if (!map_info2_flags_to_sbuf(&smb_fname
->st
, smb_fflags
,
6157 smb_fmask
, &stat_fflags
)) {
6158 /* Client asked to alter a flag we don't understand. */
6159 return NT_STATUS_INVALID_PARAMETER
;
6162 if (fsp
== NULL
|| S_ISLNK(smb_fname
->st
.st_ex_mode
)) {
6163 DBG_WARNING("Can't change flags on symlink %s\n",
6164 smb_fname_str_dbg(smb_fname
));
6165 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
6167 if (SMB_VFS_FCHFLAGS(fsp
, stat_fflags
) != 0) {
6168 return map_nt_error_from_unix(errno
);
6172 /* XXX: need to add support for changing the create_time here. You
6173 * can do this for paths on Darwin with setattrlist(2). The right way
6174 * to hook this up is probably by extending the VFS utimes interface.
6177 return NT_STATUS_OK
;
6180 /****************************************************************************
6181 Create a directory with POSIX semantics.
6182 ****************************************************************************/
6184 static NTSTATUS
smb_posix_mkdir(connection_struct
*conn
,
6185 struct smb_request
*req
,
6188 struct smb_filename
*smb_fname
,
6189 int *pdata_return_size
)
6191 NTSTATUS status
= NT_STATUS_OK
;
6192 uint32_t raw_unixmode
= 0;
6193 mode_t unixmode
= (mode_t
)0;
6194 files_struct
*fsp
= NULL
;
6195 uint16_t info_level_return
= 0;
6197 char *pdata
= *ppdata
;
6198 struct smb2_create_blobs
*posx
= NULL
;
6200 if (total_data
< 18) {
6201 return NT_STATUS_INVALID_PARAMETER
;
6204 raw_unixmode
= IVAL(pdata
,8);
6205 /* Next 4 bytes are not yet defined. */
6207 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
6208 PERM_NEW_DIR
, &unixmode
);
6209 if (!NT_STATUS_IS_OK(status
)) {
6213 status
= make_smb2_posix_create_ctx(talloc_tos(), &posx
, unixmode
);
6214 if (!NT_STATUS_IS_OK(status
)) {
6215 DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
6220 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
6221 smb_fname_str_dbg(smb_fname
), (unsigned int)unixmode
));
6223 status
= SMB_VFS_CREATE_FILE(
6227 smb_fname
, /* fname */
6228 FILE_READ_ATTRIBUTES
, /* access_mask */
6229 FILE_SHARE_NONE
, /* share_access */
6230 FILE_CREATE
, /* create_disposition*/
6231 FILE_DIRECTORY_FILE
, /* create_options */
6232 0, /* file_attributes */
6233 0, /* oplock_request */
6235 0, /* allocation_size */
6236 0, /* private_flags */
6241 posx
, /* in_context_blobs */
6242 NULL
); /* out_context_blobs */
6246 if (NT_STATUS_IS_OK(status
)) {
6247 close_file_free(req
, &fsp
, NORMAL_CLOSE
);
6250 info_level_return
= SVAL(pdata
,16);
6252 if (info_level_return
== SMB_QUERY_FILE_UNIX_BASIC
) {
6253 *pdata_return_size
= 12 + SMB_FILE_UNIX_BASIC_SIZE
;
6254 } else if (info_level_return
== SMB_QUERY_FILE_UNIX_INFO2
) {
6255 *pdata_return_size
= 12 + SMB_FILE_UNIX_INFO2_SIZE
;
6257 *pdata_return_size
= 12;
6260 /* Realloc the data size */
6261 *ppdata
= (char *)SMB_REALLOC(*ppdata
,*pdata_return_size
);
6262 if (*ppdata
== NULL
) {
6263 *pdata_return_size
= 0;
6264 return NT_STATUS_NO_MEMORY
;
6268 SSVAL(pdata
,0,NO_OPLOCK_RETURN
);
6269 SSVAL(pdata
,2,0); /* No fnum. */
6270 SIVAL(pdata
,4,info
); /* Was directory created. */
6272 switch (info_level_return
) {
6273 case SMB_QUERY_FILE_UNIX_BASIC
:
6274 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_BASIC
);
6275 SSVAL(pdata
,10,0); /* Padding. */
6276 store_file_unix_basic(conn
, pdata
+ 12, fsp
,
6279 case SMB_QUERY_FILE_UNIX_INFO2
:
6280 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_INFO2
);
6281 SSVAL(pdata
,10,0); /* Padding. */
6282 store_file_unix_basic_info2(conn
, pdata
+ 12, fsp
,
6286 SSVAL(pdata
,8,SMB_NO_INFO_LEVEL_RETURNED
);
6287 SSVAL(pdata
,10,0); /* Padding. */
6294 /****************************************************************************
6295 Open/Create a file with POSIX semantics.
6296 ****************************************************************************/
6298 #define SMB_O_RDONLY_MAPPING (FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA)
6299 #define SMB_O_WRONLY_MAPPING (FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA)
6301 static NTSTATUS
smb_posix_open(connection_struct
*conn
,
6302 struct smb_request
*req
,
6305 struct smb_filename
*smb_fname
,
6306 int *pdata_return_size
)
6308 bool extended_oplock_granted
= False
;
6309 char *pdata
= *ppdata
;
6311 uint32_t wire_open_mode
= 0;
6312 uint32_t raw_unixmode
= 0;
6313 uint32_t attributes
= 0;
6314 uint32_t create_disp
= 0;
6315 uint32_t access_mask
= 0;
6316 uint32_t create_options
= FILE_NON_DIRECTORY_FILE
;
6317 NTSTATUS status
= NT_STATUS_OK
;
6318 mode_t unixmode
= (mode_t
)0;
6319 files_struct
*fsp
= NULL
;
6320 int oplock_request
= 0;
6322 uint16_t info_level_return
= 0;
6323 struct smb2_create_blobs
*posx
= NULL
;
6325 if (total_data
< 18) {
6326 return NT_STATUS_INVALID_PARAMETER
;
6329 flags
= IVAL(pdata
,0);
6330 oplock_request
= (flags
& REQUEST_OPLOCK
) ? EXCLUSIVE_OPLOCK
: 0;
6331 if (oplock_request
) {
6332 oplock_request
|= (flags
& REQUEST_BATCH_OPLOCK
) ? BATCH_OPLOCK
: 0;
6335 wire_open_mode
= IVAL(pdata
,4);
6337 if (wire_open_mode
== (SMB_O_CREAT
|SMB_O_DIRECTORY
)) {
6338 return smb_posix_mkdir(conn
, req
,
6345 switch (wire_open_mode
& SMB_ACCMODE
) {
6347 access_mask
= SMB_O_RDONLY_MAPPING
;
6350 access_mask
= SMB_O_WRONLY_MAPPING
;
6353 access_mask
= (SMB_O_RDONLY_MAPPING
|
6354 SMB_O_WRONLY_MAPPING
);
6357 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
6358 (unsigned int)wire_open_mode
));
6359 return NT_STATUS_INVALID_PARAMETER
;
6362 wire_open_mode
&= ~SMB_ACCMODE
;
6364 /* First take care of O_CREAT|O_EXCL interactions. */
6365 switch (wire_open_mode
& (SMB_O_CREAT
| SMB_O_EXCL
)) {
6366 case (SMB_O_CREAT
| SMB_O_EXCL
):
6367 /* File exists fail. File not exist create. */
6368 create_disp
= FILE_CREATE
;
6371 /* File exists open. File not exist create. */
6372 create_disp
= FILE_OPEN_IF
;
6375 /* O_EXCL on its own without O_CREAT is undefined.
6376 We deliberately ignore it as some versions of
6377 Linux CIFSFS can send a bare O_EXCL on the
6378 wire which other filesystems in the kernel
6379 ignore. See bug 9519 for details. */
6384 /* File exists open. File not exist fail. */
6385 create_disp
= FILE_OPEN
;
6388 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
6389 (unsigned int)wire_open_mode
));
6390 return NT_STATUS_INVALID_PARAMETER
;
6393 /* Next factor in the effects of O_TRUNC. */
6394 wire_open_mode
&= ~(SMB_O_CREAT
| SMB_O_EXCL
);
6396 if (wire_open_mode
& SMB_O_TRUNC
) {
6397 switch (create_disp
) {
6399 /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
6400 /* Leave create_disp alone as
6401 (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
6403 /* File exists fail. File not exist create. */
6406 /* SMB_O_CREAT | SMB_O_TRUNC */
6407 /* File exists overwrite. File not exist create. */
6408 create_disp
= FILE_OVERWRITE_IF
;
6412 /* File exists overwrite. File not exist fail. */
6413 create_disp
= FILE_OVERWRITE
;
6416 /* Cannot get here. */
6417 smb_panic("smb_posix_open: logic error");
6418 return NT_STATUS_INVALID_PARAMETER
;
6422 raw_unixmode
= IVAL(pdata
,8);
6423 /* Next 4 bytes are not yet defined. */
6425 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
6426 (VALID_STAT(smb_fname
->st
) ?
6427 PERM_EXISTING_FILE
: PERM_NEW_FILE
),
6430 if (!NT_STATUS_IS_OK(status
)) {
6434 status
= make_smb2_posix_create_ctx(talloc_tos(), &posx
, unixmode
);
6435 if (!NT_STATUS_IS_OK(status
)) {
6436 DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
6441 if (wire_open_mode
& SMB_O_SYNC
) {
6442 create_options
|= FILE_WRITE_THROUGH
;
6444 if (wire_open_mode
& SMB_O_APPEND
) {
6445 access_mask
|= FILE_APPEND_DATA
;
6447 if (wire_open_mode
& SMB_O_DIRECT
) {
6448 attributes
|= FILE_FLAG_NO_BUFFERING
;
6451 if ((wire_open_mode
& SMB_O_DIRECTORY
) ||
6452 VALID_STAT_OF_DIR(smb_fname
->st
)) {
6453 if (access_mask
!= SMB_O_RDONLY_MAPPING
) {
6454 return NT_STATUS_FILE_IS_A_DIRECTORY
;
6456 create_options
&= ~FILE_NON_DIRECTORY_FILE
;
6457 create_options
|= FILE_DIRECTORY_FILE
;
6460 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
6461 smb_fname_str_dbg(smb_fname
),
6462 (unsigned int)wire_open_mode
,
6463 (unsigned int)unixmode
));
6465 status
= SMB_VFS_CREATE_FILE(
6469 smb_fname
, /* fname */
6470 access_mask
, /* access_mask */
6471 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
6473 create_disp
, /* create_disposition*/
6474 create_options
, /* create_options */
6475 attributes
, /* file_attributes */
6476 oplock_request
, /* oplock_request */
6478 0, /* allocation_size */
6479 0, /* private_flags */
6484 posx
, /* in_context_blobs */
6485 NULL
); /* out_context_blobs */
6489 if (!NT_STATUS_IS_OK(status
)) {
6493 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
6494 extended_oplock_granted
= True
;
6497 if(oplock_request
&& EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
6498 extended_oplock_granted
= True
;
6501 info_level_return
= SVAL(pdata
,16);
6503 /* Allocate the correct return size. */
6505 if (info_level_return
== SMB_QUERY_FILE_UNIX_BASIC
) {
6506 *pdata_return_size
= 12 + SMB_FILE_UNIX_BASIC_SIZE
;
6507 } else if (info_level_return
== SMB_QUERY_FILE_UNIX_INFO2
) {
6508 *pdata_return_size
= 12 + SMB_FILE_UNIX_INFO2_SIZE
;
6510 *pdata_return_size
= 12;
6513 /* Realloc the data size */
6514 *ppdata
= (char *)SMB_REALLOC(*ppdata
,*pdata_return_size
);
6515 if (*ppdata
== NULL
) {
6516 close_file_free(req
, &fsp
, ERROR_CLOSE
);
6517 *pdata_return_size
= 0;
6518 return NT_STATUS_NO_MEMORY
;
6522 if (extended_oplock_granted
) {
6523 if (flags
& REQUEST_BATCH_OPLOCK
) {
6524 SSVAL(pdata
,0, BATCH_OPLOCK_RETURN
);
6526 SSVAL(pdata
,0, EXCLUSIVE_OPLOCK_RETURN
);
6528 } else if (fsp
->oplock_type
== LEVEL_II_OPLOCK
) {
6529 SSVAL(pdata
,0, LEVEL_II_OPLOCK_RETURN
);
6531 SSVAL(pdata
,0,NO_OPLOCK_RETURN
);
6534 SSVAL(pdata
,2,fsp
->fnum
);
6535 SIVAL(pdata
,4,info
); /* Was file created etc. */
6537 switch (info_level_return
) {
6538 case SMB_QUERY_FILE_UNIX_BASIC
:
6539 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_BASIC
);
6540 SSVAL(pdata
,10,0); /* padding. */
6541 store_file_unix_basic(conn
, pdata
+ 12, fsp
,
6544 case SMB_QUERY_FILE_UNIX_INFO2
:
6545 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_INFO2
);
6546 SSVAL(pdata
,10,0); /* padding. */
6547 store_file_unix_basic_info2(conn
, pdata
+ 12, fsp
,
6551 SSVAL(pdata
,8,SMB_NO_INFO_LEVEL_RETURNED
);
6552 SSVAL(pdata
,10,0); /* padding. */
6555 return NT_STATUS_OK
;
6558 /****************************************************************************
6559 Delete a file with POSIX semantics.
6560 ****************************************************************************/
6562 struct smb_posix_unlink_state
{
6563 struct smb_filename
*smb_fname
;
6564 struct files_struct
*fsp
;
6568 static void smb_posix_unlink_locked(struct share_mode_lock
*lck
,
6571 struct smb_posix_unlink_state
*state
= private_data
;
6573 bool other_nonposix_opens
;
6575 other_nonposix_opens
= has_other_nonposix_opens(lck
, state
->fsp
);
6576 if (other_nonposix_opens
) {
6577 /* Fail with sharing violation. */
6578 state
->status
= NT_STATUS_SHARING_VIOLATION
;
6583 * Set the delete on close.
6585 state
->status
= smb_set_file_disposition_info(state
->fsp
->conn
,
6592 static NTSTATUS
smb_posix_unlink(connection_struct
*conn
,
6593 struct smb_request
*req
,
6596 struct smb_filename
*smb_fname
)
6598 struct smb_posix_unlink_state state
= {};
6599 NTSTATUS status
= NT_STATUS_OK
;
6600 files_struct
*fsp
= NULL
;
6603 int create_options
= 0;
6604 struct smb2_create_blobs
*posx
= NULL
;
6606 if (total_data
< 2) {
6607 return NT_STATUS_INVALID_PARAMETER
;
6610 flags
= SVAL(pdata
,0);
6612 if (!VALID_STAT(smb_fname
->st
)) {
6613 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
6616 if ((flags
== SMB_POSIX_UNLINK_DIRECTORY_TARGET
) &&
6617 !VALID_STAT_OF_DIR(smb_fname
->st
)) {
6618 return NT_STATUS_NOT_A_DIRECTORY
;
6621 DEBUG(10,("smb_posix_unlink: %s %s\n",
6622 (flags
== SMB_POSIX_UNLINK_DIRECTORY_TARGET
) ? "directory" : "file",
6623 smb_fname_str_dbg(smb_fname
)));
6625 if (VALID_STAT_OF_DIR(smb_fname
->st
)) {
6626 create_options
|= FILE_DIRECTORY_FILE
;
6629 status
= make_smb2_posix_create_ctx(talloc_tos(), &posx
, 0777);
6630 if (!NT_STATUS_IS_OK(status
)) {
6631 DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
6636 status
= SMB_VFS_CREATE_FILE(
6640 smb_fname
, /* fname */
6641 DELETE_ACCESS
, /* access_mask */
6642 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
6644 FILE_OPEN
, /* create_disposition*/
6645 create_options
, /* create_options */
6646 0, /* file_attributes */
6647 0, /* oplock_request */
6649 0, /* allocation_size */
6650 0, /* private_flags */
6655 posx
, /* in_context_blobs */
6656 NULL
); /* out_context_blobs */
6660 if (!NT_STATUS_IS_OK(status
)) {
6665 * Don't lie to client. If we can't really delete due to
6666 * non-POSIX opens return SHARING_VIOLATION.
6669 state
= (struct smb_posix_unlink_state
) {
6670 .smb_fname
= smb_fname
,
6674 status
= share_mode_do_locked_vfs_allowed(fsp
->file_id
,
6675 smb_posix_unlink_locked
,
6677 if (!NT_STATUS_IS_OK(status
)) {
6678 DBG_ERR("share_mode_do_locked_vfs_allowed(%s) failed - %s\n",
6679 fsp_str_dbg(fsp
), nt_errstr(status
));
6680 close_file_free(req
, &fsp
, NORMAL_CLOSE
);
6681 return NT_STATUS_INVALID_PARAMETER
;
6684 status
= state
.status
;
6685 if (!NT_STATUS_IS_OK(status
)) {
6686 close_file_free(req
, &fsp
, NORMAL_CLOSE
);
6689 return close_file_free(req
, &fsp
, NORMAL_CLOSE
);
6692 static NTSTATUS
smbd_do_posix_setfilepathinfo(struct connection_struct
*conn
,
6693 struct smb_request
*req
,
6694 TALLOC_CTX
*mem_ctx
,
6695 uint16_t info_level
,
6696 struct smb_filename
*smb_fname
,
6702 char *pdata
= *ppdata
;
6703 NTSTATUS status
= NT_STATUS_OK
;
6704 int data_return_size
= 0;
6708 if (!CAN_WRITE(conn
)) {
6709 /* Allow POSIX opens. The open path will deny
6710 * any non-readonly opens. */
6711 if (info_level
!= SMB_POSIX_PATH_OPEN
) {
6712 return NT_STATUS_DOS(ERRSRV
, ERRaccess
);
6716 DBG_DEBUG("file=%s (%s) info_level=%d totdata=%d\n",
6717 smb_fname_str_dbg(smb_fname
),
6722 switch (info_level
) {
6723 case SMB_SET_FILE_UNIX_BASIC
:
6725 status
= smb_set_file_unix_basic(conn
, req
,
6733 case SMB_SET_FILE_UNIX_INFO2
:
6735 status
= smb_set_file_unix_info2(conn
, req
,
6743 case SMB_SET_FILE_UNIX_LINK
:
6745 if (smb_fname
== NULL
) {
6746 /* We must have a pathname for this. */
6747 return NT_STATUS_INVALID_LEVEL
;
6749 status
= smb_set_file_unix_link(conn
, req
, pdata
,
6750 total_data
, smb_fname
);
6754 case SMB_SET_FILE_UNIX_HLINK
:
6756 if (smb_fname
== NULL
) {
6757 /* We must have a pathname for this. */
6758 return NT_STATUS_INVALID_LEVEL
;
6760 status
= smb_set_file_unix_hlink(conn
, req
,
6766 #if defined(HAVE_POSIX_ACLS)
6767 case SMB_SET_POSIX_ACL
:
6769 status
= smb_set_posix_acl(conn
,
6779 #if defined(WITH_SMB1SERVER)
6780 case SMB_SET_POSIX_LOCK
:
6783 return NT_STATUS_INVALID_LEVEL
;
6785 status
= smb_set_posix_lock(conn
, req
,
6786 pdata
, total_data
, fsp
);
6791 case SMB_POSIX_PATH_OPEN
:
6793 if (smb_fname
== NULL
) {
6794 /* We must have a pathname for this. */
6795 return NT_STATUS_INVALID_LEVEL
;
6798 status
= smb_posix_open(conn
, req
,
6806 case SMB_POSIX_PATH_UNLINK
:
6808 if (smb_fname
== NULL
) {
6809 /* We must have a pathname for this. */
6810 return NT_STATUS_INVALID_LEVEL
;
6813 status
= smb_posix_unlink(conn
, req
,
6821 return NT_STATUS_INVALID_LEVEL
;
6824 if (!NT_STATUS_IS_OK(status
)) {
6828 *ret_data_size
= data_return_size
;
6829 return NT_STATUS_OK
;
6832 NTSTATUS
smbd_do_setfilepathinfo(connection_struct
*conn
,
6833 struct smb_request
*req
,
6834 TALLOC_CTX
*mem_ctx
,
6835 uint16_t info_level
,
6837 struct smb_filename
*smb_fname
,
6838 char **ppdata
, int total_data
,
6841 char *pdata
= *ppdata
;
6842 NTSTATUS status
= NT_STATUS_OK
;
6843 int data_return_size
= 0;
6845 if (INFO_LEVEL_IS_UNIX(info_level
)) {
6846 if (!lp_smb1_unix_extensions()) {
6847 return NT_STATUS_INVALID_LEVEL
;
6849 if (!req
->posix_pathnames
) {
6850 return NT_STATUS_INVALID_LEVEL
;
6852 status
= smbd_do_posix_setfilepathinfo(conn
,
6861 if (!NT_STATUS_IS_OK(status
)) {
6864 *ret_data_size
= data_return_size
;
6865 return NT_STATUS_OK
;
6870 DEBUG(3,("smbd_do_setfilepathinfo: %s (%s) info_level=%d "
6871 "totdata=%d\n", smb_fname_str_dbg(smb_fname
),
6873 info_level
, total_data
));
6875 switch (info_level
) {
6877 case SMB_INFO_STANDARD
:
6879 status
= smb_set_info_standard(conn
,
6887 case SMB_INFO_SET_EA
:
6889 status
= smb_info_set_ea(conn
,
6897 case SMB_SET_FILE_BASIC_INFO
:
6898 case SMB_FILE_BASIC_INFORMATION
:
6900 status
= smb_set_file_basic_info(conn
,
6908 case SMB_FILE_ALLOCATION_INFORMATION
:
6909 case SMB_SET_FILE_ALLOCATION_INFO
:
6911 status
= smb_set_file_allocation_info(conn
, req
,
6919 case SMB_FILE_END_OF_FILE_INFORMATION
:
6920 case SMB_SET_FILE_END_OF_FILE_INFO
:
6923 * XP/Win7 both fail after the createfile with
6924 * SMB_SET_FILE_END_OF_FILE_INFO but not
6925 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
6926 * The level is known here, so pass it down
6930 (info_level
== SMB_SET_FILE_END_OF_FILE_INFO
);
6932 status
= smb_set_file_end_of_file_info(conn
, req
,
6941 case SMB_FILE_DISPOSITION_INFORMATION
:
6942 case SMB_SET_FILE_DISPOSITION_INFO
: /* Set delete on close for open file. */
6945 /* JRA - We used to just ignore this on a path ?
6946 * Shouldn't this be invalid level on a pathname
6949 if (tran_call
!= TRANSACT2_SETFILEINFO
) {
6950 return ERROR_NT(NT_STATUS_INVALID_LEVEL
);
6953 status
= smb_set_file_disposition_info(conn
,
6961 case SMB_FILE_POSITION_INFORMATION
:
6963 status
= smb_file_position_information(conn
,
6970 case SMB_FILE_FULL_EA_INFORMATION
:
6972 status
= smb_set_file_full_ea_info(conn
,
6979 /* From tridge Samba4 :
6980 * MODE_INFORMATION in setfileinfo (I have no
6981 * idea what "mode information" on a file is - it takes a value of 0,
6982 * 2, 4 or 6. What could it be?).
6985 case SMB_FILE_MODE_INFORMATION
:
6987 status
= smb_file_mode_information(conn
,
6993 /* [MS-SMB2] 3.3.5.21.1 states we MUST fail with STATUS_NOT_SUPPORTED. */
6994 case SMB_FILE_VALID_DATA_LENGTH_INFORMATION
:
6995 case SMB_FILE_SHORT_NAME_INFORMATION
:
6996 return NT_STATUS_NOT_SUPPORTED
;
6998 case SMB_FILE_RENAME_INFORMATION
:
7000 status
= smb_file_rename_information(conn
, req
,
7006 case SMB2_FILE_RENAME_INFORMATION_INTERNAL
:
7008 /* SMB2 rename information. */
7009 status
= smb2_file_rename_information(conn
, req
,
7015 case SMB_FILE_LINK_INFORMATION
:
7017 status
= smb_file_link_information(conn
, req
,
7024 return NT_STATUS_INVALID_LEVEL
;
7027 if (!NT_STATUS_IS_OK(status
)) {
7031 *ret_data_size
= data_return_size
;
7032 return NT_STATUS_OK
;
7035 static uint32_t generate_volume_serial_number(
7036 const struct loadparm_substitution
*lp_sub
,
7039 int serial
= lp_volume_serial_number(snum
);
7040 return serial
!= -1 ? serial
:
7041 str_checksum(lp_servicename(talloc_tos(), lp_sub
, snum
)) ^
7042 (str_checksum(get_local_machine_name())<<16);