2 Unix SMB/CIFS implementation.
3 SMB transaction2 handling
4 Copyright (C) Jeremy Allison 1994-2007
5 Copyright (C) Stefan (metze) Metzmacher 2003
6 Copyright (C) Volker Lendecke 2005-2007
7 Copyright (C) Steve French 2005
8 Copyright (C) James Peach 2006-2007
10 Extensively modified by Andrew Tridgell, 1995
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 3 of the License, or
15 (at your option) any later version.
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with this program. If not, see <http://www.gnu.org/licenses/>.
28 #include "system/filesys.h"
29 #include "lib/util/time_basic.h"
31 #include "smbd/smbd.h"
32 #include "smbd/globals.h"
33 #include "../libcli/auth/libcli_auth.h"
34 #include "../librpc/gen_ndr/xattr.h"
35 #include "../librpc/gen_ndr/ndr_security.h"
36 #include "libcli/security/security.h"
39 #include "smbprofile.h"
40 #include "rpc_server/srv_pipe_hnd.h"
42 #include "lib/util_ea.h"
43 #include "lib/readdir_attr.h"
45 #include "libcli/smb/smb2_posix.h"
46 #include "lib/util/string_wrappers.h"
47 #include "source3/lib/substitute.h"
48 #include "source3/lib/adouble.h"
50 #define DIR_ENTRY_SAFETY_MARGIN 4096
52 static uint32_t generate_volume_serial_number(
53 const struct loadparm_substitution
*lp_sub
,
56 /****************************************************************************
57 Check if an open file handle is a symlink.
58 ****************************************************************************/
60 NTSTATUS
refuse_symlink_fsp(const files_struct
*fsp
)
63 if (!VALID_STAT(fsp
->fsp_name
->st
)) {
64 return NT_STATUS_ACCESS_DENIED
;
66 if (S_ISLNK(fsp
->fsp_name
->st
.st_ex_mode
)) {
67 return NT_STATUS_ACCESS_DENIED
;
69 if (fsp_get_pathref_fd(fsp
) == -1) {
70 return NT_STATUS_ACCESS_DENIED
;
75 NTSTATUS
check_access_fsp(struct files_struct
*fsp
,
78 if (!fsp
->fsp_flags
.is_fsa
) {
79 return smbd_check_access_rights_fsp(fsp
->conn
->cwd_fsp
,
84 if (!(fsp
->access_mask
& access_mask
)) {
85 return NT_STATUS_ACCESS_DENIED
;
90 #if defined(HAVE_POSIX_ACLS)
91 /****************************************************************************
92 Utility function to open a fsp for a POSIX handle operation.
93 ****************************************************************************/
95 static NTSTATUS
get_posix_fsp(connection_struct
*conn
,
96 struct smb_request
*req
,
97 struct smb_filename
*smb_fname
,
99 files_struct
**ret_fsp
)
102 uint32_t create_disposition
= FILE_OPEN
;
103 uint32_t share_access
= FILE_SHARE_READ
|
106 struct smb2_create_blobs
*posx
= NULL
;
109 * Only FILE_FLAG_POSIX_SEMANTICS matters on existing files,
110 * but set reasonable defaults.
112 uint32_t file_attributes
= 0664;
113 uint32_t oplock
= NO_OPLOCK
;
114 uint32_t create_options
= FILE_NON_DIRECTORY_FILE
;
116 /* File or directory must exist. */
117 if (!VALID_STAT(smb_fname
->st
)) {
118 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
120 /* Cannot be a symlink. */
121 if (S_ISLNK(smb_fname
->st
.st_ex_mode
)) {
122 return NT_STATUS_ACCESS_DENIED
;
124 /* Set options correctly for directory open. */
125 if (S_ISDIR(smb_fname
->st
.st_ex_mode
)) {
127 * Only FILE_FLAG_POSIX_SEMANTICS matters on existing
128 * directories, but set reasonable defaults.
130 file_attributes
= 0775;
131 create_options
= FILE_DIRECTORY_FILE
;
134 status
= make_smb2_posix_create_ctx(
135 talloc_tos(), &posx
, file_attributes
);
136 if (!NT_STATUS_IS_OK(status
)) {
137 DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
142 status
= SMB_VFS_CREATE_FILE(
146 smb_fname
, /* fname */
147 access_mask
, /* access_mask */
148 share_access
, /* share_access */
149 create_disposition
,/* create_disposition*/
150 create_options
, /* create_options */
151 file_attributes
,/* file_attributes */
152 oplock
, /* oplock_request */
154 0, /* allocation_size */
155 0, /* private_flags */
158 ret_fsp
, /* result */
160 posx
, /* in_context */
161 NULL
); /* out_context */
169 /********************************************************************
170 Roundup a value to the nearest allocation roundup size boundary.
171 Only do this for Windows clients.
172 ********************************************************************/
174 uint64_t smb_roundup(connection_struct
*conn
, uint64_t val
)
176 uint64_t rval
= lp_allocation_roundup_size(SNUM(conn
));
178 /* Only roundup for Windows clients. */
179 enum remote_arch_types ra_type
= get_remote_arch();
180 if (rval
&& (ra_type
!= RA_SAMBA
) && (ra_type
!= RA_CIFSFS
)) {
181 val
= SMB_ROUNDUP(val
,rval
);
186 /****************************************************************************
187 Utility functions for dealing with extended attributes.
188 ****************************************************************************/
190 /****************************************************************************
191 Refuse to allow clients to overwrite our private xattrs.
192 ****************************************************************************/
194 bool samba_private_attr_name(const char *unix_ea_name
)
196 static const char * const prohibited_ea_names
[] = {
197 SAMBA_POSIX_INHERITANCE_EA_NAME
,
198 SAMBA_XATTR_DOS_ATTRIB
,
207 for (i
= 0; prohibited_ea_names
[i
]; i
++) {
208 if (strequal( prohibited_ea_names
[i
], unix_ea_name
))
211 if (strncasecmp_m(unix_ea_name
, SAMBA_XATTR_DOSSTREAM_PREFIX
,
212 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX
)) == 0) {
218 /****************************************************************************
219 Get one EA value. Fill in a struct ea_struct.
220 ****************************************************************************/
222 NTSTATUS
get_ea_value_fsp(TALLOC_CTX
*mem_ctx
,
225 struct ea_struct
*pea
)
227 /* Get the value of this xattr. Max size is 64k. */
228 size_t attr_size
= 256;
231 size_t max_xattr_size
= 0;
234 return NT_STATUS_INVALID_HANDLE
;
237 max_xattr_size
= lp_smbd_max_xattr_size(SNUM(fsp
->conn
));
241 val
= talloc_realloc(mem_ctx
, val
, char, attr_size
);
243 return NT_STATUS_NO_MEMORY
;
246 sizeret
= SMB_VFS_FGETXATTR(fsp
, ea_name
, val
, attr_size
);
247 if (sizeret
== -1 && errno
== ERANGE
&& attr_size
< max_xattr_size
) {
248 attr_size
= max_xattr_size
;
253 return map_nt_error_from_unix(errno
);
256 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name
, (unsigned int)sizeret
));
257 dump_data(10, (uint8_t *)val
, sizeret
);
260 if (strnequal(ea_name
, "user.", 5)) {
261 pea
->name
= talloc_strdup(mem_ctx
, &ea_name
[5]);
263 pea
->name
= talloc_strdup(mem_ctx
, ea_name
);
265 if (pea
->name
== NULL
) {
267 return NT_STATUS_NO_MEMORY
;
269 pea
->value
.data
= (unsigned char *)val
;
270 pea
->value
.length
= (size_t)sizeret
;
274 NTSTATUS
get_ea_names_from_fsp(TALLOC_CTX
*mem_ctx
,
280 /* Get a list of all xattrs. Max namesize is 64k. */
281 size_t ea_namelist_size
= 1024;
282 char *ea_namelist
= smallbuf
;
283 char *to_free
= NULL
;
288 ssize_t sizeret
= -1;
298 * Callers may pass fsp == NULL when passing smb_fname->fsp of a
299 * symlink. This is ok, handle it here, by just return no EA's
305 /* should be the case that fsp != NULL */
306 SMB_ASSERT(fsp
!= NULL
);
308 sizeret
= SMB_VFS_FLISTXATTR(fsp
, ea_namelist
,
311 if ((sizeret
== -1) && (errno
== ERANGE
)) {
312 ea_namelist_size
= 65536;
313 ea_namelist
= talloc_array(mem_ctx
, char, ea_namelist_size
);
314 if (ea_namelist
== NULL
) {
315 return NT_STATUS_NO_MEMORY
;
317 to_free
= ea_namelist
;
319 sizeret
= SMB_VFS_FLISTXATTR(fsp
, ea_namelist
,
324 status
= map_nt_error_from_unix(errno
);
325 TALLOC_FREE(to_free
);
329 DBG_DEBUG("ea_namelist size = %zd\n", sizeret
);
332 TALLOC_FREE(to_free
);
337 * Ensure the result is 0-terminated
340 if (ea_namelist
[sizeret
-1] != '\0') {
341 TALLOC_FREE(to_free
);
342 return NT_STATUS_INTERNAL_ERROR
;
350 for (p
= ea_namelist
; p
- ea_namelist
< sizeret
; p
+= strlen(p
)+1) {
354 *pnum_names
= num_names
;
356 if (pnames
== NULL
) {
357 TALLOC_FREE(to_free
);
361 names
= talloc_array(mem_ctx
, char *, num_names
);
363 DEBUG(0, ("talloc failed\n"));
364 TALLOC_FREE(to_free
);
365 return NT_STATUS_NO_MEMORY
;
368 if (ea_namelist
== smallbuf
) {
369 ea_namelist
= talloc_memdup(names
, smallbuf
, sizeret
);
370 if (ea_namelist
== NULL
) {
372 return NT_STATUS_NO_MEMORY
;
375 talloc_steal(names
, ea_namelist
);
377 ea_namelist
= talloc_realloc(names
, ea_namelist
, char,
379 if (ea_namelist
== NULL
) {
381 return NT_STATUS_NO_MEMORY
;
387 for (p
= ea_namelist
; p
- ea_namelist
< sizeret
; p
+= strlen(p
)+1) {
388 names
[num_names
++] = p
;
396 /****************************************************************************
397 Return a linked list of the total EA's. Plus the total size
398 ****************************************************************************/
400 static NTSTATUS
get_ea_list_from_fsp(TALLOC_CTX
*mem_ctx
,
402 size_t *pea_total_len
,
403 struct ea_list
**ea_list
)
405 /* Get a list of all xattrs. Max namesize is 64k. */
408 struct ea_list
*ea_list_head
= NULL
;
409 bool posix_pathnames
= false;
420 if (!lp_ea_support(SNUM(fsp
->conn
))) {
424 if (fsp_is_alternate_stream(fsp
)) {
425 return NT_STATUS_INVALID_PARAMETER
;
428 posix_pathnames
= (fsp
->fsp_name
->flags
& SMB_FILENAME_POSIX_PATH
);
430 status
= get_ea_names_from_fsp(talloc_tos(),
435 if (!NT_STATUS_IS_OK(status
)) {
439 if (num_names
== 0) {
443 for (i
=0; i
<num_names
; i
++) {
444 struct ea_list
*listp
;
448 * POSIX EA names are divided into several namespaces by
449 * means of string prefixes. Usually, the system controls
450 * semantics for each namespace, but the 'user' namespace is
451 * available for arbitrary use, which comes closest to
452 * Windows EA semantics. Hence, we map POSIX EAs from the
453 * 'user' namespace to Windows EAs, and just ignore all the
454 * other namespaces. Also, a few specific names in the 'user'
455 * namespace are used by Samba internally. Filter them out as
456 * well, and only present the EAs that are available for
459 if (!strnequal(names
[i
], "user.", 5)
460 || samba_private_attr_name(names
[i
]))
464 * Filter out any underlying POSIX EA names
465 * that a Windows client can't handle.
467 if (!posix_pathnames
&&
468 is_invalid_windows_ea_name(names
[i
])) {
472 listp
= talloc(mem_ctx
, struct ea_list
);
474 return NT_STATUS_NO_MEMORY
;
477 status
= get_ea_value_fsp(listp
,
482 if (!NT_STATUS_IS_OK(status
)) {
487 if (listp
->ea
.value
.length
== 0) {
489 * We can never return a zero length EA.
490 * Windows reports the EA's as corrupted.
494 } else if (listp
->ea
.value
.length
> 65536) {
496 * SMB clients may report error with file
497 * if large EA is presented to them.
499 DBG_ERR("EA [%s] on file [%s] exceeds "
500 "maximum permitted EA size of 64KiB: %zu\n.",
501 listp
->ea
.name
, fsp_str_dbg(fsp
),
502 listp
->ea
.value
.length
);
507 push_ascii_fstring(dos_ea_name
, listp
->ea
.name
);
510 4 + strlen(dos_ea_name
) + 1 + listp
->ea
.value
.length
;
512 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
513 "= %u\n", (unsigned int)*pea_total_len
, dos_ea_name
,
514 (unsigned int)listp
->ea
.value
.length
));
516 DLIST_ADD_END(ea_list_head
, listp
);
520 /* Add on 4 for total length. */
521 if (*pea_total_len
) {
525 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
526 (unsigned int)*pea_total_len
));
528 *ea_list
= ea_list_head
;
532 /****************************************************************************
533 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
535 ****************************************************************************/
537 static unsigned int fill_ea_buffer(TALLOC_CTX
*mem_ctx
, char *pdata
, unsigned int total_data_size
,
538 connection_struct
*conn
, struct ea_list
*ea_list
)
540 unsigned int ret_data_size
= 4;
543 SMB_ASSERT(total_data_size
>= 4);
545 if (!lp_ea_support(SNUM(conn
))) {
550 for (p
= pdata
+ 4; ea_list
; ea_list
= ea_list
->next
) {
553 push_ascii_fstring(dos_ea_name
, ea_list
->ea
.name
);
554 dos_namelen
= strlen(dos_ea_name
);
555 if (dos_namelen
> 255 || dos_namelen
== 0) {
558 if (ea_list
->ea
.value
.length
> 65535) {
561 if (4 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
> total_data_size
) {
565 /* We know we have room. */
566 SCVAL(p
,0,ea_list
->ea
.flags
);
567 SCVAL(p
,1,dos_namelen
);
568 SSVAL(p
,2,ea_list
->ea
.value
.length
);
569 strlcpy(p
+4, dos_ea_name
, dos_namelen
+1);
570 if (ea_list
->ea
.value
.length
> 0) {
571 memcpy(p
+ 4 + dos_namelen
+ 1,
572 ea_list
->ea
.value
.data
,
573 ea_list
->ea
.value
.length
);
576 total_data_size
-= 4 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
;
577 p
+= 4 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
;
580 ret_data_size
= PTR_DIFF(p
, pdata
);
581 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size
));
582 SIVAL(pdata
,0,ret_data_size
);
583 return ret_data_size
;
586 static NTSTATUS
fill_ea_chained_buffer(TALLOC_CTX
*mem_ctx
,
588 unsigned int total_data_size
,
589 unsigned int *ret_data_size
,
590 connection_struct
*conn
,
591 struct ea_list
*ea_list
)
593 uint8_t *p
= (uint8_t *)pdata
;
594 uint8_t *last_start
= NULL
;
595 bool do_store_data
= (pdata
!= NULL
);
599 if (!lp_ea_support(SNUM(conn
))) {
600 return NT_STATUS_NO_EAS_ON_FILE
;
603 for (; ea_list
; ea_list
= ea_list
->next
) {
609 if (last_start
!= NULL
&& do_store_data
) {
610 SIVAL(last_start
, 0, PTR_DIFF(p
, last_start
));
614 push_ascii_fstring(dos_ea_name
, ea_list
->ea
.name
);
615 dos_namelen
= strlen(dos_ea_name
);
616 if (dos_namelen
> 255 || dos_namelen
== 0) {
617 return NT_STATUS_INTERNAL_ERROR
;
619 if (ea_list
->ea
.value
.length
> 65535) {
620 return NT_STATUS_INTERNAL_ERROR
;
623 this_size
= 0x08 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
;
626 pad
= (4 - (this_size
% 4)) % 4;
631 if (this_size
> total_data_size
) {
632 return NT_STATUS_INFO_LENGTH_MISMATCH
;
635 /* We know we have room. */
636 SIVAL(p
, 0x00, 0); /* next offset */
637 SCVAL(p
, 0x04, ea_list
->ea
.flags
);
638 SCVAL(p
, 0x05, dos_namelen
);
639 SSVAL(p
, 0x06, ea_list
->ea
.value
.length
);
640 strlcpy((char *)(p
+0x08), dos_ea_name
, dos_namelen
+1);
641 memcpy(p
+ 0x08 + dos_namelen
+ 1, ea_list
->ea
.value
.data
, ea_list
->ea
.value
.length
);
643 memset(p
+ 0x08 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
,
647 total_data_size
-= this_size
;
653 *ret_data_size
= PTR_DIFF(p
, pdata
);
654 DEBUG(10,("fill_ea_chained_buffer: data_size = %u\n", *ret_data_size
));
658 unsigned int estimate_ea_size(files_struct
*fsp
)
660 size_t total_ea_len
= 0;
662 struct ea_list
*ea_list
= NULL
;
670 if (!lp_ea_support(SNUM(fsp
->conn
))) {
674 mem_ctx
= talloc_stackframe();
676 /* If this is a stream fsp, then we need to instead find the
677 * estimated ea len from the main file, not the stream
678 * (streams cannot have EAs), but the estimate isn't just 0 in
680 fsp
= metadata_fsp(fsp
);
681 (void)get_ea_list_from_fsp(mem_ctx
,
686 if(fsp
->conn
->sconn
->using_smb2
) {
687 unsigned int ret_data_size
;
689 * We're going to be using fill_ea_chained_buffer() to
690 * marshall EA's - this size is significantly larger
691 * than the SMB1 buffer. Re-calculate the size without
694 status
= fill_ea_chained_buffer(mem_ctx
,
700 if (!NT_STATUS_IS_OK(status
)) {
703 total_ea_len
= ret_data_size
;
705 TALLOC_FREE(mem_ctx
);
709 /****************************************************************************
710 Ensure the EA name is case insensitive by matching any existing EA name.
711 ****************************************************************************/
713 static void canonicalize_ea_name(files_struct
*fsp
,
714 fstring unix_ea_name
)
717 TALLOC_CTX
*mem_ctx
= talloc_tos();
718 struct ea_list
*ea_list
;
719 NTSTATUS status
= get_ea_list_from_fsp(mem_ctx
,
723 if (!NT_STATUS_IS_OK(status
)) {
727 for (; ea_list
; ea_list
= ea_list
->next
) {
728 if (strequal(&unix_ea_name
[5], ea_list
->ea
.name
)) {
729 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
730 &unix_ea_name
[5], ea_list
->ea
.name
));
731 strlcpy(&unix_ea_name
[5], ea_list
->ea
.name
, sizeof(fstring
)-5);
737 /****************************************************************************
738 Set or delete an extended attribute.
739 ****************************************************************************/
741 NTSTATUS
set_ea(connection_struct
*conn
, files_struct
*fsp
,
742 struct ea_list
*ea_list
)
745 bool posix_pathnames
= false;
747 if (!lp_ea_support(SNUM(conn
))) {
748 return NT_STATUS_EAS_NOT_SUPPORTED
;
752 return NT_STATUS_INVALID_HANDLE
;
755 posix_pathnames
= (fsp
->fsp_name
->flags
& SMB_FILENAME_POSIX_PATH
);
757 status
= refuse_symlink_fsp(fsp
);
758 if (!NT_STATUS_IS_OK(status
)) {
762 status
= check_access_fsp(fsp
, FILE_WRITE_EA
);
763 if (!NT_STATUS_IS_OK(status
)) {
767 /* Setting EAs on streams isn't supported. */
768 if (fsp_is_alternate_stream(fsp
)) {
769 return NT_STATUS_INVALID_PARAMETER
;
773 * Filter out invalid Windows EA names - before
774 * we set *any* of them.
777 if (!posix_pathnames
&& ea_list_has_invalid_name(ea_list
)) {
778 return STATUS_INVALID_EA_NAME
;
781 for (;ea_list
; ea_list
= ea_list
->next
) {
783 fstring unix_ea_name
;
786 * Complementing the forward mapping from POSIX EAs to
787 * Windows EAs in get_ea_list_from_fsp(), here we map in the
788 * opposite direction from Windows EAs to the 'user' namespace
789 * of POSIX EAs. Hence, all POSIX EA names the we set here must
790 * start with a 'user.' prefix.
792 fstrcpy(unix_ea_name
, "user.");
793 fstrcat(unix_ea_name
, ea_list
->ea
.name
);
795 canonicalize_ea_name(fsp
, unix_ea_name
);
797 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name
, (unsigned int)ea_list
->ea
.value
.length
));
799 if (samba_private_attr_name(unix_ea_name
)) {
800 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name
));
801 return NT_STATUS_ACCESS_DENIED
;
804 if (ea_list
->ea
.value
.length
== 0) {
805 /* Remove the attribute. */
806 DBG_DEBUG("deleting ea name %s on "
807 "file %s by file descriptor.\n",
808 unix_ea_name
, fsp_str_dbg(fsp
));
809 ret
= SMB_VFS_FREMOVEXATTR(fsp
, unix_ea_name
);
811 /* Removing a non existent attribute always succeeds. */
812 if (ret
== -1 && errno
== ENOATTR
) {
813 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
819 DEBUG(10,("set_ea: setting ea name %s on file "
820 "%s by file descriptor.\n",
821 unix_ea_name
, fsp_str_dbg(fsp
)));
822 ret
= SMB_VFS_FSETXATTR(fsp
, unix_ea_name
,
823 ea_list
->ea
.value
.data
, ea_list
->ea
.value
.length
, 0);
828 if (errno
== ENOTSUP
) {
829 return NT_STATUS_EAS_NOT_SUPPORTED
;
832 return map_nt_error_from_unix(errno
);
839 /****************************************************************************
840 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
841 ****************************************************************************/
843 struct ea_list
*read_ea_list(TALLOC_CTX
*ctx
, const char *pdata
, size_t data_size
)
845 struct ea_list
*ea_list_head
= NULL
;
847 size_t bytes_used
= 0;
849 while (offset
< data_size
) {
850 struct ea_list
*eal
= read_ea_list_entry(ctx
, pdata
+ offset
, data_size
- offset
, &bytes_used
);
856 DLIST_ADD_END(ea_list_head
, eal
);
857 offset
+= bytes_used
;
863 /****************************************************************************
864 Count the total EA size needed.
865 ****************************************************************************/
867 static size_t ea_list_size(struct ea_list
*ealist
)
870 struct ea_list
*listp
;
873 for (listp
= ealist
; listp
; listp
= listp
->next
) {
874 push_ascii_fstring(dos_ea_name
, listp
->ea
.name
);
875 ret
+= 4 + strlen(dos_ea_name
) + 1 + listp
->ea
.value
.length
;
877 /* Add on 4 for total length. */
885 /****************************************************************************
886 Return a union of EA's from a file list and a list of names.
887 The TALLOC context for the two lists *MUST* be identical as we steal
888 memory from one list to add to another. JRA.
889 ****************************************************************************/
891 static struct ea_list
*ea_list_union(struct ea_list
*name_list
, struct ea_list
*file_list
, size_t *total_ea_len
)
893 struct ea_list
*nlistp
, *flistp
;
895 for (nlistp
= name_list
; nlistp
; nlistp
= nlistp
->next
) {
896 for (flistp
= file_list
; flistp
; flistp
= flistp
->next
) {
897 if (strequal(nlistp
->ea
.name
, flistp
->ea
.name
)) {
903 /* Copy the data from this entry. */
904 nlistp
->ea
.flags
= flistp
->ea
.flags
;
905 nlistp
->ea
.value
= flistp
->ea
.value
;
908 nlistp
->ea
.flags
= 0;
909 ZERO_STRUCT(nlistp
->ea
.value
);
913 *total_ea_len
= ea_list_size(name_list
);
917 /*********************************************************
918 Routine to check if a given string matches exactly.
919 as a special case a mask of "." does NOT match. That
920 is required for correct wildcard semantics
921 Case can be significant or not.
922 **********************************************************/
924 static bool exact_match(bool has_wild
,
929 if (mask
[0] == '.' && mask
[1] == 0) {
937 if (case_sensitive
) {
938 return strcmp(str
,mask
)==0;
940 return strcasecmp_m(str
,mask
) == 0;
944 /****************************************************************************
945 Return the filetype for UNIX extensions.
946 ****************************************************************************/
948 static uint32_t unix_filetype(mode_t mode
)
951 return UNIX_TYPE_FILE
;
952 else if(S_ISDIR(mode
))
953 return UNIX_TYPE_DIR
;
955 else if(S_ISLNK(mode
))
956 return UNIX_TYPE_SYMLINK
;
959 else if(S_ISCHR(mode
))
960 return UNIX_TYPE_CHARDEV
;
963 else if(S_ISBLK(mode
))
964 return UNIX_TYPE_BLKDEV
;
967 else if(S_ISFIFO(mode
))
968 return UNIX_TYPE_FIFO
;
971 else if(S_ISSOCK(mode
))
972 return UNIX_TYPE_SOCKET
;
975 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode
));
976 return UNIX_TYPE_UNKNOWN
;
979 /****************************************************************************
980 Map wire perms onto standard UNIX permissions. Obey share restrictions.
981 ****************************************************************************/
983 NTSTATUS
unix_perms_from_wire(connection_struct
*conn
,
984 const SMB_STRUCT_STAT
*psbuf
,
986 enum perm_type ptype
,
991 if (perms
== SMB_MODE_NO_CHANGE
) {
992 if (!VALID_STAT(*psbuf
)) {
993 return NT_STATUS_INVALID_PARAMETER
;
995 *ret_perms
= psbuf
->st_ex_mode
;
1000 ret
= wire_perms_to_unix(perms
);
1002 if (ptype
== PERM_NEW_FILE
) {
1004 * "create mask"/"force create mode" are
1005 * only applied to new files, not existing ones.
1007 ret
&= lp_create_mask(SNUM(conn
));
1008 /* Add in force bits */
1009 ret
|= lp_force_create_mode(SNUM(conn
));
1010 } else if (ptype
== PERM_NEW_DIR
) {
1012 * "directory mask"/"force directory mode" are
1013 * only applied to new directories, not existing ones.
1015 ret
&= lp_directory_mask(SNUM(conn
));
1016 /* Add in force bits */
1017 ret
|= lp_force_directory_mode(SNUM(conn
));
1021 return NT_STATUS_OK
;
1024 /****************************************************************************
1025 Needed to show the msdfs symlinks as directories. Modifies psbuf
1026 to be a directory if it's a msdfs link.
1027 ****************************************************************************/
1029 static bool check_msdfs_link(struct files_struct
*dirfsp
,
1030 struct smb_filename
*atname
,
1031 struct smb_filename
*smb_fname
)
1033 int saved_errno
= errno
;
1034 if(lp_host_msdfs() &&
1035 lp_msdfs_root(SNUM(dirfsp
->conn
)) &&
1036 is_msdfs_link(dirfsp
, atname
)) {
1039 * Copy the returned stat struct from the relative
1040 * to the full pathname.
1042 smb_fname
->st
= atname
->st
;
1044 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1046 smb_fname
->base_name
));
1047 smb_fname
->st
.st_ex_mode
=
1048 (smb_fname
->st
.st_ex_mode
& 0xFFF) | S_IFDIR
;
1049 errno
= saved_errno
;
1052 errno
= saved_errno
;
1057 /****************************************************************************
1058 Get a level dependent lanman2 dir entry.
1059 ****************************************************************************/
1061 struct smbd_dirptr_lanman2_state
{
1062 connection_struct
*conn
;
1063 uint32_t info_level
;
1064 bool check_mangled_names
;
1066 bool got_exact_match
;
1067 bool case_sensitive
;
1070 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX
*ctx
,
1076 struct smbd_dirptr_lanman2_state
*state
=
1077 (struct smbd_dirptr_lanman2_state
*)private_data
;
1079 char mangled_name
[13]; /* mangled 8.3 name. */
1083 /* Mangle fname if it's an illegal name. */
1084 if (mangle_must_mangle(dname
, state
->conn
->params
)) {
1086 * Slow path - ensure we can push the original name as UCS2. If
1087 * not, then just don't return this name.
1091 size_t len
= (strlen(dname
) + 2) * 4; /* Allow enough space. */
1092 uint8_t *tmp
= talloc_array(talloc_tos(),
1096 status
= srvstr_push(NULL
,
1097 FLAGS2_UNICODE_STRINGS
,
1106 if (!NT_STATUS_IS_OK(status
)) {
1110 ok
= name_to_8_3(dname
, mangled_name
,
1111 true, state
->conn
->params
);
1115 fname
= mangled_name
;
1120 got_match
= exact_match(state
->has_wild
,
1121 state
->case_sensitive
,
1123 state
->got_exact_match
= got_match
;
1125 got_match
= mask_match(fname
, mask
,
1126 state
->case_sensitive
);
1129 if(!got_match
&& state
->check_mangled_names
&&
1130 !mangle_is_8_3(fname
, false, state
->conn
->params
)) {
1132 * It turns out that NT matches wildcards against
1133 * both long *and* short names. This may explain some
1134 * of the wildcard wierdness from old DOS clients
1135 * that some people have been seeing.... JRA.
1137 /* Force the mangling into 8.3. */
1138 ok
= name_to_8_3(fname
, mangled_name
,
1139 false, state
->conn
->params
);
1144 got_match
= exact_match(state
->has_wild
,
1145 state
->case_sensitive
,
1146 mangled_name
, mask
);
1147 state
->got_exact_match
= got_match
;
1149 got_match
= mask_match(mangled_name
, mask
,
1150 state
->case_sensitive
);
1158 *_fname
= talloc_strdup(ctx
, fname
);
1159 if (*_fname
== NULL
) {
1166 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX
*ctx
,
1168 struct files_struct
*dirfsp
,
1169 struct smb_filename
*atname
,
1170 struct smb_filename
*smb_fname
,
1174 struct smbd_dirptr_lanman2_state
*state
=
1175 (struct smbd_dirptr_lanman2_state
*)private_data
;
1176 bool ms_dfs_link
= false;
1178 if (smb_fname
->flags
& SMB_FILENAME_POSIX_PATH
) {
1179 if (SMB_VFS_LSTAT(state
->conn
, smb_fname
) != 0) {
1180 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1181 "Couldn't lstat [%s] (%s)\n",
1182 smb_fname_str_dbg(smb_fname
),
1189 if (!VALID_STAT(smb_fname
->st
) &&
1190 SMB_VFS_STAT(state
->conn
, smb_fname
) != 0) {
1191 /* Needed to show the msdfs symlinks as
1194 ms_dfs_link
= check_msdfs_link(dirfsp
,
1198 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1199 "Couldn't stat [%s] (%s)\n",
1200 smb_fname_str_dbg(smb_fname
),
1205 *_mode
= dos_mode_msdfs(state
->conn
, smb_fname
);
1213 *_mode
= fdos_mode(smb_fname
->fsp
);
1214 smb_fname
->st
= smb_fname
->fsp
->fsp_name
->st
;
1219 static NTSTATUS
smbd_marshall_dir_entry(TALLOC_CTX
*ctx
,
1220 connection_struct
*conn
,
1222 uint32_t info_level
,
1223 struct ea_list
*name_list
,
1224 bool check_mangled_names
,
1225 bool requires_resume_key
,
1228 const struct smb_filename
*smb_fname
,
1229 int space_remaining
,
1235 uint64_t *last_entry_off
)
1237 char *p
, *q
, *pdata
= *ppdata
;
1239 uint64_t file_size
= 0;
1240 uint64_t allocation_size
= 0;
1241 uint64_t file_id
= 0;
1243 struct timespec mdate_ts
= {0};
1244 struct timespec adate_ts
= {0};
1245 struct timespec cdate_ts
= {0};
1246 struct timespec create_date_ts
= {0};
1247 time_t mdate
= (time_t)0, adate
= (time_t)0, create_date
= (time_t)0;
1249 char *last_entry_ptr
;
1254 struct readdir_attr_data
*readdir_attr_data
= NULL
;
1256 if (!(mode
& FILE_ATTRIBUTE_DIRECTORY
)) {
1257 file_size
= get_file_size_stat(&smb_fname
->st
);
1259 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
, NULL
, &smb_fname
->st
);
1262 * Skip SMB_VFS_FREADDIR_ATTR if the directory entry is a symlink or
1265 if (smb_fname
->fsp
!= NULL
&&
1266 !(mode
& FILE_ATTRIBUTE_REPARSE_POINT
)) {
1267 status
= SMB_VFS_FREADDIR_ATTR(smb_fname
->fsp
,
1269 &readdir_attr_data
);
1270 if (!NT_STATUS_IS_OK(status
)) {
1271 if (!NT_STATUS_EQUAL(NT_STATUS_NOT_SUPPORTED
,
1278 file_id
= SMB_VFS_FS_FILE_ID(conn
, &smb_fname
->st
);
1280 mdate_ts
= smb_fname
->st
.st_ex_mtime
;
1281 adate_ts
= smb_fname
->st
.st_ex_atime
;
1282 create_date_ts
= get_create_timespec(conn
, NULL
, smb_fname
);
1283 cdate_ts
= get_change_timespec(conn
, NULL
, smb_fname
);
1285 if (lp_dos_filetime_resolution(SNUM(conn
))) {
1286 dos_filetime_timespec(&create_date_ts
);
1287 dos_filetime_timespec(&mdate_ts
);
1288 dos_filetime_timespec(&adate_ts
);
1289 dos_filetime_timespec(&cdate_ts
);
1292 create_date
= convert_timespec_to_time_t(create_date_ts
);
1293 mdate
= convert_timespec_to_time_t(mdate_ts
);
1294 adate
= convert_timespec_to_time_t(adate_ts
);
1296 /* align the record */
1297 SMB_ASSERT(align
>= 1);
1299 off
= (int)PTR_DIFF(pdata
, base_data
);
1300 pad
= (off
+ (align
-1)) & ~(align
-1);
1303 if (pad
&& pad
> space_remaining
) {
1304 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1305 "for padding (wanted %u, had %d)\n",
1308 return STATUS_MORE_ENTRIES
; /* Not finished - just out of space */
1312 /* initialize padding to 0 */
1314 memset(pdata
, 0, pad
);
1316 space_remaining
-= pad
;
1318 DEBUG(10,("smbd_marshall_dir_entry: space_remaining = %d\n",
1328 switch (info_level
) {
1329 case SMB_FIND_INFO_STANDARD
:
1330 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1331 if(requires_resume_key
) {
1335 srv_put_dos_date2(p
,0,create_date
);
1336 srv_put_dos_date2(p
,4,adate
);
1337 srv_put_dos_date2(p
,8,mdate
);
1338 SIVAL(p
,12,(uint32_t)file_size
);
1339 SIVAL(p
,16,(uint32_t)allocation_size
);
1343 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1344 p
+= ucs2_align(base_data
, p
, 0);
1346 status
= srvstr_push(base_data
, flags2
, p
,
1347 fname
, PTR_DIFF(end_data
, p
),
1348 STR_TERMINATE
, &len
);
1349 if (!NT_STATUS_IS_OK(status
)) {
1352 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1354 SCVAL(nameptr
, -1, len
- 2);
1356 SCVAL(nameptr
, -1, 0);
1360 SCVAL(nameptr
, -1, len
- 1);
1362 SCVAL(nameptr
, -1, 0);
1368 case SMB_FIND_EA_SIZE
:
1369 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
1370 if (requires_resume_key
) {
1374 srv_put_dos_date2(p
,0,create_date
);
1375 srv_put_dos_date2(p
,4,adate
);
1376 srv_put_dos_date2(p
,8,mdate
);
1377 SIVAL(p
,12,(uint32_t)file_size
);
1378 SIVAL(p
,16,(uint32_t)allocation_size
);
1381 unsigned int ea_size
= estimate_ea_size(smb_fname
->fsp
);
1382 SIVAL(p
,22,ea_size
); /* Extended attributes */
1386 status
= srvstr_push(base_data
, flags2
,
1387 p
, fname
, PTR_DIFF(end_data
, p
),
1388 STR_TERMINATE
| STR_NOALIGN
, &len
);
1389 if (!NT_STATUS_IS_OK(status
)) {
1392 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1405 SCVAL(nameptr
,0,len
);
1407 SCVAL(p
,0,0); p
+= 1; /* Extra zero byte ? - why.. */
1410 case SMB_FIND_EA_LIST
:
1412 struct ea_list
*file_list
= NULL
;
1415 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
1417 return NT_STATUS_INVALID_PARAMETER
;
1419 if (requires_resume_key
) {
1423 srv_put_dos_date2(p
,0,create_date
);
1424 srv_put_dos_date2(p
,4,adate
);
1425 srv_put_dos_date2(p
,8,mdate
);
1426 SIVAL(p
,12,(uint32_t)file_size
);
1427 SIVAL(p
,16,(uint32_t)allocation_size
);
1429 p
+= 22; /* p now points to the EA area. */
1431 status
= get_ea_list_from_fsp(ctx
,
1433 &ea_len
, &file_list
);
1434 if (!NT_STATUS_IS_OK(status
)) {
1437 name_list
= ea_list_union(name_list
, file_list
, &ea_len
);
1439 /* We need to determine if this entry will fit in the space available. */
1440 /* Max string size is 255 bytes. */
1441 if (PTR_DIFF(p
+ 255 + ea_len
,pdata
) > space_remaining
) {
1442 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1443 "(wanted %u, had %d)\n",
1444 (unsigned int)PTR_DIFF(p
+ 255 + ea_len
,pdata
),
1446 return STATUS_MORE_ENTRIES
; /* Not finished - just out of space */
1449 /* Push the ea_data followed by the name. */
1450 p
+= fill_ea_buffer(ctx
, p
, space_remaining
, conn
, name_list
);
1452 status
= srvstr_push(base_data
, flags2
,
1453 p
+ 1, fname
, PTR_DIFF(end_data
, p
+1),
1454 STR_TERMINATE
| STR_NOALIGN
, &len
);
1455 if (!NT_STATUS_IS_OK(status
)) {
1458 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1471 SCVAL(nameptr
,0,len
);
1473 SCVAL(p
,0,0); p
+= 1; /* Extra zero byte ? - why.. */
1477 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
1478 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1479 was_8_3
= mangle_is_8_3(fname
, True
, conn
->params
);
1481 SIVAL(p
,0,reskey
); p
+= 4;
1482 put_long_date_full_timespec(conn
->ts_res
,p
,&create_date_ts
); p
+= 8;
1483 put_long_date_full_timespec(conn
->ts_res
,p
,&adate_ts
); p
+= 8;
1484 put_long_date_full_timespec(conn
->ts_res
,p
,&mdate_ts
); p
+= 8;
1485 put_long_date_full_timespec(conn
->ts_res
,p
,&cdate_ts
); p
+= 8;
1486 SOFF_T(p
,0,file_size
); p
+= 8;
1487 SOFF_T(p
,0,allocation_size
); p
+= 8;
1488 SIVAL(p
,0,mode
); p
+= 4;
1489 q
= p
; p
+= 4; /* q is placeholder for name length. */
1490 if (mode
& FILE_ATTRIBUTE_REPARSE_POINT
) {
1491 SIVAL(p
, 0, IO_REPARSE_TAG_DFS
);
1493 unsigned int ea_size
= estimate_ea_size(smb_fname
->fsp
);
1494 SIVAL(p
,0,ea_size
); /* Extended attributes */
1497 /* Clear the short name buffer. This is
1498 * IMPORTANT as not doing so will trigger
1499 * a Win2k client bug. JRA.
1501 if (!was_8_3
&& check_mangled_names
) {
1502 char mangled_name
[13]; /* mangled 8.3 name. */
1503 if (!name_to_8_3(fname
,mangled_name
,True
,
1505 /* Error - mangle failed ! */
1506 memset(mangled_name
,'\0',12);
1508 mangled_name
[12] = 0;
1509 status
= srvstr_push(base_data
, flags2
,
1510 p
+2, mangled_name
, 24,
1511 STR_UPPER
|STR_UNICODE
, &len
);
1512 if (!NT_STATUS_IS_OK(status
)) {
1516 memset(p
+ 2 + len
,'\0',24 - len
);
1523 status
= srvstr_push(base_data
, flags2
, p
,
1524 fname
, PTR_DIFF(end_data
, p
),
1525 STR_TERMINATE_ASCII
, &len
);
1526 if (!NT_STATUS_IS_OK(status
)) {
1532 len
= PTR_DIFF(p
, pdata
);
1533 pad
= (len
+ (align
-1)) & ~(align
-1);
1535 * offset to the next entry, the caller
1536 * will overwrite it for the last entry
1537 * that's why we always include the padding
1541 * set padding to zero
1544 memset(p
, 0, pad
- len
);
1551 case SMB_FIND_FILE_DIRECTORY_INFO
:
1552 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1554 SIVAL(p
,0,reskey
); p
+= 4;
1555 put_long_date_full_timespec(conn
->ts_res
,p
,&create_date_ts
); p
+= 8;
1556 put_long_date_full_timespec(conn
->ts_res
,p
,&adate_ts
); p
+= 8;
1557 put_long_date_full_timespec(conn
->ts_res
,p
,&mdate_ts
); p
+= 8;
1558 put_long_date_full_timespec(conn
->ts_res
,p
,&cdate_ts
); p
+= 8;
1559 SOFF_T(p
,0,file_size
); p
+= 8;
1560 SOFF_T(p
,0,allocation_size
); p
+= 8;
1561 SIVAL(p
,0,mode
); p
+= 4;
1562 status
= srvstr_push(base_data
, flags2
,
1563 p
+ 4, fname
, PTR_DIFF(end_data
, p
+4),
1564 STR_TERMINATE_ASCII
, &len
);
1565 if (!NT_STATUS_IS_OK(status
)) {
1571 len
= PTR_DIFF(p
, pdata
);
1572 pad
= (len
+ (align
-1)) & ~(align
-1);
1574 * offset to the next entry, the caller
1575 * will overwrite it for the last entry
1576 * that's why we always include the padding
1580 * set padding to zero
1583 memset(p
, 0, pad
- len
);
1590 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
1591 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1593 SIVAL(p
,0,reskey
); p
+= 4;
1594 put_long_date_full_timespec(conn
->ts_res
,p
,&create_date_ts
); p
+= 8;
1595 put_long_date_full_timespec(conn
->ts_res
,p
,&adate_ts
); p
+= 8;
1596 put_long_date_full_timespec(conn
->ts_res
,p
,&mdate_ts
); p
+= 8;
1597 put_long_date_full_timespec(conn
->ts_res
,p
,&cdate_ts
); p
+= 8;
1598 SOFF_T(p
,0,file_size
); p
+= 8;
1599 SOFF_T(p
,0,allocation_size
); p
+= 8;
1600 SIVAL(p
,0,mode
); p
+= 4;
1601 q
= p
; p
+= 4; /* q is placeholder for name length. */
1602 if (mode
& FILE_ATTRIBUTE_REPARSE_POINT
) {
1603 SIVAL(p
, 0, IO_REPARSE_TAG_DFS
);
1605 unsigned int ea_size
= estimate_ea_size(smb_fname
->fsp
);
1606 SIVAL(p
,0,ea_size
); /* Extended attributes */
1609 status
= srvstr_push(base_data
, flags2
, p
,
1610 fname
, PTR_DIFF(end_data
, p
),
1611 STR_TERMINATE_ASCII
, &len
);
1612 if (!NT_STATUS_IS_OK(status
)) {
1618 len
= PTR_DIFF(p
, pdata
);
1619 pad
= (len
+ (align
-1)) & ~(align
-1);
1621 * offset to the next entry, the caller
1622 * will overwrite it for the last entry
1623 * that's why we always include the padding
1627 * set padding to zero
1630 memset(p
, 0, pad
- len
);
1637 case SMB_FIND_FILE_NAMES_INFO
:
1638 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1640 SIVAL(p
,0,reskey
); p
+= 4;
1642 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1643 acl on a dir (tridge) */
1644 status
= srvstr_push(base_data
, flags2
, p
,
1645 fname
, PTR_DIFF(end_data
, p
),
1646 STR_TERMINATE_ASCII
, &len
);
1647 if (!NT_STATUS_IS_OK(status
)) {
1653 len
= PTR_DIFF(p
, pdata
);
1654 pad
= (len
+ (align
-1)) & ~(align
-1);
1656 * offset to the next entry, the caller
1657 * will overwrite it for the last entry
1658 * that's why we always include the padding
1662 * set padding to zero
1665 memset(p
, 0, pad
- len
);
1672 case SMB_FIND_ID_FULL_DIRECTORY_INFO
:
1673 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1675 SIVAL(p
,0,reskey
); p
+= 4;
1676 put_long_date_full_timespec(conn
->ts_res
,p
,&create_date_ts
); p
+= 8;
1677 put_long_date_full_timespec(conn
->ts_res
,p
,&adate_ts
); p
+= 8;
1678 put_long_date_full_timespec(conn
->ts_res
,p
,&mdate_ts
); p
+= 8;
1679 put_long_date_full_timespec(conn
->ts_res
,p
,&cdate_ts
); p
+= 8;
1680 SOFF_T(p
,0,file_size
); p
+= 8;
1681 SOFF_T(p
,0,allocation_size
); p
+= 8;
1682 SIVAL(p
,0,mode
); p
+= 4;
1683 q
= p
; p
+= 4; /* q is placeholder for name length. */
1684 if (mode
& FILE_ATTRIBUTE_REPARSE_POINT
) {
1685 SIVAL(p
, 0, IO_REPARSE_TAG_DFS
);
1687 unsigned int ea_size
= estimate_ea_size(smb_fname
->fsp
);
1688 SIVAL(p
,0,ea_size
); /* Extended attributes */
1691 SIVAL(p
,0,0); p
+= 4; /* Unknown - reserved ? */
1692 SBVAL(p
,0,file_id
); p
+= 8;
1693 status
= srvstr_push(base_data
, flags2
, p
,
1694 fname
, PTR_DIFF(end_data
, p
),
1695 STR_TERMINATE_ASCII
, &len
);
1696 if (!NT_STATUS_IS_OK(status
)) {
1702 len
= PTR_DIFF(p
, pdata
);
1703 pad
= (len
+ (align
-1)) & ~(align
-1);
1705 * offset to the next entry, the caller
1706 * will overwrite it for the last entry
1707 * that's why we always include the padding
1711 * set padding to zero
1714 memset(p
, 0, pad
- len
);
1721 case SMB_FIND_ID_BOTH_DIRECTORY_INFO
:
1722 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1723 was_8_3
= mangle_is_8_3(fname
, True
, conn
->params
);
1725 SIVAL(p
,0,reskey
); p
+= 4;
1726 put_long_date_full_timespec(conn
->ts_res
,p
,&create_date_ts
); p
+= 8;
1727 put_long_date_full_timespec(conn
->ts_res
,p
,&adate_ts
); p
+= 8;
1728 put_long_date_full_timespec(conn
->ts_res
,p
,&mdate_ts
); p
+= 8;
1729 put_long_date_full_timespec(conn
->ts_res
,p
,&cdate_ts
); p
+= 8;
1730 SOFF_T(p
,0,file_size
); p
+= 8;
1731 SOFF_T(p
,0,allocation_size
); p
+= 8;
1732 SIVAL(p
,0,mode
); p
+= 4;
1733 q
= p
; p
+= 4; /* q is placeholder for name length */
1734 if (mode
& FILE_ATTRIBUTE_REPARSE_POINT
) {
1735 SIVAL(p
, 0, IO_REPARSE_TAG_DFS
);
1736 } else if (readdir_attr_data
&&
1737 readdir_attr_data
->type
== RDATTR_AAPL
) {
1739 * OS X specific SMB2 extension negotiated via
1740 * AAPL create context: return max_access in
1743 SIVAL(p
, 0, readdir_attr_data
->attr_data
.aapl
.max_access
);
1745 unsigned int ea_size
= estimate_ea_size(smb_fname
->fsp
);
1746 SIVAL(p
,0,ea_size
); /* Extended attributes */
1750 if (readdir_attr_data
&&
1751 readdir_attr_data
->type
== RDATTR_AAPL
) {
1753 * OS X specific SMB2 extension negotiated via
1754 * AAPL create context: return resource fork
1755 * length and compressed FinderInfo in
1758 * According to documentation short_name_len
1759 * should be 0, but on the wire behaviour
1760 * shows its set to 24 by clients.
1764 /* Resourefork length */
1765 SBVAL(p
, 2, readdir_attr_data
->attr_data
.aapl
.rfork_size
);
1767 /* Compressed FinderInfo */
1768 memcpy(p
+ 10, &readdir_attr_data
->attr_data
.aapl
.finder_info
, 16);
1769 } else if (!was_8_3
&& check_mangled_names
) {
1770 char mangled_name
[13]; /* mangled 8.3 name. */
1771 if (!name_to_8_3(fname
,mangled_name
,True
,
1773 /* Error - mangle failed ! */
1774 memset(mangled_name
,'\0',12);
1776 mangled_name
[12] = 0;
1777 status
= srvstr_push(base_data
, flags2
,
1778 p
+2, mangled_name
, 24,
1779 STR_UPPER
|STR_UNICODE
, &len
);
1780 if (!NT_STATUS_IS_OK(status
)) {
1785 memset(p
+ 2 + len
,'\0',24 - len
);
1789 /* Clear the short name buffer. This is
1790 * IMPORTANT as not doing so will trigger
1791 * a Win2k client bug. JRA.
1798 if (readdir_attr_data
&&
1799 readdir_attr_data
->type
== RDATTR_AAPL
) {
1801 * OS X specific SMB2 extension negotiated via
1802 * AAPL create context: return UNIX mode in
1805 uint16_t aapl_mode
= (uint16_t)readdir_attr_data
->attr_data
.aapl
.unix_mode
;
1806 SSVAL(p
, 0, aapl_mode
);
1812 SBVAL(p
,0,file_id
); p
+= 8;
1813 status
= srvstr_push(base_data
, flags2
, p
,
1814 fname
, PTR_DIFF(end_data
, p
),
1815 STR_TERMINATE_ASCII
, &len
);
1816 if (!NT_STATUS_IS_OK(status
)) {
1822 len
= PTR_DIFF(p
, pdata
);
1823 pad
= (len
+ (align
-1)) & ~(align
-1);
1825 * offset to the next entry, the caller
1826 * will overwrite it for the last entry
1827 * that's why we always include the padding
1831 * set padding to zero
1834 memset(p
, 0, pad
- len
);
1841 /* CIFS UNIX Extension. */
1843 case SMB_FIND_FILE_UNIX
:
1844 case SMB_FIND_FILE_UNIX_INFO2
:
1846 SIVAL(p
,0,reskey
); p
+= 4; /* Used for continuing search. */
1848 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1850 if (info_level
== SMB_FIND_FILE_UNIX
) {
1851 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
1852 p
= store_file_unix_basic(conn
, p
,
1853 NULL
, &smb_fname
->st
);
1854 status
= srvstr_push(base_data
, flags2
, p
,
1855 fname
, PTR_DIFF(end_data
, p
),
1856 STR_TERMINATE
, &len
);
1857 if (!NT_STATUS_IS_OK(status
)) {
1861 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
1862 p
= store_file_unix_basic_info2(conn
, p
,
1863 NULL
, &smb_fname
->st
);
1866 status
= srvstr_push(base_data
, flags2
, p
, fname
,
1867 PTR_DIFF(end_data
, p
), 0, &len
);
1868 if (!NT_STATUS_IS_OK(status
)) {
1871 SIVAL(nameptr
, 0, len
);
1876 len
= PTR_DIFF(p
, pdata
);
1877 pad
= (len
+ (align
-1)) & ~(align
-1);
1879 * offset to the next entry, the caller
1880 * will overwrite it for the last entry
1881 * that's why we always include the padding
1885 * set padding to zero
1888 memset(p
, 0, pad
- len
);
1893 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1897 /* SMB2 UNIX Extension. */
1899 case SMB2_FILE_POSIX_INFORMATION
:
1901 uint8_t *buf
= NULL
;
1904 SIVAL(p
,0,reskey
); p
+= 4;
1906 DEBUG(10,("smbd_marshall_dir_entry: "
1907 "SMB2_FILE_POSIX_INFORMATION\n"));
1908 if (!(conn
->sconn
->using_smb2
)) {
1909 return NT_STATUS_INVALID_LEVEL
;
1911 if (!lp_smb3_unix_extensions()) {
1912 return NT_STATUS_INVALID_LEVEL
;
1915 /* Determine the size of the posix info context */
1916 plen
= store_smb2_posix_info(conn
,
1923 return NT_STATUS_INVALID_PARAMETER
;
1925 buf
= talloc_zero_size(ctx
, plen
);
1927 return NT_STATUS_NO_MEMORY
;
1930 /* Store the context in buf */
1931 store_smb2_posix_info(conn
,
1937 memcpy(p
, buf
, plen
);
1943 status
= srvstr_push(base_data
, flags2
, p
, fname
,
1944 PTR_DIFF(end_data
, p
), 0, &len
);
1945 if (!NT_STATUS_IS_OK(status
)) {
1948 SIVAL(nameptr
, 0, len
);
1952 len
= PTR_DIFF(p
, pdata
);
1953 pad
= (len
+ (align
-1)) & ~(align
-1);
1955 * offset to the next entry, the caller
1956 * will overwrite it for the last entry
1957 * that's why we always include the padding
1964 return NT_STATUS_INVALID_LEVEL
;
1967 if (PTR_DIFF(p
,pdata
) > space_remaining
) {
1968 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1969 "(wanted %u, had %d)\n",
1970 (unsigned int)PTR_DIFF(p
,pdata
),
1972 return STATUS_MORE_ENTRIES
; /* Not finished - just out of space */
1975 /* Setup the last entry pointer, as an offset from base_data */
1976 *last_entry_off
= PTR_DIFF(last_entry_ptr
,base_data
);
1977 /* Advance the data pointer to the next slot */
1980 return NT_STATUS_OK
;
1983 NTSTATUS
smbd_dirptr_lanman2_entry(TALLOC_CTX
*ctx
,
1984 connection_struct
*conn
,
1985 struct dptr_struct
*dirptr
,
1987 const char *path_mask
,
1990 int requires_resume_key
,
1999 int space_remaining
,
2000 struct smb_filename
**_smb_fname
,
2001 bool *got_exact_match
,
2002 int *_last_entry_off
,
2003 struct ea_list
*name_list
,
2004 struct file_id
*file_id
)
2007 const char *mask
= NULL
;
2008 long prev_dirpos
= 0;
2011 struct smb_filename
*smb_fname
= NULL
;
2012 struct smbd_dirptr_lanman2_state state
;
2014 uint64_t last_entry_off
= 0;
2016 enum mangled_names_options mangled_names
;
2017 bool marshall_with_83_names
;
2019 mangled_names
= lp_mangled_names(conn
->params
);
2023 state
.info_level
= info_level
;
2024 if (mangled_names
!= MANGLED_NAMES_NO
) {
2025 state
.check_mangled_names
= true;
2027 state
.has_wild
= dptr_has_wild(dirptr
);
2028 state
.got_exact_match
= false;
2029 state
.case_sensitive
= dptr_case_sensitive(dirptr
);
2031 *got_exact_match
= false;
2033 p
= strrchr_m(path_mask
,'/');
2044 ok
= smbd_dirptr_get_entry(ctx
,
2051 smbd_dirptr_lanman2_match_fn
,
2052 smbd_dirptr_lanman2_mode_fn
,
2059 return NT_STATUS_END_OF_FILE
;
2062 *got_exact_match
= state
.got_exact_match
;
2064 marshall_with_83_names
= (mangled_names
== MANGLED_NAMES_YES
);
2066 status
= smbd_marshall_dir_entry(ctx
,
2071 marshall_with_83_names
,
2072 requires_resume_key
,
2083 if (NT_STATUS_EQUAL(status
, NT_STATUS_ILLEGAL_CHARACTER
)) {
2084 DEBUG(1,("Conversion error: illegal character: %s\n",
2085 smb_fname_str_dbg(smb_fname
)));
2088 if (file_id
!= NULL
) {
2089 *file_id
= vfs_file_id_from_sbuf(conn
, &smb_fname
->st
);
2092 if (!NT_STATUS_IS_OK(status
) &&
2093 !NT_STATUS_EQUAL(status
, STATUS_MORE_ENTRIES
))
2095 TALLOC_FREE(smb_fname
);
2100 if (_smb_fname
!= NULL
) {
2102 * smb_fname is already talloc'ed off ctx.
2103 * We just need to make sure we don't return
2104 * any stream_name, and replace base_name
2105 * with fname in case base_name got mangled.
2106 * This allows us to preserve any smb_fname->fsp
2107 * for asynchronous handle lookups.
2109 TALLOC_FREE(smb_fname
->stream_name
);
2110 TALLOC_FREE(smb_fname
->base_name
);
2111 smb_fname
->base_name
= talloc_strdup(smb_fname
, fname
);
2113 if (smb_fname
->base_name
== NULL
) {
2114 TALLOC_FREE(smb_fname
);
2116 return NT_STATUS_NO_MEMORY
;
2118 *_smb_fname
= smb_fname
;
2120 TALLOC_FREE(smb_fname
);
2124 if (NT_STATUS_EQUAL(status
, STATUS_MORE_ENTRIES
)) {
2125 dptr_SeekDir(dirptr
, prev_dirpos
);
2129 *_last_entry_off
= last_entry_off
;
2130 return NT_STATUS_OK
;
2133 unsigned char *create_volume_objectid(connection_struct
*conn
, unsigned char objid
[16])
2135 const struct loadparm_substitution
*lp_sub
=
2136 loadparm_s3_global_substitution();
2138 E_md4hash(lp_servicename(talloc_tos(), lp_sub
, SNUM(conn
)),objid
);
2142 static void samba_extended_info_version(struct smb_extended_info
*extended_info
)
2144 SMB_ASSERT(extended_info
!= NULL
);
2146 extended_info
->samba_magic
= SAMBA_EXTENDED_INFO_MAGIC
;
2147 extended_info
->samba_version
= ((SAMBA_VERSION_MAJOR
& 0xff) << 24)
2148 | ((SAMBA_VERSION_MINOR
& 0xff) << 16)
2149 | ((SAMBA_VERSION_RELEASE
& 0xff) << 8);
2150 #ifdef SAMBA_VERSION_REVISION
2151 extended_info
->samba_version
|= (tolower(*SAMBA_VERSION_REVISION
) - 'a' + 1) & 0xff;
2153 extended_info
->samba_subversion
= 0;
2154 #ifdef SAMBA_VERSION_RC_RELEASE
2155 extended_info
->samba_subversion
|= (SAMBA_VERSION_RC_RELEASE
& 0xff) << 24;
2157 #ifdef SAMBA_VERSION_PRE_RELEASE
2158 extended_info
->samba_subversion
|= (SAMBA_VERSION_PRE_RELEASE
& 0xff) << 16;
2161 #ifdef SAMBA_VERSION_VENDOR_PATCH
2162 extended_info
->samba_subversion
|= (SAMBA_VERSION_VENDOR_PATCH
& 0xffff);
2164 extended_info
->samba_gitcommitdate
= 0;
2165 #ifdef SAMBA_VERSION_COMMIT_TIME
2166 unix_to_nt_time(&extended_info
->samba_gitcommitdate
, SAMBA_VERSION_COMMIT_TIME
);
2169 memset(extended_info
->samba_version_string
, 0,
2170 sizeof(extended_info
->samba_version_string
));
2172 snprintf (extended_info
->samba_version_string
,
2173 sizeof(extended_info
->samba_version_string
),
2174 "%s", samba_version_string());
2177 static bool fsinfo_unix_valid_level(connection_struct
*conn
,
2178 uint16_t info_level
)
2180 if (conn
->sconn
->using_smb2
&&
2181 lp_smb3_unix_extensions() &&
2182 info_level
== SMB2_FS_POSIX_INFORMATION_INTERNAL
) {
2185 #if defined(SMB1SERVER)
2186 if (lp_smb1_unix_extensions() &&
2187 info_level
== SMB_QUERY_POSIX_FS_INFO
) {
2194 NTSTATUS
smbd_do_qfsinfo(struct smbXsrv_connection
*xconn
,
2195 connection_struct
*conn
,
2196 TALLOC_CTX
*mem_ctx
,
2197 uint16_t info_level
,
2199 unsigned int max_data_bytes
,
2200 size_t *fixed_portion
,
2201 struct smb_filename
*fname
,
2205 const struct loadparm_substitution
*lp_sub
=
2206 loadparm_s3_global_substitution();
2207 char *pdata
, *end_data
;
2210 const char *vname
= volume_label(talloc_tos(), SNUM(conn
));
2211 int snum
= SNUM(conn
);
2212 const char *fstype
= lp_fstype(SNUM(conn
));
2213 const char *filename
= NULL
;
2214 const uint64_t bytes_per_sector
= 512;
2215 uint32_t additional_flags
= 0;
2216 struct smb_filename smb_fname
;
2218 NTSTATUS status
= NT_STATUS_OK
;
2222 if (fname
== NULL
|| fname
->base_name
== NULL
) {
2225 filename
= fname
->base_name
;
2229 if (info_level
!= SMB_QUERY_CIFS_UNIX_INFO
) {
2230 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
2231 "info level (0x%x) on IPC$.\n",
2232 (unsigned int)info_level
));
2233 return NT_STATUS_ACCESS_DENIED
;
2237 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level
));
2239 smb_fname
= (struct smb_filename
) {
2240 .base_name
= discard_const_p(char, filename
),
2241 .flags
= fname
? fname
->flags
: 0,
2242 .twrp
= fname
? fname
->twrp
: 0,
2245 if(info_level
!= SMB_FS_QUOTA_INFORMATION
2246 && SMB_VFS_STAT(conn
, &smb_fname
) != 0) {
2247 DEBUG(2,("stat of . failed (%s)\n", strerror(errno
)));
2248 return map_nt_error_from_unix(errno
);
2253 if (max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
< max_data_bytes
) {
2254 return NT_STATUS_INVALID_PARAMETER
;
2257 *ppdata
= (char *)SMB_REALLOC(
2258 *ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
2259 if (*ppdata
== NULL
) {
2260 return NT_STATUS_NO_MEMORY
;
2264 memset((char *)pdata
,'\0',max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
2265 end_data
= pdata
+ max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
- 1;
2269 switch (info_level
) {
2270 case SMB_INFO_ALLOCATION
:
2272 uint64_t dfree
,dsize
,bsize
,block_size
,sectors_per_unit
;
2274 df_ret
= get_dfree_info(conn
, &smb_fname
, &bsize
,
2276 if (df_ret
== (uint64_t)-1) {
2277 return map_nt_error_from_unix(errno
);
2280 block_size
= lp_block_size(snum
);
2281 if (bsize
< block_size
) {
2282 uint64_t factor
= block_size
/bsize
;
2287 if (bsize
> block_size
) {
2288 uint64_t factor
= bsize
/block_size
;
2293 sectors_per_unit
= bsize
/bytes_per_sector
;
2295 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2296 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st
.st_ex_dev
, (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
2297 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
2300 * For large drives, return max values and not modulo.
2302 dsize
= MIN(dsize
, UINT32_MAX
);
2303 dfree
= MIN(dfree
, UINT32_MAX
);
2305 SIVAL(pdata
,l1_idFileSystem
,st
.st_ex_dev
);
2306 SIVAL(pdata
,l1_cSectorUnit
,sectors_per_unit
);
2307 SIVAL(pdata
,l1_cUnit
,dsize
);
2308 SIVAL(pdata
,l1_cUnitAvail
,dfree
);
2309 SSVAL(pdata
,l1_cbSector
,bytes_per_sector
);
2313 case SMB_INFO_VOLUME
:
2314 /* Return volume name */
2316 * Add volume serial number - hash of a combination of
2317 * the called hostname and the service name.
2319 serial
= generate_volume_serial_number(lp_sub
, snum
);
2320 SIVAL(pdata
,0,serial
);
2322 * Win2k3 and previous mess this up by sending a name length
2323 * one byte short. I believe only older clients (OS/2 Win9x) use
2324 * this call so try fixing this by adding a terminating null to
2325 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2327 status
= srvstr_push(
2329 pdata
+l2_vol_szVolLabel
, vname
,
2330 PTR_DIFF(end_data
, pdata
+l2_vol_szVolLabel
),
2331 STR_NOALIGN
|STR_TERMINATE
, &len
);
2332 if (!NT_STATUS_IS_OK(status
)) {
2335 SCVAL(pdata
,l2_vol_cch
,len
);
2336 data_len
= l2_vol_szVolLabel
+ len
;
2337 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %u, "
2338 "name = %s serial = 0x%04"PRIx32
"\n",
2339 (unsigned)convert_timespec_to_time_t(st
.st_ex_ctime
),
2340 (unsigned)len
, vname
, serial
));
2343 case SMB_QUERY_FS_ATTRIBUTE_INFO
:
2344 case SMB_FS_ATTRIBUTE_INFORMATION
:
2346 additional_flags
= 0;
2347 #if defined(HAVE_SYS_QUOTAS)
2348 additional_flags
|= FILE_VOLUME_QUOTAS
;
2351 if(lp_nt_acl_support(SNUM(conn
))) {
2352 additional_flags
|= FILE_PERSISTENT_ACLS
;
2355 /* Capabilities are filled in at connection time through STATVFS call */
2356 additional_flags
|= conn
->fs_capabilities
;
2357 additional_flags
|= lp_parm_int(conn
->params
->service
,
2358 "share", "fake_fscaps",
2361 SIVAL(pdata
,0,FILE_CASE_PRESERVED_NAMES
|FILE_CASE_SENSITIVE_SEARCH
|
2362 FILE_SUPPORTS_OBJECT_IDS
|FILE_UNICODE_ON_DISK
|
2363 additional_flags
); /* FS ATTRIBUTES */
2365 SIVAL(pdata
,4,255); /* Max filename component length */
2366 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2367 and will think we can't do long filenames */
2368 status
= srvstr_push(pdata
, flags2
, pdata
+12, fstype
,
2369 PTR_DIFF(end_data
, pdata
+12),
2371 if (!NT_STATUS_IS_OK(status
)) {
2375 data_len
= 12 + len
;
2376 if (max_data_bytes
>= 16 && data_len
> max_data_bytes
) {
2377 /* the client only requested a portion of the
2379 data_len
= max_data_bytes
;
2380 status
= STATUS_BUFFER_OVERFLOW
;
2382 *fixed_portion
= 16;
2385 case SMB_QUERY_FS_LABEL_INFO
:
2386 case SMB_FS_LABEL_INFORMATION
:
2387 status
= srvstr_push(pdata
, flags2
, pdata
+4, vname
,
2388 PTR_DIFF(end_data
, pdata
+4), 0, &len
);
2389 if (!NT_STATUS_IS_OK(status
)) {
2396 case SMB_QUERY_FS_VOLUME_INFO
:
2397 case SMB_FS_VOLUME_INFORMATION
:
2398 put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER
,
2399 pdata
, &st
.st_ex_btime
);
2401 * Add volume serial number - hash of a combination of
2402 * the called hostname and the service name.
2404 serial
= generate_volume_serial_number(lp_sub
, snum
);
2405 SIVAL(pdata
,8,serial
);
2407 /* Max label len is 32 characters. */
2408 status
= srvstr_push(pdata
, flags2
, pdata
+18, vname
,
2409 PTR_DIFF(end_data
, pdata
+18),
2411 if (!NT_STATUS_IS_OK(status
)) {
2414 SIVAL(pdata
,12,len
);
2417 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO "
2418 "namelen = %d, vol=%s serv=%s "
2419 "serial=0x%04"PRIx32
"\n",
2420 (int)strlen(vname
),vname
,
2421 lp_servicename(talloc_tos(), lp_sub
, snum
),
2423 if (max_data_bytes
>= 24 && data_len
> max_data_bytes
) {
2424 /* the client only requested a portion of the
2426 data_len
= max_data_bytes
;
2427 status
= STATUS_BUFFER_OVERFLOW
;
2429 *fixed_portion
= 24;
2432 case SMB_QUERY_FS_SIZE_INFO
:
2433 case SMB_FS_SIZE_INFORMATION
:
2435 uint64_t dfree
,dsize
,bsize
,block_size
,sectors_per_unit
;
2437 df_ret
= get_dfree_info(conn
, &smb_fname
, &bsize
,
2439 if (df_ret
== (uint64_t)-1) {
2440 return map_nt_error_from_unix(errno
);
2442 block_size
= lp_block_size(snum
);
2443 if (bsize
< block_size
) {
2444 uint64_t factor
= block_size
/bsize
;
2449 if (bsize
> block_size
) {
2450 uint64_t factor
= bsize
/block_size
;
2455 sectors_per_unit
= bsize
/bytes_per_sector
;
2456 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2457 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
2458 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
2459 SBIG_UINT(pdata
,0,dsize
);
2460 SBIG_UINT(pdata
,8,dfree
);
2461 SIVAL(pdata
,16,sectors_per_unit
);
2462 SIVAL(pdata
,20,bytes_per_sector
);
2463 *fixed_portion
= 24;
2467 case SMB_FS_FULL_SIZE_INFORMATION
:
2469 uint64_t dfree
,dsize
,bsize
,block_size
,sectors_per_unit
;
2471 df_ret
= get_dfree_info(conn
, &smb_fname
, &bsize
,
2473 if (df_ret
== (uint64_t)-1) {
2474 return map_nt_error_from_unix(errno
);
2476 block_size
= lp_block_size(snum
);
2477 if (bsize
< block_size
) {
2478 uint64_t factor
= block_size
/bsize
;
2483 if (bsize
> block_size
) {
2484 uint64_t factor
= bsize
/block_size
;
2489 sectors_per_unit
= bsize
/bytes_per_sector
;
2490 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2491 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
2492 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
2493 SBIG_UINT(pdata
,0,dsize
); /* Total Allocation units. */
2494 SBIG_UINT(pdata
,8,dfree
); /* Caller available allocation units. */
2495 SBIG_UINT(pdata
,16,dfree
); /* Actual available allocation units. */
2496 SIVAL(pdata
,24,sectors_per_unit
); /* Sectors per allocation unit. */
2497 SIVAL(pdata
,28,bytes_per_sector
); /* Bytes per sector. */
2498 *fixed_portion
= 32;
2502 case SMB_QUERY_FS_DEVICE_INFO
:
2503 case SMB_FS_DEVICE_INFORMATION
:
2505 uint32_t characteristics
= FILE_DEVICE_IS_MOUNTED
;
2507 if (!CAN_WRITE(conn
)) {
2508 characteristics
|= FILE_READ_ONLY_DEVICE
;
2511 SIVAL(pdata
,0,FILE_DEVICE_DISK
); /* dev type */
2512 SIVAL(pdata
,4,characteristics
);
2517 #ifdef HAVE_SYS_QUOTAS
2518 case SMB_FS_QUOTA_INFORMATION
:
2520 * what we have to send --metze:
2522 * Unknown1: 24 NULL bytes
2523 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
2524 * Hard Quota Limit: 8 bytes seems like uint64_t or so
2525 * Quota Flags: 2 byte :
2526 * Unknown3: 6 NULL bytes
2530 * details for Quota Flags:
2532 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2533 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2534 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2535 * 0x0001 Enable Quotas: enable quota for this fs
2539 /* we need to fake up a fsp here,
2540 * because its not send in this call
2543 SMB_NTQUOTA_STRUCT quotas
;
2546 ZERO_STRUCT(quotas
);
2549 fsp
.fnum
= FNUM_FIELD_INVALID
;
2552 if (get_current_uid(conn
) != 0) {
2553 DEBUG(0,("get_user_quota: access_denied "
2554 "service [%s] user [%s]\n",
2555 lp_servicename(talloc_tos(), lp_sub
, SNUM(conn
)),
2556 conn
->session_info
->unix_info
->unix_name
));
2557 return NT_STATUS_ACCESS_DENIED
;
2560 status
= vfs_get_ntquota(&fsp
, SMB_USER_FS_QUOTA_TYPE
,
2562 if (!NT_STATUS_IS_OK(status
)) {
2563 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), lp_sub
, SNUM(conn
))));
2569 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
2570 lp_servicename(talloc_tos(), lp_sub
, SNUM(conn
))));
2572 /* Unknown1 24 NULL bytes*/
2573 SBIG_UINT(pdata
,0,(uint64_t)0);
2574 SBIG_UINT(pdata
,8,(uint64_t)0);
2575 SBIG_UINT(pdata
,16,(uint64_t)0);
2577 /* Default Soft Quota 8 bytes */
2578 SBIG_UINT(pdata
,24,quotas
.softlim
);
2580 /* Default Hard Quota 8 bytes */
2581 SBIG_UINT(pdata
,32,quotas
.hardlim
);
2583 /* Quota flag 2 bytes */
2584 SSVAL(pdata
,40,quotas
.qflags
);
2586 /* Unknown3 6 NULL bytes */
2592 #endif /* HAVE_SYS_QUOTAS */
2593 case SMB_FS_OBJECTID_INFORMATION
:
2595 unsigned char objid
[16];
2596 struct smb_extended_info extended_info
;
2597 memcpy(pdata
,create_volume_objectid(conn
, objid
),16);
2598 samba_extended_info_version (&extended_info
);
2599 SIVAL(pdata
,16,extended_info
.samba_magic
);
2600 SIVAL(pdata
,20,extended_info
.samba_version
);
2601 SIVAL(pdata
,24,extended_info
.samba_subversion
);
2602 SBIG_UINT(pdata
,28,extended_info
.samba_gitcommitdate
);
2603 memcpy(pdata
+36,extended_info
.samba_version_string
,28);
2608 case SMB_FS_SECTOR_SIZE_INFORMATION
:
2612 * These values match a physical Windows Server 2012
2613 * share backed by NTFS atop spinning rust.
2615 DEBUG(5, ("SMB_FS_SECTOR_SIZE_INFORMATION:"));
2616 /* logical_bytes_per_sector */
2617 SIVAL(pdata
, 0, bytes_per_sector
);
2618 /* phys_bytes_per_sector_atomic */
2619 SIVAL(pdata
, 4, bytes_per_sector
);
2620 /* phys_bytes_per_sector_perf */
2621 SIVAL(pdata
, 8, bytes_per_sector
);
2622 /* fs_effective_phys_bytes_per_sector_atomic */
2623 SIVAL(pdata
, 12, bytes_per_sector
);
2625 SIVAL(pdata
, 16, SSINFO_FLAGS_ALIGNED_DEVICE
2626 | SSINFO_FLAGS_PARTITION_ALIGNED_ON_DEVICE
);
2627 /* byte_off_sector_align */
2628 SIVAL(pdata
, 20, 0);
2629 /* byte_off_partition_align */
2630 SIVAL(pdata
, 24, 0);
2631 *fixed_portion
= 28;
2636 #if defined(WITH_SMB1SERVER)
2638 * Query the version and capabilities of the CIFS UNIX extensions
2642 case SMB_QUERY_CIFS_UNIX_INFO
:
2644 bool large_write
= lp_min_receive_file_size() &&
2645 !smb1_srv_is_signing_active(xconn
);
2646 bool large_read
= !smb1_srv_is_signing_active(xconn
);
2647 int encrypt_caps
= 0;
2649 if (!lp_smb1_unix_extensions()) {
2650 return NT_STATUS_INVALID_LEVEL
;
2653 switch (conn
->encrypt_level
) {
2654 case SMB_SIGNING_OFF
:
2657 case SMB_SIGNING_DESIRED
:
2658 case SMB_SIGNING_IF_REQUIRED
:
2659 case SMB_SIGNING_DEFAULT
:
2660 encrypt_caps
= CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP
;
2662 case SMB_SIGNING_REQUIRED
:
2663 encrypt_caps
= CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP
|
2664 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP
;
2665 large_write
= false;
2671 SSVAL(pdata
,0,CIFS_UNIX_MAJOR_VERSION
);
2672 SSVAL(pdata
,2,CIFS_UNIX_MINOR_VERSION
);
2674 /* We have POSIX ACLs, pathname, encryption,
2675 * large read/write, and locking capability. */
2677 SBIG_UINT(pdata
,4,((uint64_t)(
2678 CIFS_UNIX_POSIX_ACLS_CAP
|
2679 CIFS_UNIX_POSIX_PATHNAMES_CAP
|
2680 CIFS_UNIX_FCNTL_LOCKS_CAP
|
2681 CIFS_UNIX_EXTATTR_CAP
|
2682 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP
|
2684 (large_read
? CIFS_UNIX_LARGE_READ_CAP
: 0) |
2686 CIFS_UNIX_LARGE_WRITE_CAP
: 0))));
2691 case SMB_QUERY_POSIX_FS_INFO
:
2692 case SMB2_FS_POSIX_INFORMATION_INTERNAL
:
2695 struct vfs_statvfs_struct svfs
;
2697 if (!fsinfo_unix_valid_level(conn
, info_level
)) {
2698 return NT_STATUS_INVALID_LEVEL
;
2701 rc
= SMB_VFS_STATVFS(conn
, &smb_fname
, &svfs
);
2705 SIVAL(pdata
,0,svfs
.OptimalTransferSize
);
2706 SIVAL(pdata
,4,svfs
.BlockSize
);
2707 SBIG_UINT(pdata
,8,svfs
.TotalBlocks
);
2708 SBIG_UINT(pdata
,16,svfs
.BlocksAvail
);
2709 SBIG_UINT(pdata
,24,svfs
.UserBlocksAvail
);
2710 SBIG_UINT(pdata
,32,svfs
.TotalFileNodes
);
2711 SBIG_UINT(pdata
,40,svfs
.FreeFileNodes
);
2712 SBIG_UINT(pdata
,48,svfs
.FsIdentifier
);
2713 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
2715 } else if (rc
== EOPNOTSUPP
) {
2716 return NT_STATUS_INVALID_LEVEL
;
2717 #endif /* EOPNOTSUPP */
2719 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(talloc_tos(), lp_sub
, SNUM(conn
))));
2720 return NT_STATUS_DOS(ERRSRV
, ERRerror
);
2725 case SMB_QUERY_POSIX_WHOAMI
:
2731 if (!lp_smb1_unix_extensions()) {
2732 return NT_STATUS_INVALID_LEVEL
;
2735 if (max_data_bytes
< 40) {
2736 return NT_STATUS_BUFFER_TOO_SMALL
;
2739 if (security_session_user_level(conn
->session_info
, NULL
) < SECURITY_USER
) {
2740 flags
|= SMB_WHOAMI_GUEST
;
2743 /* NOTE: 8 bytes for UID/GID, irrespective of native
2744 * platform size. This matches
2745 * SMB_QUERY_FILE_UNIX_BASIC and friends.
2747 data_len
= 4 /* flags */
2754 + 4 /* pad/reserved */
2755 + (conn
->session_info
->unix_token
->ngroups
* 8)
2757 + (conn
->session_info
->security_token
->num_sids
*
2761 SIVAL(pdata
, 0, flags
);
2762 SIVAL(pdata
, 4, SMB_WHOAMI_MASK
);
2764 (uint64_t)conn
->session_info
->unix_token
->uid
);
2765 SBIG_UINT(pdata
, 16,
2766 (uint64_t)conn
->session_info
->unix_token
->gid
);
2769 if (data_len
>= max_data_bytes
) {
2770 /* Potential overflow, skip the GIDs and SIDs. */
2772 SIVAL(pdata
, 24, 0); /* num_groups */
2773 SIVAL(pdata
, 28, 0); /* num_sids */
2774 SIVAL(pdata
, 32, 0); /* num_sid_bytes */
2775 SIVAL(pdata
, 36, 0); /* reserved */
2781 SIVAL(pdata
, 24, conn
->session_info
->unix_token
->ngroups
);
2782 SIVAL(pdata
, 28, conn
->session_info
->security_token
->num_sids
);
2784 /* We walk the SID list twice, but this call is fairly
2785 * infrequent, and I don't expect that it's performance
2786 * sensitive -- jpeach
2788 for (i
= 0, sid_bytes
= 0;
2789 i
< conn
->session_info
->security_token
->num_sids
; ++i
) {
2790 sid_bytes
+= ndr_size_dom_sid(
2791 &conn
->session_info
->security_token
->sids
[i
],
2795 /* SID list byte count */
2796 SIVAL(pdata
, 32, sid_bytes
);
2798 /* 4 bytes pad/reserved - must be zero */
2799 SIVAL(pdata
, 36, 0);
2803 for (i
= 0; i
< conn
->session_info
->unix_token
->ngroups
; ++i
) {
2804 SBIG_UINT(pdata
, data_len
,
2805 (uint64_t)conn
->session_info
->unix_token
->groups
[i
]);
2811 i
< conn
->session_info
->security_token
->num_sids
; ++i
) {
2812 int sid_len
= ndr_size_dom_sid(
2813 &conn
->session_info
->security_token
->sids
[i
],
2816 sid_linearize((uint8_t *)(pdata
+ data_len
),
2818 &conn
->session_info
->security_token
->sids
[i
]);
2819 data_len
+= sid_len
;
2825 case SMB_MAC_QUERY_FS_INFO
:
2827 * Thursby MAC extension... ONLY on NTFS filesystems
2828 * once we do streams then we don't need this
2830 if (strequal(lp_fstype(SNUM(conn
)),"NTFS")) {
2832 SIVAL(pdata
,84,0x100); /* Don't support mac... */
2838 return NT_STATUS_INVALID_LEVEL
;
2841 *ret_data_len
= data_len
;
2845 NTSTATUS
smb_set_fsquota(connection_struct
*conn
,
2846 struct smb_request
*req
,
2848 const DATA_BLOB
*qdata
)
2850 const struct loadparm_substitution
*lp_sub
=
2851 loadparm_s3_global_substitution();
2853 SMB_NTQUOTA_STRUCT quotas
;
2855 ZERO_STRUCT(quotas
);
2858 if ((get_current_uid(conn
) != 0) || !CAN_WRITE(conn
)) {
2859 DEBUG(3, ("set_fsquota: access_denied service [%s] user [%s]\n",
2860 lp_servicename(talloc_tos(), lp_sub
, SNUM(conn
)),
2861 conn
->session_info
->unix_info
->unix_name
));
2862 return NT_STATUS_ACCESS_DENIED
;
2865 if (!check_fsp_ntquota_handle(conn
, req
,
2867 DEBUG(1, ("set_fsquota: no valid QUOTA HANDLE\n"));
2868 return NT_STATUS_INVALID_HANDLE
;
2871 /* note: normally there're 48 bytes,
2872 * but we didn't use the last 6 bytes for now
2875 if (qdata
->length
< 42) {
2876 DEBUG(0,("set_fsquota: requires total_data(%u) >= 42 bytes!\n",
2877 (unsigned int)qdata
->length
));
2878 return NT_STATUS_INVALID_PARAMETER
;
2881 /* unknown_1 24 NULL bytes in pdata*/
2883 /* the soft quotas 8 bytes (uint64_t)*/
2884 quotas
.softlim
= BVAL(qdata
->data
,24);
2886 /* the hard quotas 8 bytes (uint64_t)*/
2887 quotas
.hardlim
= BVAL(qdata
->data
,32);
2889 /* quota_flags 2 bytes **/
2890 quotas
.qflags
= SVAL(qdata
->data
,40);
2892 /* unknown_2 6 NULL bytes follow*/
2894 /* now set the quotas */
2895 if (vfs_set_ntquota(fsp
, SMB_USER_FS_QUOTA_TYPE
, NULL
, "as
)!=0) {
2896 DEBUG(1, ("vfs_set_ntquota() failed for service [%s]\n",
2897 lp_servicename(talloc_tos(), lp_sub
, SNUM(conn
))));
2898 status
= map_nt_error_from_unix(errno
);
2900 status
= NT_STATUS_OK
;
2905 NTSTATUS
smbd_do_setfsinfo(connection_struct
*conn
,
2906 struct smb_request
*req
,
2907 TALLOC_CTX
*mem_ctx
,
2908 uint16_t info_level
,
2910 const DATA_BLOB
*pdata
)
2912 switch (info_level
) {
2913 case SMB_FS_QUOTA_INFORMATION
:
2915 return smb_set_fsquota(conn
,
2924 return NT_STATUS_INVALID_LEVEL
;
2927 #if defined(HAVE_POSIX_ACLS)
2928 /****************************************************************************
2929 Utility function to count the number of entries in a POSIX acl.
2930 ****************************************************************************/
2932 static unsigned int count_acl_entries(connection_struct
*conn
, SMB_ACL_T posix_acl
)
2934 unsigned int ace_count
= 0;
2935 int entry_id
= SMB_ACL_FIRST_ENTRY
;
2936 SMB_ACL_ENTRY_T entry
;
2938 while ( posix_acl
&& (sys_acl_get_entry(posix_acl
, entry_id
, &entry
) == 1)) {
2940 if (entry_id
== SMB_ACL_FIRST_ENTRY
) {
2941 entry_id
= SMB_ACL_NEXT_ENTRY
;
2948 /****************************************************************************
2949 Utility function to marshall a POSIX acl into wire format.
2950 ****************************************************************************/
2952 static bool marshall_posix_acl(connection_struct
*conn
, char *pdata
, SMB_STRUCT_STAT
*pst
, SMB_ACL_T posix_acl
)
2954 int entry_id
= SMB_ACL_FIRST_ENTRY
;
2955 SMB_ACL_ENTRY_T entry
;
2957 while ( posix_acl
&& (sys_acl_get_entry(posix_acl
, entry_id
, &entry
) == 1)) {
2958 SMB_ACL_TAG_T tagtype
;
2959 SMB_ACL_PERMSET_T permset
;
2960 unsigned char perms
= 0;
2961 unsigned int own_grp
;
2964 if (entry_id
== SMB_ACL_FIRST_ENTRY
) {
2965 entry_id
= SMB_ACL_NEXT_ENTRY
;
2968 if (sys_acl_get_tag_type(entry
, &tagtype
) == -1) {
2969 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
2973 if (sys_acl_get_permset(entry
, &permset
) == -1) {
2974 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
2978 perms
|= (sys_acl_get_perm(permset
, SMB_ACL_READ
) ? SMB_POSIX_ACL_READ
: 0);
2979 perms
|= (sys_acl_get_perm(permset
, SMB_ACL_WRITE
) ? SMB_POSIX_ACL_WRITE
: 0);
2980 perms
|= (sys_acl_get_perm(permset
, SMB_ACL_EXECUTE
) ? SMB_POSIX_ACL_EXECUTE
: 0);
2982 SCVAL(pdata
,1,perms
);
2985 case SMB_ACL_USER_OBJ
:
2986 SCVAL(pdata
,0,SMB_POSIX_ACL_USER_OBJ
);
2987 own_grp
= (unsigned int)pst
->st_ex_uid
;
2988 SIVAL(pdata
,2,own_grp
);
2993 uid_t
*puid
= (uid_t
*)sys_acl_get_qualifier(entry
);
2995 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
2998 own_grp
= (unsigned int)*puid
;
2999 SCVAL(pdata
,0,SMB_POSIX_ACL_USER
);
3000 SIVAL(pdata
,2,own_grp
);
3004 case SMB_ACL_GROUP_OBJ
:
3005 SCVAL(pdata
,0,SMB_POSIX_ACL_GROUP_OBJ
);
3006 own_grp
= (unsigned int)pst
->st_ex_gid
;
3007 SIVAL(pdata
,2,own_grp
);
3012 gid_t
*pgid
= (gid_t
*)sys_acl_get_qualifier(entry
);
3014 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3017 own_grp
= (unsigned int)*pgid
;
3018 SCVAL(pdata
,0,SMB_POSIX_ACL_GROUP
);
3019 SIVAL(pdata
,2,own_grp
);
3024 SCVAL(pdata
,0,SMB_POSIX_ACL_MASK
);
3025 SIVAL(pdata
,2,0xFFFFFFFF);
3026 SIVAL(pdata
,6,0xFFFFFFFF);
3029 SCVAL(pdata
,0,SMB_POSIX_ACL_OTHER
);
3030 SIVAL(pdata
,2,0xFFFFFFFF);
3031 SIVAL(pdata
,6,0xFFFFFFFF);
3034 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3037 pdata
+= SMB_POSIX_ACL_ENTRY_SIZE
;
3044 /****************************************************************************
3045 Store the FILE_UNIX_BASIC info.
3046 ****************************************************************************/
3048 char *store_file_unix_basic(connection_struct
*conn
,
3051 const SMB_STRUCT_STAT
*psbuf
)
3055 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3056 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf
->st_ex_mode
));
3058 SOFF_T(pdata
,0,get_file_size_stat(psbuf
)); /* File size 64 Bit */
3061 SOFF_T(pdata
,0,SMB_VFS_GET_ALLOC_SIZE(conn
,fsp
,psbuf
)); /* Number of bytes used on disk - 64 Bit */
3064 put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER
, pdata
, &psbuf
->st_ex_ctime
); /* Change Time 64 Bit */
3065 put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER
,pdata
+8, &psbuf
->st_ex_atime
); /* Last access time 64 Bit */
3066 put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER
, pdata
+16, &psbuf
->st_ex_mtime
); /* Last modification time 64 Bit */
3069 SIVAL(pdata
,0,psbuf
->st_ex_uid
); /* user id for the owner */
3073 SIVAL(pdata
,0,psbuf
->st_ex_gid
); /* group id of owner */
3077 SIVAL(pdata
,0,unix_filetype(psbuf
->st_ex_mode
));
3080 if (S_ISBLK(psbuf
->st_ex_mode
) || S_ISCHR(psbuf
->st_ex_mode
)) {
3081 devno
= psbuf
->st_ex_rdev
;
3083 devno
= psbuf
->st_ex_dev
;
3086 SIVAL(pdata
,0,unix_dev_major(devno
)); /* Major device number if type is device */
3090 SIVAL(pdata
,0,unix_dev_minor(devno
)); /* Minor device number if type is device */
3094 SINO_T_VAL(pdata
, 0, psbuf
->st_ex_ino
); /* inode number */
3097 SIVAL(pdata
,0, unix_perms_to_wire(psbuf
->st_ex_mode
)); /* Standard UNIX file permissions */
3101 SIVAL(pdata
,0,psbuf
->st_ex_nlink
); /* number of hard links */
3108 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3109 * the chflags(2) (or equivalent) flags.
3111 * XXX: this really should be behind the VFS interface. To do this, we would
3112 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3113 * Each VFS module could then implement its own mapping as appropriate for the
3114 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3116 static const struct {unsigned stat_fflag
; unsigned smb_fflag
;}
3120 { UF_NODUMP
, EXT_DO_NOT_BACKUP
},
3124 { UF_IMMUTABLE
, EXT_IMMUTABLE
},
3128 { UF_APPEND
, EXT_OPEN_APPEND_ONLY
},
3132 { UF_HIDDEN
, EXT_HIDDEN
},
3135 /* Do not remove. We need to guarantee that this array has at least one
3136 * entry to build on HP-UX.
3142 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT
*psbuf
,
3143 uint32_t *smb_fflags
, uint32_t *smb_fmask
)
3147 for (i
= 0; i
< ARRAY_SIZE(info2_flags_map
); ++i
) {
3148 *smb_fmask
|= info2_flags_map
[i
].smb_fflag
;
3149 if (psbuf
->st_ex_flags
& info2_flags_map
[i
].stat_fflag
) {
3150 *smb_fflags
|= info2_flags_map
[i
].smb_fflag
;
3155 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT
*psbuf
,
3156 const uint32_t smb_fflags
,
3157 const uint32_t smb_fmask
,
3160 uint32_t max_fmask
= 0;
3163 *stat_fflags
= psbuf
->st_ex_flags
;
3165 /* For each flags requested in smb_fmask, check the state of the
3166 * corresponding flag in smb_fflags and set or clear the matching
3170 for (i
= 0; i
< ARRAY_SIZE(info2_flags_map
); ++i
) {
3171 max_fmask
|= info2_flags_map
[i
].smb_fflag
;
3172 if (smb_fmask
& info2_flags_map
[i
].smb_fflag
) {
3173 if (smb_fflags
& info2_flags_map
[i
].smb_fflag
) {
3174 *stat_fflags
|= info2_flags_map
[i
].stat_fflag
;
3176 *stat_fflags
&= ~info2_flags_map
[i
].stat_fflag
;
3181 /* If smb_fmask is asking to set any bits that are not supported by
3182 * our flag mappings, we should fail.
3184 if ((smb_fmask
& max_fmask
) != smb_fmask
) {
3192 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
3193 * of file flags and birth (create) time.
3195 char *store_file_unix_basic_info2(connection_struct
*conn
,
3198 const SMB_STRUCT_STAT
*psbuf
)
3200 uint32_t file_flags
= 0;
3201 uint32_t flags_mask
= 0;
3203 pdata
= store_file_unix_basic(conn
, pdata
, fsp
, psbuf
);
3205 /* Create (birth) time 64 bit */
3206 put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER
,pdata
, &psbuf
->st_ex_btime
);
3209 map_info2_flags_from_sbuf(psbuf
, &file_flags
, &flags_mask
);
3210 SIVAL(pdata
, 0, file_flags
); /* flags */
3211 SIVAL(pdata
, 4, flags_mask
); /* mask */
3217 static NTSTATUS
marshall_stream_info(unsigned int num_streams
,
3218 const struct stream_struct
*streams
,
3220 unsigned int max_data_bytes
,
3221 unsigned int *data_size
)
3224 unsigned int ofs
= 0;
3226 if (max_data_bytes
< 32) {
3227 return NT_STATUS_INFO_LENGTH_MISMATCH
;
3230 for (i
= 0; i
< num_streams
; i
++) {
3231 unsigned int next_offset
;
3233 smb_ucs2_t
*namebuf
;
3235 if (!push_ucs2_talloc(talloc_tos(), &namebuf
,
3236 streams
[i
].name
, &namelen
) ||
3239 return NT_STATUS_INVALID_PARAMETER
;
3243 * name_buf is now null-terminated, we need to marshall as not
3250 * We cannot overflow ...
3252 if ((ofs
+ 24 + namelen
) > max_data_bytes
) {
3253 DEBUG(10, ("refusing to overflow reply at stream %u\n",
3255 TALLOC_FREE(namebuf
);
3256 return STATUS_BUFFER_OVERFLOW
;
3259 SIVAL(data
, ofs
+4, namelen
);
3260 SOFF_T(data
, ofs
+8, streams
[i
].size
);
3261 SOFF_T(data
, ofs
+16, streams
[i
].alloc_size
);
3262 memcpy(data
+ofs
+24, namebuf
, namelen
);
3263 TALLOC_FREE(namebuf
);
3265 next_offset
= ofs
+ 24 + namelen
;
3267 if (i
== num_streams
-1) {
3268 SIVAL(data
, ofs
, 0);
3271 unsigned int align
= ndr_align_size(next_offset
, 8);
3273 if ((next_offset
+ align
) > max_data_bytes
) {
3274 DEBUG(10, ("refusing to overflow align "
3275 "reply at stream %u\n",
3277 TALLOC_FREE(namebuf
);
3278 return STATUS_BUFFER_OVERFLOW
;
3281 memset(data
+next_offset
, 0, align
);
3282 next_offset
+= align
;
3284 SIVAL(data
, ofs
, next_offset
- ofs
);
3291 DEBUG(10, ("max_data: %u, data_size: %u\n", max_data_bytes
, ofs
));
3295 return NT_STATUS_OK
;
3298 static NTSTATUS
smb_unix_read_symlink(connection_struct
*conn
,
3299 struct smb_request
*req
,
3300 struct smb_filename
*smb_fname
,
3302 unsigned int data_size_in
,
3303 unsigned int *pdata_size_out
)
3308 struct smb_filename
*parent_fname
= NULL
;
3309 struct smb_filename
*base_name
= NULL
;
3311 char *buffer
= talloc_array(talloc_tos(), char, PATH_MAX
+1);
3314 return NT_STATUS_NO_MEMORY
;
3317 DBG_DEBUG("SMB_QUERY_FILE_UNIX_LINK for file %s\n",
3318 smb_fname_str_dbg(smb_fname
));
3320 if(!S_ISLNK(smb_fname
->st
.st_ex_mode
)) {
3321 TALLOC_FREE(buffer
);
3322 return NT_STATUS_DOS(ERRSRV
, ERRbadlink
);
3325 status
= parent_pathref(talloc_tos(),
3330 if (!NT_STATUS_IS_OK(status
)) {
3331 TALLOC_FREE(buffer
);
3335 link_len
= SMB_VFS_READLINKAT(conn
,
3341 TALLOC_FREE(parent_fname
);
3343 if (link_len
== -1) {
3344 TALLOC_FREE(buffer
);
3345 return map_nt_error_from_unix(errno
);
3348 buffer
[link_len
] = 0;
3349 status
= srvstr_push(pdata
,
3356 TALLOC_FREE(buffer
);
3357 if (!NT_STATUS_IS_OK(status
)) {
3360 *pdata_size_out
= len
;
3362 return NT_STATUS_OK
;
3365 #if defined(HAVE_POSIX_ACLS)
3366 static NTSTATUS
smb_query_posix_acl(connection_struct
*conn
,
3367 struct smb_request
*req
,
3369 struct smb_filename
*smb_fname
,
3371 unsigned int data_size_in
,
3372 unsigned int *pdata_size_out
)
3374 SMB_ACL_T file_acl
= NULL
;
3375 SMB_ACL_T def_acl
= NULL
;
3376 uint16_t num_file_acls
= 0;
3377 uint16_t num_def_acls
= 0;
3378 unsigned int size_needed
= 0;
3381 bool close_fsp
= false;
3384 * Ensure we always operate on a file descriptor, not just
3387 if (fsp
== NULL
|| !fsp
->fsp_flags
.is_fsa
) {
3388 uint32_t access_mask
= SEC_STD_READ_CONTROL
|
3389 FILE_READ_ATTRIBUTES
|
3390 FILE_WRITE_ATTRIBUTES
;
3392 status
= get_posix_fsp(conn
,
3398 if (!NT_STATUS_IS_OK(status
)) {
3404 SMB_ASSERT(fsp
!= NULL
);
3406 status
= refuse_symlink_fsp(fsp
);
3407 if (!NT_STATUS_IS_OK(status
)) {
3411 file_acl
= SMB_VFS_SYS_ACL_GET_FD(fsp
, SMB_ACL_TYPE_ACCESS
,
3414 if (file_acl
== NULL
&& no_acl_syscall_error(errno
)) {
3415 DBG_INFO("ACLs not implemented on "
3416 "filesystem containing %s\n",
3418 status
= NT_STATUS_NOT_IMPLEMENTED
;
3422 if (S_ISDIR(fsp
->fsp_name
->st
.st_ex_mode
)) {
3424 * We can only have default POSIX ACLs on
3427 if (!fsp
->fsp_flags
.is_directory
) {
3428 DBG_INFO("Non-directory open %s\n",
3430 status
= NT_STATUS_INVALID_HANDLE
;
3433 def_acl
= SMB_VFS_SYS_ACL_GET_FD(fsp
,
3434 SMB_ACL_TYPE_DEFAULT
,
3436 def_acl
= free_empty_sys_acl(conn
, def_acl
);
3439 num_file_acls
= count_acl_entries(conn
, file_acl
);
3440 num_def_acls
= count_acl_entries(conn
, def_acl
);
3443 if (num_file_acls
+ num_def_acls
< num_file_acls
) {
3444 status
= NT_STATUS_INVALID_PARAMETER
;
3448 size_needed
= num_file_acls
+ num_def_acls
;
3451 * (size_needed * SMB_POSIX_ACL_ENTRY_SIZE) must be less
3452 * than UINT_MAX, so check by division.
3454 if (size_needed
> (UINT_MAX
/SMB_POSIX_ACL_ENTRY_SIZE
)) {
3455 status
= NT_STATUS_INVALID_PARAMETER
;
3459 size_needed
= size_needed
*SMB_POSIX_ACL_ENTRY_SIZE
;
3460 if (size_needed
+ SMB_POSIX_ACL_HEADER_SIZE
< size_needed
) {
3461 status
= NT_STATUS_INVALID_PARAMETER
;
3464 size_needed
+= SMB_POSIX_ACL_HEADER_SIZE
;
3466 if ( data_size_in
< size_needed
) {
3467 DBG_INFO("data_size too small (%u) need %u\n",
3470 status
= NT_STATUS_BUFFER_TOO_SMALL
;
3474 SSVAL(pdata
,0,SMB_POSIX_ACL_VERSION
);
3475 SSVAL(pdata
,2,num_file_acls
);
3476 SSVAL(pdata
,4,num_def_acls
);
3477 pdata
+= SMB_POSIX_ACL_HEADER_SIZE
;
3479 ok
= marshall_posix_acl(conn
,
3484 status
= NT_STATUS_INTERNAL_ERROR
;
3487 pdata
+= (num_file_acls
*SMB_POSIX_ACL_ENTRY_SIZE
);
3489 ok
= marshall_posix_acl(conn
,
3494 status
= NT_STATUS_INTERNAL_ERROR
;
3498 *pdata_size_out
= size_needed
;
3499 status
= NT_STATUS_OK
;
3505 * Ensure the stat struct in smb_fname is up to
3506 * date. Structure copy.
3508 smb_fname
->st
= fsp
->fsp_name
->st
;
3509 (void)close_file_free(req
, &fsp
, NORMAL_CLOSE
);
3512 TALLOC_FREE(file_acl
);
3513 TALLOC_FREE(def_acl
);
3518 NTSTATUS
smbd_do_qfilepathinfo(connection_struct
*conn
,
3519 TALLOC_CTX
*mem_ctx
,
3520 struct smb_request
*req
,
3521 uint16_t info_level
,
3523 struct smb_filename
*smb_fname
,
3524 bool delete_pending
,
3525 struct timespec write_time_ts
,
3526 struct ea_list
*ea_list
,
3527 int lock_data_count
,
3530 unsigned int max_data_bytes
,
3531 size_t *fixed_portion
,
3533 unsigned int *pdata_size
)
3535 char *pdata
= *ppdata
;
3536 char *dstart
, *dend
;
3537 unsigned int data_size
;
3538 struct timespec create_time_ts
, mtime_ts
, atime_ts
, ctime_ts
;
3539 time_t create_time
, mtime
, atime
, c_time
;
3540 SMB_STRUCT_STAT
*psbuf
= NULL
;
3541 SMB_STRUCT_STAT
*base_sp
= NULL
;
3548 uint64_t file_size
= 0;
3550 uint64_t allocation_size
= 0;
3551 uint64_t file_id
= 0;
3552 uint32_t access_mask
= 0;
3555 if (INFO_LEVEL_IS_UNIX(info_level
)) {
3558 if (lp_smb1_unix_extensions() && req
->posix_pathnames
) {
3559 DBG_DEBUG("SMB1 unix extensions activated\n");
3563 if (lp_smb3_unix_extensions() &&
3565 (fsp
->posix_flags
& FSP_POSIX_FLAGS_OPEN
)) {
3566 DBG_DEBUG("SMB2 posix open\n");
3571 return NT_STATUS_INVALID_LEVEL
;
3575 DEBUG(5,("smbd_do_qfilepathinfo: %s (%s) level=%d max_data=%u\n",
3576 smb_fname_str_dbg(smb_fname
),
3578 info_level
, max_data_bytes
));
3581 * In case of querying a symlink in POSIX context,
3582 * fsp will be NULL. fdos_mode() deals with it.
3585 smb_fname
= fsp
->fsp_name
;
3587 mode
= fdos_mode(fsp
);
3588 psbuf
= &smb_fname
->st
;
3591 base_sp
= fsp
->base_fsp
?
3592 &fsp
->base_fsp
->fsp_name
->st
:
3595 base_sp
= &smb_fname
->st
;
3598 nlink
= psbuf
->st_ex_nlink
;
3600 if (nlink
&& (mode
&FILE_ATTRIBUTE_DIRECTORY
)) {
3604 if ((nlink
> 0) && delete_pending
) {
3608 if (max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
< max_data_bytes
) {
3609 return NT_STATUS_INVALID_PARAMETER
;
3612 data_size
= max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
;
3613 *ppdata
= (char *)SMB_REALLOC(*ppdata
, data_size
);
3614 if (*ppdata
== NULL
) {
3615 return NT_STATUS_NO_MEMORY
;
3619 dend
= dstart
+ data_size
- 1;
3621 if (!is_omit_timespec(&write_time_ts
) &&
3622 !INFO_LEVEL_IS_UNIX(info_level
))
3624 update_stat_ex_mtime(psbuf
, write_time_ts
);
3627 create_time_ts
= get_create_timespec(conn
, fsp
, smb_fname
);
3628 mtime_ts
= psbuf
->st_ex_mtime
;
3629 atime_ts
= psbuf
->st_ex_atime
;
3630 ctime_ts
= get_change_timespec(conn
, fsp
, smb_fname
);
3632 if (lp_dos_filetime_resolution(SNUM(conn
))) {
3633 dos_filetime_timespec(&create_time_ts
);
3634 dos_filetime_timespec(&mtime_ts
);
3635 dos_filetime_timespec(&atime_ts
);
3636 dos_filetime_timespec(&ctime_ts
);
3639 create_time
= convert_timespec_to_time_t(create_time_ts
);
3640 mtime
= convert_timespec_to_time_t(mtime_ts
);
3641 atime
= convert_timespec_to_time_t(atime_ts
);
3642 c_time
= convert_timespec_to_time_t(ctime_ts
);
3644 p
= strrchr_m(smb_fname
->base_name
,'/');
3646 base_name
= smb_fname
->base_name
;
3650 /* NT expects the name to be in an exact form of the *full*
3651 filename. See the trans2 torture test */
3652 if (ISDOT(base_name
)) {
3653 dos_fname
= talloc_strdup(mem_ctx
, "\\");
3655 return NT_STATUS_NO_MEMORY
;
3658 dos_fname
= talloc_asprintf(mem_ctx
,
3660 smb_fname
->base_name
);
3662 return NT_STATUS_NO_MEMORY
;
3664 if (is_named_stream(smb_fname
)) {
3665 dos_fname
= talloc_asprintf(dos_fname
, "%s",
3666 smb_fname
->stream_name
);
3668 return NT_STATUS_NO_MEMORY
;
3672 string_replace(dos_fname
, '/', '\\');
3675 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
, fsp
, psbuf
);
3677 if (fsp
== NULL
|| !fsp
->fsp_flags
.is_fsa
) {
3678 /* Do we have this path open ? */
3680 struct file_id fileid
= vfs_file_id_from_sbuf(conn
, psbuf
);
3681 fsp1
= file_find_di_first(conn
->sconn
, fileid
, true);
3682 if (fsp1
&& fsp1
->initial_allocation_size
) {
3683 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
, fsp1
, psbuf
);
3687 if (!(mode
& FILE_ATTRIBUTE_DIRECTORY
)) {
3688 file_size
= get_file_size_stat(psbuf
);
3692 pos
= fh_get_position_information(fsp
->fh
);
3696 access_mask
= fsp
->access_mask
;
3698 /* GENERIC_EXECUTE mapping from Windows */
3699 access_mask
= 0x12019F;
3702 /* This should be an index number - looks like
3705 I think this causes us to fail the IFSKIT
3706 BasicFileInformationTest. -tpot */
3707 file_id
= SMB_VFS_FS_FILE_ID(conn
, base_sp
);
3711 switch (info_level
) {
3712 case SMB_INFO_STANDARD
:
3713 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
3715 srv_put_dos_date2(pdata
,l1_fdateCreation
,create_time
);
3716 srv_put_dos_date2(pdata
,l1_fdateLastAccess
,atime
);
3717 srv_put_dos_date2(pdata
,l1_fdateLastWrite
,mtime
); /* write time */
3718 SIVAL(pdata
,l1_cbFile
,(uint32_t)file_size
);
3719 SIVAL(pdata
,l1_cbFileAlloc
,(uint32_t)allocation_size
);
3720 SSVAL(pdata
,l1_attrFile
,mode
);
3723 case SMB_INFO_QUERY_EA_SIZE
:
3725 unsigned int ea_size
=
3726 estimate_ea_size(smb_fname
->fsp
);
3727 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
3729 srv_put_dos_date2(pdata
,0,create_time
);
3730 srv_put_dos_date2(pdata
,4,atime
);
3731 srv_put_dos_date2(pdata
,8,mtime
); /* write time */
3732 SIVAL(pdata
,12,(uint32_t)file_size
);
3733 SIVAL(pdata
,16,(uint32_t)allocation_size
);
3734 SSVAL(pdata
,20,mode
);
3735 SIVAL(pdata
,22,ea_size
);
3739 case SMB_INFO_IS_NAME_VALID
:
3740 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
3742 /* os/2 needs this ? really ?*/
3743 return NT_STATUS_DOS(ERRDOS
, ERRbadfunc
);
3745 /* This is only reached for qpathinfo */
3749 case SMB_INFO_QUERY_EAS_FROM_LIST
:
3751 size_t total_ea_len
= 0;
3752 struct ea_list
*ea_file_list
= NULL
;
3753 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
3756 get_ea_list_from_fsp(mem_ctx
,
3758 &total_ea_len
, &ea_file_list
);
3759 if (!NT_STATUS_IS_OK(status
)) {
3763 ea_list
= ea_list_union(ea_list
, ea_file_list
, &total_ea_len
);
3765 if (!ea_list
|| (total_ea_len
> data_size
)) {
3767 SIVAL(pdata
,0,4); /* EA List Length must be set to 4 if no EA's. */
3771 data_size
= fill_ea_buffer(mem_ctx
, pdata
, data_size
, conn
, ea_list
);
3775 case SMB_INFO_QUERY_ALL_EAS
:
3777 /* We have data_size bytes to put EA's into. */
3778 size_t total_ea_len
= 0;
3779 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
3781 status
= get_ea_list_from_fsp(mem_ctx
,
3783 &total_ea_len
, &ea_list
);
3784 if (!NT_STATUS_IS_OK(status
)) {
3788 if (!ea_list
|| (total_ea_len
> data_size
)) {
3790 SIVAL(pdata
,0,4); /* EA List Length must be set to 4 if no EA's. */
3794 data_size
= fill_ea_buffer(mem_ctx
, pdata
, data_size
, conn
, ea_list
);
3798 case SMB2_FILE_FULL_EA_INFORMATION
:
3800 /* We have data_size bytes to put EA's into. */
3801 size_t total_ea_len
= 0;
3802 struct ea_list
*ea_file_list
= NULL
;
3804 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
3806 /*TODO: add filtering and index handling */
3809 get_ea_list_from_fsp(mem_ctx
,
3811 &total_ea_len
, &ea_file_list
);
3812 if (!NT_STATUS_IS_OK(status
)) {
3815 if (!ea_file_list
) {
3816 return NT_STATUS_NO_EAS_ON_FILE
;
3819 status
= fill_ea_chained_buffer(mem_ctx
,
3823 conn
, ea_file_list
);
3824 if (!NT_STATUS_IS_OK(status
)) {
3830 case SMB_FILE_BASIC_INFORMATION
:
3831 case SMB_QUERY_FILE_BASIC_INFO
:
3833 if (info_level
== SMB_QUERY_FILE_BASIC_INFO
) {
3834 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
3835 data_size
= 36; /* w95 returns 40 bytes not 36 - why ?. */
3837 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
3841 put_long_date_full_timespec(conn
->ts_res
,pdata
,&create_time_ts
);
3842 put_long_date_full_timespec(conn
->ts_res
,pdata
+8,&atime_ts
);
3843 put_long_date_full_timespec(conn
->ts_res
,pdata
+16,&mtime_ts
); /* write time */
3844 put_long_date_full_timespec(conn
->ts_res
,pdata
+24,&ctime_ts
); /* change time */
3845 SIVAL(pdata
,32,mode
);
3847 DEBUG(5,("SMB_QFBI - "));
3848 DEBUG(5,("create: %s ", ctime(&create_time
)));
3849 DEBUG(5,("access: %s ", ctime(&atime
)));
3850 DEBUG(5,("write: %s ", ctime(&mtime
)));
3851 DEBUG(5,("change: %s ", ctime(&c_time
)));
3852 DEBUG(5,("mode: %x\n", mode
));
3853 *fixed_portion
= data_size
;
3856 case SMB_FILE_STANDARD_INFORMATION
:
3857 case SMB_QUERY_FILE_STANDARD_INFO
:
3859 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
3861 SOFF_T(pdata
,0,allocation_size
);
3862 SOFF_T(pdata
,8,file_size
);
3863 SIVAL(pdata
,16,nlink
);
3864 SCVAL(pdata
,20,delete_pending
?1:0);
3865 SCVAL(pdata
,21,(mode
&FILE_ATTRIBUTE_DIRECTORY
)?1:0);
3866 SSVAL(pdata
,22,0); /* Padding. */
3867 *fixed_portion
= 24;
3870 case SMB_FILE_EA_INFORMATION
:
3871 case SMB_QUERY_FILE_EA_INFO
:
3873 unsigned int ea_size
=
3874 estimate_ea_size(smb_fname
->fsp
);
3875 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
3878 SIVAL(pdata
,0,ea_size
);
3882 /* Get the 8.3 name - used if NT SMB was negotiated. */
3883 case SMB_QUERY_FILE_ALT_NAME_INFO
:
3884 case SMB_FILE_ALTERNATE_NAME_INFORMATION
:
3886 char mangled_name
[13];
3887 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
3888 if (!name_to_8_3(base_name
,mangled_name
,
3889 True
,conn
->params
)) {
3890 return NT_STATUS_NO_MEMORY
;
3892 status
= srvstr_push(dstart
, flags2
,
3893 pdata
+4, mangled_name
,
3894 PTR_DIFF(dend
, pdata
+4),
3896 if (!NT_STATUS_IS_OK(status
)) {
3899 data_size
= 4 + len
;
3905 case SMB_QUERY_FILE_NAME_INFO
:
3908 this must be *exactly* right for ACLs on mapped drives to work
3910 status
= srvstr_push(dstart
, flags2
,
3912 PTR_DIFF(dend
, pdata
+4),
3914 if (!NT_STATUS_IS_OK(status
)) {
3917 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
3918 data_size
= 4 + len
;
3923 case SMB_FILE_NORMALIZED_NAME_INFORMATION
:
3925 char *nfname
= NULL
;
3927 if (fsp
== NULL
|| !fsp
->conn
->sconn
->using_smb2
) {
3928 return NT_STATUS_INVALID_LEVEL
;
3931 nfname
= talloc_strdup(mem_ctx
, smb_fname
->base_name
);
3932 if (nfname
== NULL
) {
3933 return NT_STATUS_NO_MEMORY
;
3936 if (ISDOT(nfname
)) {
3939 string_replace(nfname
, '/', '\\');
3941 if (fsp_is_alternate_stream(fsp
)) {
3942 const char *s
= smb_fname
->stream_name
;
3943 const char *e
= NULL
;
3946 SMB_ASSERT(s
[0] != '\0');
3949 * smb_fname->stream_name is in form
3950 * of ':StrEam:$DATA', but we should only
3951 * append ':StrEam' here.
3954 e
= strchr(&s
[1], ':');
3960 nfname
= talloc_strndup_append(nfname
, s
, n
);
3961 if (nfname
== NULL
) {
3962 return NT_STATUS_NO_MEMORY
;
3966 status
= srvstr_push(dstart
, flags2
,
3968 PTR_DIFF(dend
, pdata
+4),
3970 if (!NT_STATUS_IS_OK(status
)) {
3973 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NORMALIZED_NAME_INFORMATION\n"));
3974 data_size
= 4 + len
;
3980 case SMB_FILE_ALLOCATION_INFORMATION
:
3981 case SMB_QUERY_FILE_ALLOCATION_INFO
:
3982 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
3984 SOFF_T(pdata
,0,allocation_size
);
3987 case SMB_FILE_END_OF_FILE_INFORMATION
:
3988 case SMB_QUERY_FILE_END_OF_FILEINFO
:
3989 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
3991 SOFF_T(pdata
,0,file_size
);
3994 case SMB_QUERY_FILE_ALL_INFO
:
3995 case SMB_FILE_ALL_INFORMATION
:
3997 unsigned int ea_size
=
3998 estimate_ea_size(smb_fname
->fsp
);
3999 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4000 put_long_date_full_timespec(conn
->ts_res
,pdata
,&create_time_ts
);
4001 put_long_date_full_timespec(conn
->ts_res
,pdata
+8,&atime_ts
);
4002 put_long_date_full_timespec(conn
->ts_res
,pdata
+16,&mtime_ts
); /* write time */
4003 put_long_date_full_timespec(conn
->ts_res
,pdata
+24,&ctime_ts
); /* change time */
4004 SIVAL(pdata
,32,mode
);
4005 SIVAL(pdata
,36,0); /* padding. */
4007 SOFF_T(pdata
,0,allocation_size
);
4008 SOFF_T(pdata
,8,file_size
);
4009 SIVAL(pdata
,16,nlink
);
4010 SCVAL(pdata
,20,delete_pending
);
4011 SCVAL(pdata
,21,(mode
&FILE_ATTRIBUTE_DIRECTORY
)?1:0);
4014 SIVAL(pdata
,0,ea_size
);
4015 pdata
+= 4; /* EA info */
4016 status
= srvstr_push(dstart
, flags2
,
4018 PTR_DIFF(dend
, pdata
+4),
4020 if (!NT_STATUS_IS_OK(status
)) {
4025 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4026 *fixed_portion
= 10;
4030 case SMB2_FILE_ALL_INFORMATION
:
4032 unsigned int ea_size
=
4033 estimate_ea_size(smb_fname
->fsp
);
4034 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
4035 put_long_date_full_timespec(conn
->ts_res
,pdata
+0x00,&create_time_ts
);
4036 put_long_date_full_timespec(conn
->ts_res
,pdata
+0x08,&atime_ts
);
4037 put_long_date_full_timespec(conn
->ts_res
,pdata
+0x10,&mtime_ts
); /* write time */
4038 put_long_date_full_timespec(conn
->ts_res
,pdata
+0x18,&ctime_ts
); /* change time */
4039 SIVAL(pdata
, 0x20, mode
);
4040 SIVAL(pdata
, 0x24, 0); /* padding. */
4041 SBVAL(pdata
, 0x28, allocation_size
);
4042 SBVAL(pdata
, 0x30, file_size
);
4043 SIVAL(pdata
, 0x38, nlink
);
4044 SCVAL(pdata
, 0x3C, delete_pending
);
4045 SCVAL(pdata
, 0x3D, (mode
&FILE_ATTRIBUTE_DIRECTORY
)?1:0);
4046 SSVAL(pdata
, 0x3E, 0); /* padding */
4047 SBVAL(pdata
, 0x40, file_id
);
4048 SIVAL(pdata
, 0x48, ea_size
);
4049 SIVAL(pdata
, 0x4C, access_mask
);
4050 SBVAL(pdata
, 0x50, pos
);
4051 SIVAL(pdata
, 0x58, mode
); /*TODO: mode != mode fix this!!! */
4052 SIVAL(pdata
, 0x5C, 0); /* No alignment needed. */
4056 status
= srvstr_push(dstart
, flags2
,
4058 PTR_DIFF(dend
, pdata
+4),
4060 if (!NT_STATUS_IS_OK(status
)) {
4065 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4066 *fixed_portion
= 104;
4069 case SMB_FILE_INTERNAL_INFORMATION
:
4071 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4072 SBVAL(pdata
, 0, file_id
);
4077 case SMB_FILE_ACCESS_INFORMATION
:
4078 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4079 SIVAL(pdata
, 0, access_mask
);
4084 case SMB_FILE_NAME_INFORMATION
:
4085 /* Pathname with leading '\'. */
4088 byte_len
= dos_PutUniCode(pdata
+4,dos_fname
,(size_t)max_data_bytes
,False
);
4089 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4090 SIVAL(pdata
,0,byte_len
);
4091 data_size
= 4 + byte_len
;
4095 case SMB_FILE_DISPOSITION_INFORMATION
:
4096 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4098 SCVAL(pdata
,0,delete_pending
);
4102 case SMB_FILE_POSITION_INFORMATION
:
4103 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4105 SOFF_T(pdata
,0,pos
);
4109 case SMB_FILE_MODE_INFORMATION
:
4110 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4111 SIVAL(pdata
,0,mode
);
4116 case SMB_FILE_ALIGNMENT_INFORMATION
:
4117 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4118 SIVAL(pdata
,0,0); /* No alignment needed. */
4124 * NT4 server just returns "invalid query" to this - if we try
4125 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4128 /* The first statement above is false - verified using Thursby
4129 * client against NT4 -- gcolley.
4131 case SMB_QUERY_FILE_STREAM_INFO
:
4132 case SMB_FILE_STREAM_INFORMATION
: {
4133 unsigned int num_streams
= 0;
4134 struct stream_struct
*streams
= NULL
;
4136 DEBUG(10,("smbd_do_qfilepathinfo: "
4137 "SMB_FILE_STREAM_INFORMATION\n"));
4139 if (is_ntfs_stream_smb_fname(smb_fname
)) {
4140 return NT_STATUS_INVALID_PARAMETER
;
4143 status
= vfs_fstreaminfo(fsp
,
4148 if (!NT_STATUS_IS_OK(status
)) {
4149 DEBUG(10, ("could not get stream info: %s\n",
4150 nt_errstr(status
)));
4154 status
= marshall_stream_info(num_streams
, streams
,
4155 pdata
, max_data_bytes
,
4158 if (!NT_STATUS_IS_OK(status
)) {
4159 DEBUG(10, ("marshall_stream_info failed: %s\n",
4160 nt_errstr(status
)));
4161 TALLOC_FREE(streams
);
4165 TALLOC_FREE(streams
);
4167 *fixed_portion
= 32;
4171 case SMB_QUERY_COMPRESSION_INFO
:
4172 case SMB_FILE_COMPRESSION_INFORMATION
:
4173 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4174 SOFF_T(pdata
,0,file_size
);
4175 SIVAL(pdata
,8,0); /* ??? */
4176 SIVAL(pdata
,12,0); /* ??? */
4178 *fixed_portion
= 16;
4181 case SMB_FILE_NETWORK_OPEN_INFORMATION
:
4182 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4183 put_long_date_full_timespec(conn
->ts_res
,pdata
,&create_time_ts
);
4184 put_long_date_full_timespec(conn
->ts_res
,pdata
+8,&atime_ts
);
4185 put_long_date_full_timespec(conn
->ts_res
,pdata
+16,&mtime_ts
); /* write time */
4186 put_long_date_full_timespec(conn
->ts_res
,pdata
+24,&ctime_ts
); /* change time */
4187 SOFF_T(pdata
,32,allocation_size
);
4188 SOFF_T(pdata
,40,file_size
);
4189 SIVAL(pdata
,48,mode
);
4190 SIVAL(pdata
,52,0); /* ??? */
4192 *fixed_portion
= 56;
4195 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION
:
4196 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4197 SIVAL(pdata
,0,mode
);
4204 * CIFS UNIX Extensions.
4207 case SMB_QUERY_FILE_UNIX_BASIC
:
4209 pdata
= store_file_unix_basic(conn
, pdata
, fsp
, psbuf
);
4210 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4212 DEBUG(4,("smbd_do_qfilepathinfo: "
4213 "SMB_QUERY_FILE_UNIX_BASIC\n"));
4214 dump_data(4, (uint8_t *)(*ppdata
), data_size
);
4218 case SMB_QUERY_FILE_UNIX_INFO2
:
4220 pdata
= store_file_unix_basic_info2(conn
, pdata
, fsp
, psbuf
);
4221 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4225 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4227 for (i
=0; i
<100; i
++)
4228 DEBUG(4,("%d=%x, ",i
, (*ppdata
)[i
]));
4234 case SMB_QUERY_FILE_UNIX_LINK
:
4236 status
= smb_unix_read_symlink(conn
,
4242 if (!NT_STATUS_IS_OK(status
)) {
4248 #if defined(HAVE_POSIX_ACLS)
4249 case SMB_QUERY_POSIX_ACL
:
4251 status
= smb_query_posix_acl(conn
,
4258 if (!NT_STATUS_IS_OK(status
)) {
4266 case SMB_QUERY_POSIX_LOCK
:
4271 enum brl_type lock_type
;
4273 /* We need an open file with a real fd for this. */
4275 fsp
->fsp_flags
.is_pathref
||
4276 fsp_get_io_fd(fsp
) == -1)
4278 return NT_STATUS_INVALID_LEVEL
;
4281 if (lock_data_count
!= POSIX_LOCK_DATA_SIZE
) {
4282 return NT_STATUS_INVALID_PARAMETER
;
4285 switch (SVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
)) {
4286 case POSIX_LOCK_TYPE_READ
:
4287 lock_type
= READ_LOCK
;
4289 case POSIX_LOCK_TYPE_WRITE
:
4290 lock_type
= WRITE_LOCK
;
4292 case POSIX_LOCK_TYPE_UNLOCK
:
4294 /* There's no point in asking for an unlock... */
4295 return NT_STATUS_INVALID_PARAMETER
;
4298 smblctx
= (uint64_t)IVAL(pdata
, POSIX_LOCK_PID_OFFSET
);
4299 offset
= BVAL(pdata
,POSIX_LOCK_START_OFFSET
);
4300 count
= BVAL(pdata
,POSIX_LOCK_LEN_OFFSET
);
4302 status
= query_lock(fsp
,
4309 if (ERROR_WAS_LOCK_DENIED(status
)) {
4310 /* Here we need to report who has it locked... */
4311 data_size
= POSIX_LOCK_DATA_SIZE
;
4313 SSVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
, lock_type
);
4314 SSVAL(pdata
, POSIX_LOCK_FLAGS_OFFSET
, 0);
4315 SIVAL(pdata
, POSIX_LOCK_PID_OFFSET
, (uint32_t)smblctx
);
4316 SBVAL(pdata
, POSIX_LOCK_START_OFFSET
, offset
);
4317 SBVAL(pdata
, POSIX_LOCK_LEN_OFFSET
, count
);
4319 } else if (NT_STATUS_IS_OK(status
)) {
4320 /* For success we just return a copy of what we sent
4321 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4322 data_size
= POSIX_LOCK_DATA_SIZE
;
4323 memcpy(pdata
, lock_data
, POSIX_LOCK_DATA_SIZE
);
4324 SSVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
, POSIX_LOCK_TYPE_UNLOCK
);
4332 * SMB2 UNIX Extensions.
4334 case SMB2_FILE_POSIX_INFORMATION_INTERNAL
:
4336 uint8_t *buf
= NULL
;
4339 if (!(conn
->sconn
->using_smb2
)) {
4340 return NT_STATUS_INVALID_LEVEL
;
4342 if (!lp_smb3_unix_extensions()) {
4343 return NT_STATUS_INVALID_LEVEL
;
4346 return NT_STATUS_INVALID_HANDLE
;
4348 if (!(fsp
->posix_flags
& FSP_POSIX_FLAGS_OPEN
)) {
4349 return NT_STATUS_INVALID_LEVEL
;
4352 /* Determine the size of the posix info context */
4353 plen
= store_smb2_posix_info(conn
,
4359 if (plen
== -1 || data_size
< plen
) {
4360 return NT_STATUS_INVALID_PARAMETER
;
4362 buf
= talloc_zero_size(mem_ctx
, plen
);
4364 return NT_STATUS_NO_MEMORY
;
4367 /* Store the context in buf */
4368 store_smb2_posix_info(conn
,
4374 memcpy(pdata
, buf
, plen
);
4380 return NT_STATUS_INVALID_LEVEL
;
4383 *pdata_size
= data_size
;
4384 return NT_STATUS_OK
;
4387 /****************************************************************************
4388 Set a hard link (called by UNIX extensions and by NT rename with HARD link
4390 ****************************************************************************/
4392 NTSTATUS
hardlink_internals(TALLOC_CTX
*ctx
,
4393 connection_struct
*conn
,
4394 struct smb_request
*req
,
4395 bool overwrite_if_exists
,
4396 struct files_struct
*old_dirfsp
,
4397 const struct smb_filename
*smb_fname_old
,
4398 struct files_struct
*new_dirfsp
,
4399 struct smb_filename
*smb_fname_new
)
4401 NTSTATUS status
= NT_STATUS_OK
;
4404 struct smb_filename
*parent_fname_old
= NULL
;
4405 struct smb_filename
*base_name_old
= NULL
;
4406 struct smb_filename
*parent_fname_new
= NULL
;
4407 struct smb_filename
*base_name_new
= NULL
;
4409 /* source must already exist. */
4410 if (!VALID_STAT(smb_fname_old
->st
)) {
4411 status
= NT_STATUS_OBJECT_NAME_NOT_FOUND
;
4415 /* No links from a directory. */
4416 if (S_ISDIR(smb_fname_old
->st
.st_ex_mode
)) {
4417 status
= NT_STATUS_FILE_IS_A_DIRECTORY
;
4421 /* Setting a hardlink to/from a stream isn't currently supported. */
4422 ok
= is_ntfs_stream_smb_fname(smb_fname_old
);
4424 DBG_DEBUG("Old name has streams\n");
4425 status
= NT_STATUS_INVALID_PARAMETER
;
4428 ok
= is_ntfs_stream_smb_fname(smb_fname_new
);
4430 DBG_DEBUG("New name has streams\n");
4431 status
= NT_STATUS_INVALID_PARAMETER
;
4435 status
= parent_pathref(talloc_tos(),
4440 if (!NT_STATUS_IS_OK(status
)) {
4444 status
= parent_pathref(talloc_tos(),
4449 if (!NT_STATUS_IS_OK(status
)) {
4453 if (VALID_STAT(smb_fname_new
->st
)) {
4454 if (overwrite_if_exists
) {
4455 if (S_ISDIR(smb_fname_new
->st
.st_ex_mode
)) {
4456 status
= NT_STATUS_FILE_IS_A_DIRECTORY
;
4459 status
= unlink_internals(conn
,
4461 FILE_ATTRIBUTE_NORMAL
,
4462 NULL
, /* new_dirfsp */
4464 if (!NT_STATUS_IS_OK(status
)) {
4468 /* Disallow if newname already exists. */
4469 status
= NT_STATUS_OBJECT_NAME_COLLISION
;
4474 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
4475 smb_fname_old
->base_name
, smb_fname_new
->base_name
));
4477 ret
= SMB_VFS_LINKAT(conn
,
4478 parent_fname_old
->fsp
,
4480 parent_fname_new
->fsp
,
4485 status
= map_nt_error_from_unix(errno
);
4486 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
4487 nt_errstr(status
), smb_fname_old
->base_name
,
4488 smb_fname_new
->base_name
));
4493 TALLOC_FREE(parent_fname_old
);
4494 TALLOC_FREE(parent_fname_new
);
4498 /****************************************************************************
4499 Deal with setting the time from any of the setfilepathinfo functions.
4500 NOTE !!!! The check for FILE_WRITE_ATTRIBUTES access must be done *before*
4501 calling this function.
4502 ****************************************************************************/
4504 NTSTATUS
smb_set_file_time(connection_struct
*conn
,
4506 struct smb_filename
*smb_fname
,
4507 struct smb_file_time
*ft
,
4508 bool setting_write_time
)
4510 struct files_struct
*set_fsp
= NULL
;
4511 struct timeval_buf tbuf
[4];
4513 FILE_NOTIFY_CHANGE_LAST_ACCESS
4514 |FILE_NOTIFY_CHANGE_LAST_WRITE
4515 |FILE_NOTIFY_CHANGE_CREATION
;
4518 if (!VALID_STAT(smb_fname
->st
)) {
4519 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
4524 return NT_STATUS_OK
;
4527 set_fsp
= metadata_fsp(fsp
);
4529 /* get some defaults (no modifications) if any info is zero or -1. */
4530 if (is_omit_timespec(&ft
->create_time
)) {
4531 action
&= ~FILE_NOTIFY_CHANGE_CREATION
;
4534 if (is_omit_timespec(&ft
->atime
)) {
4535 action
&= ~FILE_NOTIFY_CHANGE_LAST_ACCESS
;
4538 if (is_omit_timespec(&ft
->mtime
)) {
4539 action
&= ~FILE_NOTIFY_CHANGE_LAST_WRITE
;
4542 if (!setting_write_time
) {
4543 /* ft->mtime comes from change time, not write time. */
4544 action
&= ~FILE_NOTIFY_CHANGE_LAST_WRITE
;
4547 /* Ensure the resolution is the correct for
4548 * what we can store on this filesystem. */
4550 round_timespec(conn
->ts_res
, &ft
->create_time
);
4551 round_timespec(conn
->ts_res
, &ft
->ctime
);
4552 round_timespec(conn
->ts_res
, &ft
->atime
);
4553 round_timespec(conn
->ts_res
, &ft
->mtime
);
4555 DBG_DEBUG("smb_set_filetime: actime: %s\n ",
4556 timespec_string_buf(&ft
->atime
, true, &tbuf
[0]));
4557 DBG_DEBUG("smb_set_filetime: modtime: %s\n ",
4558 timespec_string_buf(&ft
->mtime
, true, &tbuf
[1]));
4559 DBG_DEBUG("smb_set_filetime: ctime: %s\n ",
4560 timespec_string_buf(&ft
->ctime
, true, &tbuf
[2]));
4561 DBG_DEBUG("smb_set_file_time: createtime: %s\n ",
4562 timespec_string_buf(&ft
->create_time
, true, &tbuf
[3]));
4564 if (setting_write_time
) {
4566 * This was a Windows setfileinfo on an open file.
4567 * NT does this a lot. We also need to
4568 * set the time here, as it can be read by
4569 * FindFirst/FindNext and with the patch for bug #2045
4570 * in smbd/fileio.c it ensures that this timestamp is
4571 * kept sticky even after a write. We save the request
4572 * away and will set it on file close and after a write. JRA.
4575 DBG_DEBUG("setting pending modtime to %s\n",
4576 timespec_string_buf(&ft
->mtime
, true, &tbuf
[0]));
4578 if (set_fsp
!= NULL
) {
4579 set_sticky_write_time_fsp(set_fsp
, ft
->mtime
);
4581 set_sticky_write_time_path(
4582 vfs_file_id_from_sbuf(conn
, &smb_fname
->st
),
4587 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
4589 ret
= file_ntimes(conn
, set_fsp
, ft
);
4591 return map_nt_error_from_unix(errno
);
4594 notify_fname(conn
, NOTIFY_ACTION_MODIFIED
, action
,
4595 smb_fname
->base_name
);
4596 return NT_STATUS_OK
;
4599 /****************************************************************************
4600 Deal with setting the dosmode from any of the setfilepathinfo functions.
4601 NB. The check for FILE_WRITE_ATTRIBUTES access on this path must have been
4602 done before calling this function.
4603 ****************************************************************************/
4605 static NTSTATUS
smb_set_file_dosmode(connection_struct
*conn
,
4606 struct files_struct
*fsp
,
4609 struct files_struct
*dos_fsp
= NULL
;
4610 uint32_t current_dosmode
;
4613 if (!VALID_STAT(fsp
->fsp_name
->st
)) {
4614 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
4617 dos_fsp
= metadata_fsp(fsp
);
4620 if (S_ISDIR(fsp
->fsp_name
->st
.st_ex_mode
)) {
4621 dosmode
|= FILE_ATTRIBUTE_DIRECTORY
;
4623 dosmode
&= ~FILE_ATTRIBUTE_DIRECTORY
;
4627 DBG_DEBUG("dosmode: 0x%" PRIx32
"\n", dosmode
);
4629 /* check the mode isn't different, before changing it */
4631 return NT_STATUS_OK
;
4633 current_dosmode
= fdos_mode(dos_fsp
);
4634 if (dosmode
== current_dosmode
) {
4635 return NT_STATUS_OK
;
4638 DBG_DEBUG("file %s : setting dos mode 0x%" PRIx32
"\n",
4639 fsp_str_dbg(dos_fsp
), dosmode
);
4641 ret
= file_set_dosmode(conn
, dos_fsp
->fsp_name
, dosmode
, NULL
, false);
4643 DBG_WARNING("file_set_dosmode of %s failed: %s\n",
4644 fsp_str_dbg(dos_fsp
), strerror(errno
));
4645 return map_nt_error_from_unix(errno
);
4648 return NT_STATUS_OK
;
4651 /****************************************************************************
4652 Deal with setting the size from any of the setfilepathinfo functions.
4653 ****************************************************************************/
4655 static NTSTATUS
smb_set_file_size(connection_struct
*conn
,
4656 struct smb_request
*req
,
4658 struct smb_filename
*smb_fname
,
4659 const SMB_STRUCT_STAT
*psbuf
,
4661 bool fail_after_createfile
)
4663 NTSTATUS status
= NT_STATUS_OK
;
4664 files_struct
*new_fsp
= NULL
;
4666 if (!VALID_STAT(*psbuf
)) {
4667 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
4670 DBG_INFO("size: %"PRIu64
", file_size_stat=%"PRIu64
"\n",
4672 get_file_size_stat(psbuf
));
4674 if (size
== get_file_size_stat(psbuf
)) {
4676 return NT_STATUS_OK
;
4678 if (!fsp
->fsp_flags
.modified
) {
4679 return NT_STATUS_OK
;
4681 trigger_write_time_update_immediate(fsp
);
4682 return NT_STATUS_OK
;
4685 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
4686 smb_fname_str_dbg(smb_fname
), (double)size
));
4689 !fsp
->fsp_flags
.is_pathref
&&
4690 fsp_get_io_fd(fsp
) != -1)
4692 /* Handle based call. */
4693 if (!(fsp
->access_mask
& FILE_WRITE_DATA
)) {
4694 return NT_STATUS_ACCESS_DENIED
;
4697 if (vfs_set_filelen(fsp
, size
) == -1) {
4698 return map_nt_error_from_unix(errno
);
4700 trigger_write_time_update_immediate(fsp
);
4701 return NT_STATUS_OK
;
4704 status
= SMB_VFS_CREATE_FILE(
4708 smb_fname
, /* fname */
4709 FILE_WRITE_DATA
, /* access_mask */
4710 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
4712 FILE_OPEN
, /* create_disposition*/
4713 0, /* create_options */
4714 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
4715 0, /* oplock_request */
4717 0, /* allocation_size */
4718 0, /* private_flags */
4721 &new_fsp
, /* result */
4723 NULL
, NULL
); /* create context */
4725 if (!NT_STATUS_IS_OK(status
)) {
4726 /* NB. We check for open_was_deferred in the caller. */
4730 /* See RAW-SFILEINFO-END-OF-FILE */
4731 if (fail_after_createfile
) {
4732 close_file_free(req
, &new_fsp
, NORMAL_CLOSE
);
4733 return NT_STATUS_INVALID_LEVEL
;
4736 if (vfs_set_filelen(new_fsp
, size
) == -1) {
4737 status
= map_nt_error_from_unix(errno
);
4738 close_file_free(req
, &new_fsp
, NORMAL_CLOSE
);
4742 trigger_write_time_update_immediate(new_fsp
);
4743 close_file_free(req
, &new_fsp
, NORMAL_CLOSE
);
4744 return NT_STATUS_OK
;
4747 /****************************************************************************
4748 Deal with SMB_INFO_SET_EA.
4749 ****************************************************************************/
4751 static NTSTATUS
smb_info_set_ea(connection_struct
*conn
,
4755 struct smb_filename
*smb_fname
)
4757 struct ea_list
*ea_list
= NULL
;
4758 TALLOC_CTX
*ctx
= NULL
;
4759 NTSTATUS status
= NT_STATUS_OK
;
4761 if (total_data
< 10) {
4763 /* OS/2 workplace shell seems to send SET_EA requests of "null"
4764 length. They seem to have no effect. Bug #3212. JRA */
4766 if ((total_data
== 4) && (IVAL(pdata
,0) == 4)) {
4767 /* We're done. We only get EA info in this call. */
4768 return NT_STATUS_OK
;
4771 return NT_STATUS_INVALID_PARAMETER
;
4774 if (IVAL(pdata
,0) > total_data
) {
4775 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
4776 IVAL(pdata
,0), (unsigned int)total_data
));
4777 return NT_STATUS_INVALID_PARAMETER
;
4781 ea_list
= read_ea_list(ctx
, pdata
+ 4, total_data
- 4);
4783 return NT_STATUS_INVALID_PARAMETER
;
4788 * The only way fsp can be NULL here is if
4789 * smb_fname points at a symlink and
4790 * and we're in POSIX context.
4791 * Ensure this is the case.
4793 * In this case we cannot set the EA.
4795 SMB_ASSERT(smb_fname
->flags
& SMB_FILENAME_POSIX_PATH
);
4796 return NT_STATUS_ACCESS_DENIED
;
4799 status
= set_ea(conn
, fsp
, ea_list
);
4804 /****************************************************************************
4805 Deal with SMB_FILE_FULL_EA_INFORMATION set.
4806 ****************************************************************************/
4808 static NTSTATUS
smb_set_file_full_ea_info(connection_struct
*conn
,
4813 struct ea_list
*ea_list
= NULL
;
4817 return NT_STATUS_INVALID_HANDLE
;
4820 if (!lp_ea_support(SNUM(conn
))) {
4821 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
4822 "EA's not supported.\n",
4823 (unsigned int)total_data
));
4824 return NT_STATUS_EAS_NOT_SUPPORTED
;
4827 if (total_data
< 10) {
4828 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
4830 (unsigned int)total_data
));
4831 return NT_STATUS_INVALID_PARAMETER
;
4834 ea_list
= read_nttrans_ea_list(talloc_tos(),
4839 return NT_STATUS_INVALID_PARAMETER
;
4842 status
= set_ea(conn
, fsp
, ea_list
);
4844 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
4845 smb_fname_str_dbg(fsp
->fsp_name
),
4846 nt_errstr(status
) ));
4852 /****************************************************************************
4853 Deal with SMB_SET_FILE_DISPOSITION_INFO.
4854 ****************************************************************************/
4856 NTSTATUS
smb_set_file_disposition_info(connection_struct
*conn
,
4860 struct smb_filename
*smb_fname
)
4862 NTSTATUS status
= NT_STATUS_OK
;
4863 bool delete_on_close
;
4864 uint32_t dosmode
= 0;
4866 if (total_data
< 1) {
4867 return NT_STATUS_INVALID_PARAMETER
;
4871 return NT_STATUS_INVALID_HANDLE
;
4874 delete_on_close
= (CVAL(pdata
,0) ? True
: False
);
4875 dosmode
= fdos_mode(fsp
);
4877 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
4878 "delete_on_close = %u\n",
4879 smb_fname_str_dbg(smb_fname
),
4880 (unsigned int)dosmode
,
4881 (unsigned int)delete_on_close
));
4883 if (delete_on_close
) {
4884 status
= can_set_delete_on_close(fsp
, dosmode
);
4885 if (!NT_STATUS_IS_OK(status
)) {
4890 /* The set is across all open files on this dev/inode pair. */
4891 if (!set_delete_on_close(fsp
, delete_on_close
,
4892 conn
->session_info
->security_token
,
4893 conn
->session_info
->unix_token
)) {
4894 return NT_STATUS_ACCESS_DENIED
;
4896 return NT_STATUS_OK
;
4899 /****************************************************************************
4900 Deal with SMB_FILE_POSITION_INFORMATION.
4901 ****************************************************************************/
4903 static NTSTATUS
smb_file_position_information(connection_struct
*conn
,
4908 uint64_t position_information
;
4910 if (total_data
< 8) {
4911 return NT_STATUS_INVALID_PARAMETER
;
4915 /* Ignore on pathname based set. */
4916 return NT_STATUS_OK
;
4919 position_information
= (uint64_t)IVAL(pdata
,0);
4920 position_information
|= (((uint64_t)IVAL(pdata
,4)) << 32);
4922 DEBUG(10,("smb_file_position_information: Set file position "
4923 "information for file %s to %.0f\n", fsp_str_dbg(fsp
),
4924 (double)position_information
));
4925 fh_set_position_information(fsp
->fh
, position_information
);
4926 return NT_STATUS_OK
;
4929 /****************************************************************************
4930 Deal with SMB_FILE_MODE_INFORMATION.
4931 ****************************************************************************/
4933 static NTSTATUS
smb_file_mode_information(connection_struct
*conn
,
4939 if (total_data
< 4) {
4940 return NT_STATUS_INVALID_PARAMETER
;
4942 mode
= IVAL(pdata
,0);
4943 if (mode
!= 0 && mode
!= 2 && mode
!= 4 && mode
!= 6) {
4944 return NT_STATUS_INVALID_PARAMETER
;
4946 return NT_STATUS_OK
;
4949 /****************************************************************************
4950 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
4951 ****************************************************************************/
4953 static NTSTATUS
smb2_file_rename_information(connection_struct
*conn
,
4954 struct smb_request
*req
,
4958 struct smb_filename
*smb_fname_src
)
4962 char *newname
= NULL
;
4963 struct files_struct
*dst_dirfsp
= NULL
;
4964 struct smb_filename
*smb_fname_dst
= NULL
;
4965 const char *dst_original_lcomp
= NULL
;
4966 uint32_t ucf_flags
= ucf_flags_from_smb_request(req
);
4967 NTTIME dst_twrp
= 0;
4968 NTSTATUS status
= NT_STATUS_OK
;
4969 bool is_dfs
= (req
->flags2
& FLAGS2_DFS_PATHNAMES
);
4970 TALLOC_CTX
*ctx
= talloc_tos();
4973 return NT_STATUS_INVALID_HANDLE
;
4976 if (total_data
< 20) {
4977 return NT_STATUS_INVALID_PARAMETER
;
4980 overwrite
= (CVAL(pdata
,0) ? True
: False
);
4981 len
= IVAL(pdata
,16);
4983 if (len
> (total_data
- 20) || (len
== 0)) {
4984 return NT_STATUS_INVALID_PARAMETER
;
4987 (void)srvstr_pull_talloc(ctx
,
4995 if (newname
== NULL
) {
4996 return NT_STATUS_INVALID_PARAMETER
;
4998 status
= check_path_syntax_smb2(newname
, is_dfs
);
4999 if (!NT_STATUS_IS_OK(status
)) {
5003 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
5006 if (newname
[0] == ':') {
5007 /* Create an smb_fname to call rename_internals_fsp() with. */
5008 smb_fname_dst
= synthetic_smb_fname(talloc_tos(),
5009 fsp
->base_fsp
->fsp_name
->base_name
,
5012 fsp
->base_fsp
->fsp_name
->twrp
,
5013 fsp
->base_fsp
->fsp_name
->flags
);
5014 if (smb_fname_dst
== NULL
) {
5015 status
= NT_STATUS_NO_MEMORY
;
5019 if (ucf_flags
& UCF_GMT_PATHNAME
) {
5020 extract_snapshot_token(newname
, &dst_twrp
);
5022 status
= filename_convert_dirfsp(ctx
,
5029 if (!NT_STATUS_IS_OK(status
)) {
5035 * Set the original last component, since
5036 * rename_internals_fsp() requires it.
5038 dst_original_lcomp
= get_original_lcomp(smb_fname_dst
,
5042 if (dst_original_lcomp
== NULL
) {
5043 status
= NT_STATUS_NO_MEMORY
;
5047 DEBUG(10,("smb2_file_rename_information: "
5048 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
5049 fsp_fnum_dbg(fsp
), fsp_str_dbg(fsp
),
5050 smb_fname_str_dbg(smb_fname_dst
)));
5051 status
= rename_internals_fsp(conn
,
5053 NULL
, /* dst_dirfsp */
5056 (FILE_ATTRIBUTE_HIDDEN
|FILE_ATTRIBUTE_SYSTEM
),
5060 TALLOC_FREE(smb_fname_dst
);
5064 static NTSTATUS
smb_file_link_information(connection_struct
*conn
,
5065 struct smb_request
*req
,
5069 struct smb_filename
*smb_fname_src
)
5073 char *newname
= NULL
;
5074 struct files_struct
*dst_dirfsp
= NULL
;
5075 struct smb_filename
*smb_fname_dst
= NULL
;
5076 NTSTATUS status
= NT_STATUS_OK
;
5077 uint32_t ucf_flags
= ucf_flags_from_smb_request(req
);
5078 NTTIME dst_twrp
= 0;
5079 TALLOC_CTX
*ctx
= talloc_tos();
5082 return NT_STATUS_INVALID_HANDLE
;
5085 if (total_data
< 20) {
5086 return NT_STATUS_INVALID_PARAMETER
;
5089 overwrite
= (CVAL(pdata
,0) ? true : false);
5090 len
= IVAL(pdata
,16);
5092 if (len
> (total_data
- 20) || (len
== 0)) {
5093 return NT_STATUS_INVALID_PARAMETER
;
5096 if (smb_fname_src
->flags
& SMB_FILENAME_POSIX_PATH
) {
5097 srvstr_get_path_posix(ctx
,
5105 ucf_flags
|= UCF_POSIX_PATHNAMES
;
5107 srvstr_get_path(ctx
,
5116 if (!NT_STATUS_IS_OK(status
)) {
5120 DEBUG(10,("smb_file_link_information: got name |%s|\n",
5123 if (ucf_flags
& UCF_GMT_PATHNAME
) {
5124 extract_snapshot_token(newname
, &dst_twrp
);
5126 status
= filename_convert_dirfsp(ctx
,
5133 if (!NT_STATUS_IS_OK(status
)) {
5137 if (fsp
->base_fsp
) {
5138 /* No stream names. */
5139 return NT_STATUS_NOT_SUPPORTED
;
5142 DEBUG(10,("smb_file_link_information: "
5143 "SMB_FILE_LINK_INFORMATION (%s) %s -> %s\n",
5144 fsp_fnum_dbg(fsp
), fsp_str_dbg(fsp
),
5145 smb_fname_str_dbg(smb_fname_dst
)));
5146 status
= hardlink_internals(ctx
,
5150 NULL
, /* src_dirfsp */
5152 dst_dirfsp
, /* dst_dirfsp */
5155 TALLOC_FREE(smb_fname_dst
);
5159 /****************************************************************************
5160 Deal with SMB_FILE_RENAME_INFORMATION.
5161 ****************************************************************************/
5163 static NTSTATUS
smb_file_rename_information(connection_struct
*conn
,
5164 struct smb_request
*req
,
5168 struct smb_filename
*smb_fname_src
)
5173 char *newname
= NULL
;
5174 struct files_struct
*dst_dirfsp
= NULL
;
5175 struct smb_filename
*smb_fname_dst
= NULL
;
5176 const char *dst_original_lcomp
= NULL
;
5177 NTSTATUS status
= NT_STATUS_OK
;
5179 TALLOC_CTX
*ctx
= talloc_tos();
5181 if (total_data
< 13) {
5182 return NT_STATUS_INVALID_PARAMETER
;
5185 overwrite
= (CVAL(pdata
,0) != 0);
5186 root_fid
= IVAL(pdata
,4);
5187 len
= IVAL(pdata
,8);
5189 if (len
> (total_data
- 12) || (len
== 0) || (root_fid
!= 0)) {
5190 return NT_STATUS_INVALID_PARAMETER
;
5193 if (req
->posix_pathnames
) {
5194 srvstr_get_path_posix(ctx
,
5203 srvstr_get_path(ctx
,
5212 if (!NT_STATUS_IS_OK(status
)) {
5216 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
5219 /* Check the new name has no '/' characters. */
5220 if (strchr_m(newname
, '/')) {
5221 return NT_STATUS_NOT_SUPPORTED
;
5224 if (fsp
&& fsp
->base_fsp
) {
5225 /* newname must be a stream name. */
5226 if (newname
[0] != ':') {
5227 return NT_STATUS_NOT_SUPPORTED
;
5230 /* Create an smb_fname to call rename_internals_fsp() with. */
5231 smb_fname_dst
= synthetic_smb_fname(talloc_tos(),
5232 fsp
->base_fsp
->fsp_name
->base_name
,
5235 fsp
->base_fsp
->fsp_name
->twrp
,
5236 fsp
->base_fsp
->fsp_name
->flags
);
5237 if (smb_fname_dst
== NULL
) {
5238 status
= NT_STATUS_NO_MEMORY
;
5243 * Get the original last component, since
5244 * rename_internals_fsp() requires it.
5246 dst_original_lcomp
= get_original_lcomp(smb_fname_dst
,
5250 if (dst_original_lcomp
== NULL
) {
5251 status
= NT_STATUS_NO_MEMORY
;
5257 * Build up an smb_fname_dst based on the filename passed in.
5258 * We basically just strip off the last component, and put on
5259 * the newname instead.
5261 char *base_name
= NULL
;
5262 uint32_t ucf_flags
= ucf_flags_from_smb_request(req
);
5263 NTTIME dst_twrp
= 0;
5265 /* newname must *not* be a stream name. */
5266 if (newname
[0] == ':') {
5267 return NT_STATUS_NOT_SUPPORTED
;
5271 * Strip off the last component (filename) of the path passed
5274 base_name
= talloc_strdup(ctx
, smb_fname_src
->base_name
);
5276 return NT_STATUS_NO_MEMORY
;
5278 p
= strrchr_m(base_name
, '/');
5282 base_name
= talloc_strdup(ctx
, "");
5284 return NT_STATUS_NO_MEMORY
;
5287 /* Append the new name. */
5288 base_name
= talloc_asprintf_append(base_name
,
5292 return NT_STATUS_NO_MEMORY
;
5295 if (ucf_flags
& UCF_GMT_PATHNAME
) {
5296 extract_snapshot_token(base_name
, &dst_twrp
);
5298 status
= filename_convert_dirfsp(ctx
,
5306 if (!NT_STATUS_IS_OK(status
)) {
5309 dst_original_lcomp
= get_original_lcomp(smb_fname_dst
,
5313 if (dst_original_lcomp
== NULL
) {
5314 status
= NT_STATUS_NO_MEMORY
;
5319 if (fsp
!= NULL
&& fsp
->fsp_flags
.is_fsa
) {
5320 DEBUG(10,("smb_file_rename_information: "
5321 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
5322 fsp_fnum_dbg(fsp
), fsp_str_dbg(fsp
),
5323 smb_fname_str_dbg(smb_fname_dst
)));
5324 status
= rename_internals_fsp(conn
,
5332 DEBUG(10,("smb_file_rename_information: "
5333 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
5334 smb_fname_str_dbg(smb_fname_src
),
5335 smb_fname_str_dbg(smb_fname_dst
)));
5336 status
= rename_internals(ctx
,
5339 NULL
, /* src_dirfsp */
5346 FILE_WRITE_ATTRIBUTES
);
5349 TALLOC_FREE(smb_fname_dst
);
5353 /****************************************************************************
5354 Deal with SMB_SET_POSIX_ACL.
5355 ****************************************************************************/
5357 #if defined(HAVE_POSIX_ACLS)
5358 static NTSTATUS
smb_set_posix_acl(connection_struct
*conn
,
5359 struct smb_request
*req
,
5363 struct smb_filename
*smb_fname
)
5365 uint16_t posix_acl_version
;
5366 uint16_t num_file_acls
;
5367 uint16_t num_def_acls
;
5368 bool valid_file_acls
= true;
5369 bool valid_def_acls
= true;
5371 unsigned int size_needed
;
5372 unsigned int total_data
;
5373 bool close_fsp
= false;
5375 if (total_data_in
< 0) {
5376 status
= NT_STATUS_INVALID_PARAMETER
;
5380 total_data
= total_data_in
;
5382 if (total_data
< SMB_POSIX_ACL_HEADER_SIZE
) {
5383 status
= NT_STATUS_INVALID_PARAMETER
;
5386 posix_acl_version
= SVAL(pdata
,0);
5387 num_file_acls
= SVAL(pdata
,2);
5388 num_def_acls
= SVAL(pdata
,4);
5390 if (num_file_acls
== SMB_POSIX_IGNORE_ACE_ENTRIES
) {
5391 valid_file_acls
= false;
5395 if (num_def_acls
== SMB_POSIX_IGNORE_ACE_ENTRIES
) {
5396 valid_def_acls
= false;
5400 if (posix_acl_version
!= SMB_POSIX_ACL_VERSION
) {
5401 status
= NT_STATUS_INVALID_PARAMETER
;
5406 if (num_file_acls
+ num_def_acls
< num_file_acls
) {
5407 status
= NT_STATUS_INVALID_PARAMETER
;
5411 size_needed
= num_file_acls
+ num_def_acls
;
5414 * (size_needed * SMB_POSIX_ACL_ENTRY_SIZE) must be less
5415 * than UINT_MAX, so check by division.
5417 if (size_needed
> (UINT_MAX
/SMB_POSIX_ACL_ENTRY_SIZE
)) {
5418 status
= NT_STATUS_INVALID_PARAMETER
;
5422 size_needed
= size_needed
*SMB_POSIX_ACL_ENTRY_SIZE
;
5423 if (size_needed
+ SMB_POSIX_ACL_HEADER_SIZE
< size_needed
) {
5424 status
= NT_STATUS_INVALID_PARAMETER
;
5427 size_needed
+= SMB_POSIX_ACL_HEADER_SIZE
;
5429 if (total_data
< size_needed
) {
5430 status
= NT_STATUS_INVALID_PARAMETER
;
5435 * Ensure we always operate on a file descriptor, not just
5438 if (fsp
== NULL
|| !fsp
->fsp_flags
.is_fsa
) {
5439 uint32_t access_mask
= SEC_STD_WRITE_OWNER
|
5441 SEC_STD_READ_CONTROL
|
5442 FILE_READ_ATTRIBUTES
|
5443 FILE_WRITE_ATTRIBUTES
;
5445 status
= get_posix_fsp(conn
,
5451 if (!NT_STATUS_IS_OK(status
)) {
5457 /* Here we know fsp != NULL */
5458 SMB_ASSERT(fsp
!= NULL
);
5460 status
= refuse_symlink_fsp(fsp
);
5461 if (!NT_STATUS_IS_OK(status
)) {
5465 /* If we have a default acl, this *must* be a directory. */
5466 if (valid_def_acls
&& !fsp
->fsp_flags
.is_directory
) {
5467 DBG_INFO("Can't set default acls on "
5468 "non-directory %s\n",
5470 return NT_STATUS_INVALID_HANDLE
;
5473 DBG_DEBUG("file %s num_file_acls = %"PRIu16
", "
5474 "num_def_acls = %"PRIu16
"\n",
5479 /* Move pdata to the start of the file ACL entries. */
5480 pdata
+= SMB_POSIX_ACL_HEADER_SIZE
;
5482 if (valid_file_acls
) {
5483 status
= set_unix_posix_acl(conn
,
5487 if (!NT_STATUS_IS_OK(status
)) {
5492 /* Move pdata to the start of the default ACL entries. */
5493 pdata
+= (num_file_acls
*SMB_POSIX_ACL_ENTRY_SIZE
);
5495 if (valid_def_acls
) {
5496 status
= set_unix_posix_default_acl(conn
,
5500 if (!NT_STATUS_IS_OK(status
)) {
5505 status
= NT_STATUS_OK
;
5510 (void)close_file_free(req
, &fsp
, NORMAL_CLOSE
);
5516 /****************************************************************************
5517 Deal with SMB_SET_FILE_BASIC_INFO.
5518 ****************************************************************************/
5520 static NTSTATUS
smb_set_file_basic_info(connection_struct
*conn
,
5524 struct smb_filename
*smb_fname
)
5526 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
5527 struct smb_file_time ft
;
5528 uint32_t dosmode
= 0;
5529 NTSTATUS status
= NT_STATUS_OK
;
5531 init_smb_file_time(&ft
);
5533 if (total_data
< 36) {
5534 return NT_STATUS_INVALID_PARAMETER
;
5538 return NT_STATUS_INVALID_HANDLE
;
5541 status
= check_access_fsp(fsp
, FILE_WRITE_ATTRIBUTES
);
5542 if (!NT_STATUS_IS_OK(status
)) {
5546 /* Set the attributes */
5547 dosmode
= IVAL(pdata
,32);
5548 status
= smb_set_file_dosmode(conn
, fsp
, dosmode
);
5549 if (!NT_STATUS_IS_OK(status
)) {
5554 ft
.create_time
= pull_long_date_full_timespec(pdata
);
5557 ft
.atime
= pull_long_date_full_timespec(pdata
+8);
5560 ft
.mtime
= pull_long_date_full_timespec(pdata
+16);
5563 ft
.ctime
= pull_long_date_full_timespec(pdata
+24);
5565 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
5566 smb_fname_str_dbg(smb_fname
)));
5568 status
= smb_set_file_time(conn
, fsp
, smb_fname
, &ft
, true);
5569 if (!NT_STATUS_IS_OK(status
)) {
5573 if (fsp
->fsp_flags
.modified
) {
5574 trigger_write_time_update_immediate(fsp
);
5576 return NT_STATUS_OK
;
5579 /****************************************************************************
5580 Deal with SMB_INFO_STANDARD.
5581 ****************************************************************************/
5583 static NTSTATUS
smb_set_info_standard(connection_struct
*conn
,
5587 struct smb_filename
*smb_fname
)
5590 struct smb_file_time ft
;
5592 init_smb_file_time(&ft
);
5594 if (total_data
< 12) {
5595 return NT_STATUS_INVALID_PARAMETER
;
5599 return NT_STATUS_INVALID_HANDLE
;
5603 ft
.create_time
= time_t_to_full_timespec(srv_make_unix_date2(pdata
));
5605 ft
.atime
= time_t_to_full_timespec(srv_make_unix_date2(pdata
+4));
5607 ft
.mtime
= time_t_to_full_timespec(srv_make_unix_date2(pdata
+8));
5609 DEBUG(10,("smb_set_info_standard: file %s\n",
5610 smb_fname_str_dbg(smb_fname
)));
5612 status
= check_access_fsp(fsp
, FILE_WRITE_ATTRIBUTES
);
5613 if (!NT_STATUS_IS_OK(status
)) {
5617 status
= smb_set_file_time(conn
, fsp
, smb_fname
, &ft
, true);
5618 if (!NT_STATUS_IS_OK(status
)) {
5622 if (fsp
->fsp_flags
.modified
) {
5623 trigger_write_time_update_immediate(fsp
);
5625 return NT_STATUS_OK
;
5628 /****************************************************************************
5629 Deal with SMB_SET_FILE_ALLOCATION_INFO.
5630 ****************************************************************************/
5632 static NTSTATUS
smb_set_file_allocation_info(connection_struct
*conn
,
5633 struct smb_request
*req
,
5637 struct smb_filename
*smb_fname
)
5639 uint64_t allocation_size
= 0;
5640 NTSTATUS status
= NT_STATUS_OK
;
5641 files_struct
*new_fsp
= NULL
;
5643 if (!VALID_STAT(smb_fname
->st
)) {
5644 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5647 if (total_data
< 8) {
5648 return NT_STATUS_INVALID_PARAMETER
;
5651 allocation_size
= (uint64_t)IVAL(pdata
,0);
5652 allocation_size
|= (((uint64_t)IVAL(pdata
,4)) << 32);
5653 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
5654 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname
),
5655 (double)allocation_size
));
5657 if (allocation_size
) {
5658 allocation_size
= smb_roundup(conn
, allocation_size
);
5661 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
5662 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname
),
5663 (double)allocation_size
));
5666 !fsp
->fsp_flags
.is_pathref
&&
5667 fsp_get_io_fd(fsp
) != -1)
5669 /* Open file handle. */
5670 if (!(fsp
->access_mask
& FILE_WRITE_DATA
)) {
5671 return NT_STATUS_ACCESS_DENIED
;
5674 /* Only change if needed. */
5675 if (allocation_size
!= get_file_size_stat(&smb_fname
->st
)) {
5676 if (vfs_allocate_file_space(fsp
, allocation_size
) == -1) {
5677 return map_nt_error_from_unix(errno
);
5680 /* But always update the time. */
5682 * This is equivalent to a write. Ensure it's seen immediately
5683 * if there are no pending writes.
5685 trigger_write_time_update_immediate(fsp
);
5686 return NT_STATUS_OK
;
5689 /* Pathname or stat or directory file. */
5690 status
= SMB_VFS_CREATE_FILE(
5694 smb_fname
, /* fname */
5695 FILE_WRITE_DATA
, /* access_mask */
5696 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
5698 FILE_OPEN
, /* create_disposition*/
5699 0, /* create_options */
5700 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
5701 0, /* oplock_request */
5703 0, /* allocation_size */
5704 0, /* private_flags */
5707 &new_fsp
, /* result */
5709 NULL
, NULL
); /* create context */
5711 if (!NT_STATUS_IS_OK(status
)) {
5712 /* NB. We check for open_was_deferred in the caller. */
5716 /* Only change if needed. */
5717 if (allocation_size
!= get_file_size_stat(&smb_fname
->st
)) {
5718 if (vfs_allocate_file_space(new_fsp
, allocation_size
) == -1) {
5719 status
= map_nt_error_from_unix(errno
);
5720 close_file_free(req
, &new_fsp
, NORMAL_CLOSE
);
5725 /* Changing the allocation size should set the last mod time. */
5727 * This is equivalent to a write. Ensure it's seen immediately
5728 * if there are no pending writes.
5730 trigger_write_time_update_immediate(new_fsp
);
5731 close_file_free(req
, &new_fsp
, NORMAL_CLOSE
);
5732 return NT_STATUS_OK
;
5735 /****************************************************************************
5736 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
5737 ****************************************************************************/
5739 static NTSTATUS
smb_set_file_end_of_file_info(connection_struct
*conn
,
5740 struct smb_request
*req
,
5744 struct smb_filename
*smb_fname
,
5745 bool fail_after_createfile
)
5749 if (total_data
< 8) {
5750 return NT_STATUS_INVALID_PARAMETER
;
5753 size
= IVAL(pdata
,0);
5754 size
|= (((off_t
)IVAL(pdata
,4)) << 32);
5755 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
5756 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname
),
5759 return smb_set_file_size(conn
, req
,
5764 fail_after_createfile
);
5767 /****************************************************************************
5768 Allow a UNIX info mknod.
5769 ****************************************************************************/
5771 static NTSTATUS
smb_unix_mknod(connection_struct
*conn
,
5774 const struct smb_filename
*smb_fname
)
5776 uint32_t file_type
= IVAL(pdata
,56);
5777 #if defined(HAVE_MAKEDEV)
5778 uint32_t dev_major
= IVAL(pdata
,60);
5779 uint32_t dev_minor
= IVAL(pdata
,68);
5781 SMB_DEV_T dev
= (SMB_DEV_T
)0;
5782 uint32_t raw_unixmode
= IVAL(pdata
,84);
5786 struct smb_filename
*parent_fname
= NULL
;
5787 struct smb_filename
*base_name
= NULL
;
5789 if (total_data
< 100) {
5790 return NT_STATUS_INVALID_PARAMETER
;
5793 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
5794 PERM_NEW_FILE
, &unixmode
);
5795 if (!NT_STATUS_IS_OK(status
)) {
5799 #if defined(HAVE_MAKEDEV)
5800 dev
= makedev(dev_major
, dev_minor
);
5803 switch (file_type
) {
5804 /* We can't create other objects here. */
5805 case UNIX_TYPE_FILE
:
5807 case UNIX_TYPE_SYMLINK
:
5808 return NT_STATUS_ACCESS_DENIED
;
5809 #if defined(S_IFIFO)
5810 case UNIX_TYPE_FIFO
:
5811 unixmode
|= S_IFIFO
;
5814 #if defined(S_IFSOCK)
5815 case UNIX_TYPE_SOCKET
:
5816 unixmode
|= S_IFSOCK
;
5819 #if defined(S_IFCHR)
5820 case UNIX_TYPE_CHARDEV
:
5821 /* This is only allowed for root. */
5822 if (get_current_uid(conn
) != sec_initial_uid()) {
5823 return NT_STATUS_ACCESS_DENIED
;
5825 unixmode
|= S_IFCHR
;
5828 #if defined(S_IFBLK)
5829 case UNIX_TYPE_BLKDEV
:
5830 if (get_current_uid(conn
) != sec_initial_uid()) {
5831 return NT_STATUS_ACCESS_DENIED
;
5833 unixmode
|= S_IFBLK
;
5837 return NT_STATUS_INVALID_PARAMETER
;
5840 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
5841 "%.0f mode 0%o for file %s\n", (double)dev
,
5842 (unsigned int)unixmode
, smb_fname_str_dbg(smb_fname
)));
5844 status
= parent_pathref(talloc_tos(),
5849 if (!NT_STATUS_IS_OK(status
)) {
5853 /* Ok - do the mknod. */
5854 ret
= SMB_VFS_MKNODAT(conn
,
5861 TALLOC_FREE(parent_fname
);
5862 return map_nt_error_from_unix(errno
);
5865 /* If any of the other "set" calls fail we
5866 * don't want to end up with a half-constructed mknod.
5869 if (lp_inherit_permissions(SNUM(conn
))) {
5870 inherit_access_posix_acl(conn
,
5875 TALLOC_FREE(parent_fname
);
5877 return NT_STATUS_OK
;
5880 /****************************************************************************
5881 Deal with SMB_SET_FILE_UNIX_BASIC.
5882 ****************************************************************************/
5884 static NTSTATUS
smb_set_file_unix_basic(connection_struct
*conn
,
5885 struct smb_request
*req
,
5889 struct smb_filename
*smb_fname
)
5891 struct smb_file_time ft
;
5892 uint32_t raw_unixmode
;
5895 uid_t set_owner
= (uid_t
)SMB_UID_NO_CHANGE
;
5896 gid_t set_grp
= (uid_t
)SMB_GID_NO_CHANGE
;
5897 NTSTATUS status
= NT_STATUS_OK
;
5898 enum perm_type ptype
;
5899 files_struct
*all_fsps
= NULL
;
5900 bool modify_mtime
= true;
5902 SMB_STRUCT_STAT sbuf
;
5904 init_smb_file_time(&ft
);
5906 if (total_data
< 100) {
5907 return NT_STATUS_INVALID_PARAMETER
;
5910 if(IVAL(pdata
, 0) != SMB_SIZE_NO_CHANGE_LO
&&
5911 IVAL(pdata
, 4) != SMB_SIZE_NO_CHANGE_HI
) {
5912 size
=IVAL(pdata
,0); /* first 8 Bytes are size */
5913 size
|= (((off_t
)IVAL(pdata
,4)) << 32);
5916 ft
.atime
= pull_long_date_full_timespec(pdata
+24); /* access_time */
5917 ft
.mtime
= pull_long_date_full_timespec(pdata
+32); /* modification_time */
5918 set_owner
= (uid_t
)IVAL(pdata
,40);
5919 set_grp
= (gid_t
)IVAL(pdata
,48);
5920 raw_unixmode
= IVAL(pdata
,84);
5922 if (VALID_STAT(smb_fname
->st
)) {
5923 if (S_ISDIR(smb_fname
->st
.st_ex_mode
)) {
5924 ptype
= PERM_EXISTING_DIR
;
5926 ptype
= PERM_EXISTING_FILE
;
5929 ptype
= PERM_NEW_FILE
;
5932 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
5934 if (!NT_STATUS_IS_OK(status
)) {
5938 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
5939 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
5940 smb_fname_str_dbg(smb_fname
), (double)size
,
5941 (unsigned int)set_owner
, (unsigned int)set_grp
,
5942 (int)raw_unixmode
));
5944 sbuf
= smb_fname
->st
;
5946 if (!VALID_STAT(sbuf
)) {
5948 * The only valid use of this is to create character and block
5949 * devices, and named pipes. This is deprecated (IMHO) and
5950 * a new info level should be used for mknod. JRA.
5953 return smb_unix_mknod(conn
,
5960 /* Horrible backwards compatibility hack as an old server bug
5961 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
5965 size
= get_file_size_stat(&sbuf
);
5970 * Deal with the UNIX specific mode set.
5973 if (raw_unixmode
!= SMB_MODE_NO_CHANGE
) {
5976 if (fsp
== NULL
|| S_ISLNK(smb_fname
->st
.st_ex_mode
)) {
5977 DBG_WARNING("Can't set mode on symlink %s\n",
5978 smb_fname_str_dbg(smb_fname
));
5979 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5982 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
5983 "setting mode 0%o for file %s\n",
5984 (unsigned int)unixmode
,
5985 smb_fname_str_dbg(smb_fname
)));
5986 ret
= SMB_VFS_FCHMOD(fsp
, unixmode
);
5988 return map_nt_error_from_unix(errno
);
5993 * Deal with the UNIX specific uid set.
5996 if ((set_owner
!= (uid_t
)SMB_UID_NO_CHANGE
) &&
5997 (sbuf
.st_ex_uid
!= set_owner
)) {
6000 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6001 "changing owner %u for path %s\n",
6002 (unsigned int)set_owner
,
6003 smb_fname_str_dbg(smb_fname
)));
6006 !fsp
->fsp_flags
.is_pathref
&&
6007 fsp_get_io_fd(fsp
) != -1)
6009 ret
= SMB_VFS_FCHOWN(fsp
, set_owner
, (gid_t
)-1);
6012 * UNIX extensions calls must always operate
6015 ret
= SMB_VFS_LCHOWN(conn
, smb_fname
,
6016 set_owner
, (gid_t
)-1);
6020 status
= map_nt_error_from_unix(errno
);
6026 * Deal with the UNIX specific gid set.
6029 if ((set_grp
!= (uid_t
)SMB_GID_NO_CHANGE
) &&
6030 (sbuf
.st_ex_gid
!= set_grp
)) {
6033 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6034 "changing group %u for file %s\n",
6035 (unsigned int)set_grp
,
6036 smb_fname_str_dbg(smb_fname
)));
6038 !fsp
->fsp_flags
.is_pathref
&&
6039 fsp_get_io_fd(fsp
) != -1)
6041 ret
= SMB_VFS_FCHOWN(fsp
, (uid_t
)-1, set_grp
);
6044 * UNIX extensions calls must always operate
6047 ret
= SMB_VFS_LCHOWN(conn
, smb_fname
, (uid_t
)-1,
6051 status
= map_nt_error_from_unix(errno
);
6056 /* Deal with any size changes. */
6058 if (S_ISREG(sbuf
.st_ex_mode
)) {
6059 status
= smb_set_file_size(conn
, req
,
6065 if (!NT_STATUS_IS_OK(status
)) {
6070 /* Deal with any time changes. */
6071 if (is_omit_timespec(&ft
.mtime
) && is_omit_timespec(&ft
.atime
)) {
6072 /* No change, don't cancel anything. */
6076 id
= vfs_file_id_from_sbuf(conn
, &sbuf
);
6077 for(all_fsps
= file_find_di_first(conn
->sconn
, id
, true); all_fsps
;
6078 all_fsps
= file_find_di_next(all_fsps
, true)) {
6080 * We're setting the time explicitly for UNIX.
6081 * Cancel any pending changes over all handles.
6083 all_fsps
->fsp_flags
.update_write_time_on_close
= false;
6084 TALLOC_FREE(all_fsps
->update_write_time_event
);
6088 * Override the "setting_write_time"
6089 * parameter here as it almost does what
6090 * we need. Just remember if we modified
6091 * mtime and send the notify ourselves.
6093 if (is_omit_timespec(&ft
.mtime
)) {
6094 modify_mtime
= false;
6097 status
= smb_set_file_time(conn
,
6103 notify_fname(conn
, NOTIFY_ACTION_MODIFIED
,
6104 FILE_NOTIFY_CHANGE_LAST_WRITE
, smb_fname
->base_name
);
6109 /****************************************************************************
6110 Deal with SMB_SET_FILE_UNIX_INFO2.
6111 ****************************************************************************/
6113 static NTSTATUS
smb_set_file_unix_info2(connection_struct
*conn
,
6114 struct smb_request
*req
,
6118 struct smb_filename
*smb_fname
)
6121 uint32_t smb_fflags
;
6124 if (total_data
< 116) {
6125 return NT_STATUS_INVALID_PARAMETER
;
6128 /* Start by setting all the fields that are common between UNIX_BASIC
6131 status
= smb_set_file_unix_basic(conn
, req
, pdata
, total_data
,
6133 if (!NT_STATUS_IS_OK(status
)) {
6137 smb_fflags
= IVAL(pdata
, 108);
6138 smb_fmask
= IVAL(pdata
, 112);
6140 /* NB: We should only attempt to alter the file flags if the client
6141 * sends a non-zero mask.
6143 if (smb_fmask
!= 0) {
6144 int stat_fflags
= 0;
6146 if (!map_info2_flags_to_sbuf(&smb_fname
->st
, smb_fflags
,
6147 smb_fmask
, &stat_fflags
)) {
6148 /* Client asked to alter a flag we don't understand. */
6149 return NT_STATUS_INVALID_PARAMETER
;
6152 if (fsp
== NULL
|| S_ISLNK(smb_fname
->st
.st_ex_mode
)) {
6153 DBG_WARNING("Can't change flags on symlink %s\n",
6154 smb_fname_str_dbg(smb_fname
));
6155 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
6157 if (SMB_VFS_FCHFLAGS(fsp
, stat_fflags
) != 0) {
6158 return map_nt_error_from_unix(errno
);
6162 /* XXX: need to add support for changing the create_time here. You
6163 * can do this for paths on Darwin with setattrlist(2). The right way
6164 * to hook this up is probably by extending the VFS utimes interface.
6167 return NT_STATUS_OK
;
6170 static NTSTATUS
smbd_do_posix_setfilepathinfo(struct connection_struct
*conn
,
6171 struct smb_request
*req
,
6172 TALLOC_CTX
*mem_ctx
,
6173 uint16_t info_level
,
6174 struct smb_filename
*smb_fname
,
6180 char *pdata
= *ppdata
;
6181 NTSTATUS status
= NT_STATUS_OK
;
6182 int data_return_size
= 0;
6186 if (!CAN_WRITE(conn
)) {
6187 /* Allow POSIX opens. The open path will deny
6188 * any non-readonly opens. */
6189 if (info_level
!= SMB_POSIX_PATH_OPEN
) {
6190 return NT_STATUS_DOS(ERRSRV
, ERRaccess
);
6194 DBG_DEBUG("file=%s (%s) info_level=%d totdata=%d\n",
6195 smb_fname_str_dbg(smb_fname
),
6200 switch (info_level
) {
6201 case SMB_SET_FILE_UNIX_BASIC
:
6203 status
= smb_set_file_unix_basic(conn
, req
,
6211 case SMB_SET_FILE_UNIX_INFO2
:
6213 status
= smb_set_file_unix_info2(conn
, req
,
6221 #if defined(HAVE_POSIX_ACLS)
6222 case SMB_SET_POSIX_ACL
:
6224 status
= smb_set_posix_acl(conn
,
6234 #if defined(WITH_SMB1SERVER)
6235 case SMB_SET_POSIX_LOCK
:
6238 return NT_STATUS_INVALID_LEVEL
;
6240 status
= smb_set_posix_lock(conn
, req
,
6241 pdata
, total_data
, fsp
);
6247 return NT_STATUS_INVALID_LEVEL
;
6250 if (!NT_STATUS_IS_OK(status
)) {
6254 *ret_data_size
= data_return_size
;
6255 return NT_STATUS_OK
;
6258 NTSTATUS
smbd_do_setfilepathinfo(connection_struct
*conn
,
6259 struct smb_request
*req
,
6260 TALLOC_CTX
*mem_ctx
,
6261 uint16_t info_level
,
6263 struct smb_filename
*smb_fname
,
6264 char **ppdata
, int total_data
,
6267 char *pdata
= *ppdata
;
6268 NTSTATUS status
= NT_STATUS_OK
;
6269 int data_return_size
= 0;
6271 if (INFO_LEVEL_IS_UNIX(info_level
)) {
6272 if (!lp_smb1_unix_extensions()) {
6273 return NT_STATUS_INVALID_LEVEL
;
6275 if (!req
->posix_pathnames
) {
6276 return NT_STATUS_INVALID_LEVEL
;
6278 status
= smbd_do_posix_setfilepathinfo(conn
,
6287 if (!NT_STATUS_IS_OK(status
)) {
6290 *ret_data_size
= data_return_size
;
6291 return NT_STATUS_OK
;
6296 DEBUG(3,("smbd_do_setfilepathinfo: %s (%s) info_level=%d "
6297 "totdata=%d\n", smb_fname_str_dbg(smb_fname
),
6299 info_level
, total_data
));
6301 switch (info_level
) {
6303 case SMB_INFO_STANDARD
:
6305 status
= smb_set_info_standard(conn
,
6313 case SMB_INFO_SET_EA
:
6315 status
= smb_info_set_ea(conn
,
6323 case SMB_SET_FILE_BASIC_INFO
:
6324 case SMB_FILE_BASIC_INFORMATION
:
6326 status
= smb_set_file_basic_info(conn
,
6334 case SMB_FILE_ALLOCATION_INFORMATION
:
6335 case SMB_SET_FILE_ALLOCATION_INFO
:
6337 status
= smb_set_file_allocation_info(conn
, req
,
6345 case SMB_FILE_END_OF_FILE_INFORMATION
:
6346 case SMB_SET_FILE_END_OF_FILE_INFO
:
6349 * XP/Win7 both fail after the createfile with
6350 * SMB_SET_FILE_END_OF_FILE_INFO but not
6351 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
6352 * The level is known here, so pass it down
6356 (info_level
== SMB_SET_FILE_END_OF_FILE_INFO
);
6358 status
= smb_set_file_end_of_file_info(conn
, req
,
6367 case SMB_FILE_DISPOSITION_INFORMATION
:
6368 case SMB_SET_FILE_DISPOSITION_INFO
: /* Set delete on close for open file. */
6371 /* JRA - We used to just ignore this on a path ?
6372 * Shouldn't this be invalid level on a pathname
6375 if (tran_call
!= TRANSACT2_SETFILEINFO
) {
6376 return ERROR_NT(NT_STATUS_INVALID_LEVEL
);
6379 status
= smb_set_file_disposition_info(conn
,
6387 case SMB_FILE_POSITION_INFORMATION
:
6389 status
= smb_file_position_information(conn
,
6396 case SMB_FILE_FULL_EA_INFORMATION
:
6398 status
= smb_set_file_full_ea_info(conn
,
6405 /* From tridge Samba4 :
6406 * MODE_INFORMATION in setfileinfo (I have no
6407 * idea what "mode information" on a file is - it takes a value of 0,
6408 * 2, 4 or 6. What could it be?).
6411 case SMB_FILE_MODE_INFORMATION
:
6413 status
= smb_file_mode_information(conn
,
6419 /* [MS-SMB2] 3.3.5.21.1 states we MUST fail with STATUS_NOT_SUPPORTED. */
6420 case SMB_FILE_VALID_DATA_LENGTH_INFORMATION
:
6421 case SMB_FILE_SHORT_NAME_INFORMATION
:
6422 return NT_STATUS_NOT_SUPPORTED
;
6424 case SMB_FILE_RENAME_INFORMATION
:
6426 status
= smb_file_rename_information(conn
, req
,
6432 case SMB2_FILE_RENAME_INFORMATION_INTERNAL
:
6434 /* SMB2 rename information. */
6435 status
= smb2_file_rename_information(conn
, req
,
6441 case SMB_FILE_LINK_INFORMATION
:
6443 status
= smb_file_link_information(conn
, req
,
6450 return NT_STATUS_INVALID_LEVEL
;
6453 if (!NT_STATUS_IS_OK(status
)) {
6457 *ret_data_size
= data_return_size
;
6458 return NT_STATUS_OK
;
6461 static uint32_t generate_volume_serial_number(
6462 const struct loadparm_substitution
*lp_sub
,
6465 int serial
= lp_volume_serial_number(snum
);
6466 return serial
!= -1 ? serial
:
6467 str_checksum(lp_servicename(talloc_tos(), lp_sub
, snum
)) ^
6468 (str_checksum(get_local_machine_name())<<16);