2 Unix SMB/CIFS implementation.
3 SMB transaction2 handling
4 Copyright (C) Jeremy Allison 1994-2007
5 Copyright (C) Stefan (metze) Metzmacher 2003
6 Copyright (C) Volker Lendecke 2005-2007
7 Copyright (C) Steve French 2005
8 Copyright (C) James Peach 2006-2007
10 Extensively modified by Andrew Tridgell, 1995
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 3 of the License, or
15 (at your option) any later version.
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with this program. If not, see <http://www.gnu.org/licenses/>.
28 #include "system/filesys.h"
29 #include "lib/util/time_basic.h"
31 #include "smbd/smbd.h"
32 #include "smbd/globals.h"
33 #include "../libcli/auth/libcli_auth.h"
34 #include "../librpc/gen_ndr/xattr.h"
35 #include "../librpc/gen_ndr/ndr_security.h"
36 #include "libcli/security/security.h"
39 #include "smbprofile.h"
40 #include "rpc_server/srv_pipe_hnd.h"
42 #include "lib/util_ea.h"
43 #include "lib/readdir_attr.h"
45 #include "libcli/smb/smb2_posix.h"
46 #include "lib/util/string_wrappers.h"
47 #include "source3/lib/substitute.h"
48 #include "source3/lib/adouble.h"
50 #define DIR_ENTRY_SAFETY_MARGIN 4096
52 static char *store_file_unix_basic(connection_struct
*conn
,
55 const SMB_STRUCT_STAT
*psbuf
);
57 static char *store_file_unix_basic_info2(connection_struct
*conn
,
60 const SMB_STRUCT_STAT
*psbuf
);
62 /****************************************************************************
63 Check if an open file handle is a symlink.
64 ****************************************************************************/
66 NTSTATUS
refuse_symlink_fsp(const files_struct
*fsp
)
69 if (!VALID_STAT(fsp
->fsp_name
->st
)) {
70 return NT_STATUS_ACCESS_DENIED
;
72 if (S_ISLNK(fsp
->fsp_name
->st
.st_ex_mode
)) {
73 return NT_STATUS_ACCESS_DENIED
;
75 if (fsp_get_pathref_fd(fsp
) == -1) {
76 return NT_STATUS_ACCESS_DENIED
;
81 NTSTATUS
check_access_fsp(struct files_struct
*fsp
,
84 if (!fsp
->fsp_flags
.is_fsa
) {
85 return smbd_check_access_rights_fsp(fsp
->conn
->cwd_fsp
,
90 if (!(fsp
->access_mask
& access_mask
)) {
91 return NT_STATUS_ACCESS_DENIED
;
96 #if defined(HAVE_POSIX_ACLS)
97 /****************************************************************************
98 Utility function to open a fsp for a POSIX handle operation.
99 ****************************************************************************/
101 static NTSTATUS
get_posix_fsp(connection_struct
*conn
,
102 struct smb_request
*req
,
103 struct smb_filename
*smb_fname
,
104 uint32_t access_mask
,
105 files_struct
**ret_fsp
)
108 uint32_t create_disposition
= FILE_OPEN
;
109 uint32_t share_access
= FILE_SHARE_READ
|
112 struct smb2_create_blobs
*posx
= NULL
;
115 * Only FILE_FLAG_POSIX_SEMANTICS matters on existing files,
116 * but set reasonable defaults.
118 uint32_t file_attributes
= 0664;
119 uint32_t oplock
= NO_OPLOCK
;
120 uint32_t create_options
= FILE_NON_DIRECTORY_FILE
;
122 /* File or directory must exist. */
123 if (!VALID_STAT(smb_fname
->st
)) {
124 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
126 /* Cannot be a symlink. */
127 if (S_ISLNK(smb_fname
->st
.st_ex_mode
)) {
128 return NT_STATUS_ACCESS_DENIED
;
130 /* Set options correctly for directory open. */
131 if (S_ISDIR(smb_fname
->st
.st_ex_mode
)) {
133 * Only FILE_FLAG_POSIX_SEMANTICS matters on existing
134 * directories, but set reasonable defaults.
136 file_attributes
= 0775;
137 create_options
= FILE_DIRECTORY_FILE
;
140 status
= make_smb2_posix_create_ctx(
141 talloc_tos(), &posx
, file_attributes
);
142 if (!NT_STATUS_IS_OK(status
)) {
143 DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
148 status
= SMB_VFS_CREATE_FILE(
151 smb_fname
, /* fname */
152 access_mask
, /* access_mask */
153 share_access
, /* share_access */
154 create_disposition
,/* create_disposition*/
155 create_options
, /* create_options */
156 file_attributes
,/* file_attributes */
157 oplock
, /* oplock_request */
159 0, /* allocation_size */
160 0, /* private_flags */
163 ret_fsp
, /* result */
165 posx
, /* in_context */
166 NULL
); /* out_context */
174 /********************************************************************
175 Roundup a value to the nearest allocation roundup size boundary.
176 Only do this for Windows clients.
177 ********************************************************************/
179 uint64_t smb_roundup(connection_struct
*conn
, uint64_t val
)
181 uint64_t rval
= lp_allocation_roundup_size(SNUM(conn
));
183 /* Only roundup for Windows clients. */
184 enum remote_arch_types ra_type
= get_remote_arch();
185 if (rval
&& (ra_type
!= RA_SAMBA
) && (ra_type
!= RA_CIFSFS
)) {
186 val
= SMB_ROUNDUP(val
,rval
);
191 /****************************************************************************
192 Utility functions for dealing with extended attributes.
193 ****************************************************************************/
195 /****************************************************************************
196 Refuse to allow clients to overwrite our private xattrs.
197 ****************************************************************************/
199 bool samba_private_attr_name(const char *unix_ea_name
)
201 static const char * const prohibited_ea_names
[] = {
202 SAMBA_POSIX_INHERITANCE_EA_NAME
,
203 SAMBA_XATTR_DOS_ATTRIB
,
212 for (i
= 0; prohibited_ea_names
[i
]; i
++) {
213 if (strequal( prohibited_ea_names
[i
], unix_ea_name
))
216 if (strncasecmp_m(unix_ea_name
, SAMBA_XATTR_DOSSTREAM_PREFIX
,
217 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX
)) == 0) {
223 /****************************************************************************
224 Get one EA value. Fill in a struct ea_struct.
225 ****************************************************************************/
227 NTSTATUS
get_ea_value_fsp(TALLOC_CTX
*mem_ctx
,
230 struct ea_struct
*pea
)
232 /* Get the value of this xattr. Max size is 64k. */
233 size_t attr_size
= 256;
236 size_t max_xattr_size
= 0;
239 return NT_STATUS_INVALID_HANDLE
;
242 max_xattr_size
= lp_smbd_max_xattr_size(SNUM(fsp
->conn
));
246 val
= talloc_realloc(mem_ctx
, val
, char, attr_size
);
248 return NT_STATUS_NO_MEMORY
;
251 sizeret
= SMB_VFS_FGETXATTR(fsp
, ea_name
, val
, attr_size
);
252 if (sizeret
== -1 && errno
== ERANGE
&& attr_size
< max_xattr_size
) {
253 attr_size
= max_xattr_size
;
258 return map_nt_error_from_unix(errno
);
261 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name
, (unsigned int)sizeret
));
262 dump_data(10, (uint8_t *)val
, sizeret
);
265 if (strnequal(ea_name
, "user.", 5)) {
266 pea
->name
= talloc_strdup(mem_ctx
, &ea_name
[5]);
268 pea
->name
= talloc_strdup(mem_ctx
, ea_name
);
270 if (pea
->name
== NULL
) {
272 return NT_STATUS_NO_MEMORY
;
274 pea
->value
.data
= (unsigned char *)val
;
275 pea
->value
.length
= (size_t)sizeret
;
279 NTSTATUS
get_ea_names_from_fsp(TALLOC_CTX
*mem_ctx
,
285 /* Get a list of all xattrs. Max namesize is 64k. */
286 size_t ea_namelist_size
= 1024;
287 char *ea_namelist
= smallbuf
;
288 char *to_free
= NULL
;
293 ssize_t sizeret
= -1;
303 * Callers may pass fsp == NULL when passing smb_fname->fsp of a
304 * symlink. This is ok, handle it here, by just return no EA's
310 /* should be the case that fsp != NULL */
311 SMB_ASSERT(fsp
!= NULL
);
313 sizeret
= SMB_VFS_FLISTXATTR(fsp
, ea_namelist
,
316 if ((sizeret
== -1) && (errno
== ERANGE
)) {
317 ea_namelist_size
= 65536;
318 ea_namelist
= talloc_array(mem_ctx
, char, ea_namelist_size
);
319 if (ea_namelist
== NULL
) {
320 return NT_STATUS_NO_MEMORY
;
322 to_free
= ea_namelist
;
324 sizeret
= SMB_VFS_FLISTXATTR(fsp
, ea_namelist
,
329 status
= map_nt_error_from_unix(errno
);
330 TALLOC_FREE(to_free
);
334 DBG_DEBUG("ea_namelist size = %zd\n", sizeret
);
337 TALLOC_FREE(to_free
);
342 * Ensure the result is 0-terminated
345 if (ea_namelist
[sizeret
-1] != '\0') {
346 TALLOC_FREE(to_free
);
347 return NT_STATUS_INTERNAL_ERROR
;
355 for (p
= ea_namelist
; p
- ea_namelist
< sizeret
; p
+= strlen(p
)+1) {
359 *pnum_names
= num_names
;
361 if (pnames
== NULL
) {
362 TALLOC_FREE(to_free
);
366 names
= talloc_array(mem_ctx
, char *, num_names
);
368 DEBUG(0, ("talloc failed\n"));
369 TALLOC_FREE(to_free
);
370 return NT_STATUS_NO_MEMORY
;
373 if (ea_namelist
== smallbuf
) {
374 ea_namelist
= talloc_memdup(names
, smallbuf
, sizeret
);
375 if (ea_namelist
== NULL
) {
377 return NT_STATUS_NO_MEMORY
;
380 talloc_steal(names
, ea_namelist
);
382 ea_namelist
= talloc_realloc(names
, ea_namelist
, char,
384 if (ea_namelist
== NULL
) {
386 return NT_STATUS_NO_MEMORY
;
392 for (p
= ea_namelist
; p
- ea_namelist
< sizeret
; p
+= strlen(p
)+1) {
393 names
[num_names
++] = p
;
401 /****************************************************************************
402 Return a linked list of the total EA's. Plus the total size
403 ****************************************************************************/
405 static NTSTATUS
get_ea_list_from_fsp(TALLOC_CTX
*mem_ctx
,
407 size_t *pea_total_len
,
408 struct ea_list
**ea_list
)
410 /* Get a list of all xattrs. Max namesize is 64k. */
413 struct ea_list
*ea_list_head
= NULL
;
414 bool posix_pathnames
= false;
425 if (!lp_ea_support(SNUM(fsp
->conn
))) {
429 if (fsp_is_alternate_stream(fsp
)) {
430 return NT_STATUS_INVALID_PARAMETER
;
433 posix_pathnames
= (fsp
->fsp_name
->flags
& SMB_FILENAME_POSIX_PATH
);
435 status
= get_ea_names_from_fsp(talloc_tos(),
440 if (!NT_STATUS_IS_OK(status
)) {
444 if (num_names
== 0) {
448 for (i
=0; i
<num_names
; i
++) {
449 struct ea_list
*listp
;
452 if (strnequal(names
[i
], "system.", 7)
453 || samba_private_attr_name(names
[i
]))
457 * Filter out any underlying POSIX EA names
458 * that a Windows client can't handle.
460 if (!posix_pathnames
&&
461 is_invalid_windows_ea_name(names
[i
])) {
465 listp
= talloc(mem_ctx
, struct ea_list
);
467 return NT_STATUS_NO_MEMORY
;
470 status
= get_ea_value_fsp(listp
,
475 if (!NT_STATUS_IS_OK(status
)) {
480 if (listp
->ea
.value
.length
== 0) {
482 * We can never return a zero length EA.
483 * Windows reports the EA's as corrupted.
487 } else if (listp
->ea
.value
.length
> 65536) {
489 * SMB clients may report error with file
490 * if large EA is presented to them.
492 DBG_ERR("EA [%s] on file [%s] exceeds "
493 "maximum permitted EA size of 64KiB: %zu\n.",
494 listp
->ea
.name
, fsp_str_dbg(fsp
),
495 listp
->ea
.value
.length
);
500 push_ascii_fstring(dos_ea_name
, listp
->ea
.name
);
503 4 + strlen(dos_ea_name
) + 1 + listp
->ea
.value
.length
;
505 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
506 "= %u\n", (unsigned int)*pea_total_len
, dos_ea_name
,
507 (unsigned int)listp
->ea
.value
.length
));
509 DLIST_ADD_END(ea_list_head
, listp
);
513 /* Add on 4 for total length. */
514 if (*pea_total_len
) {
518 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
519 (unsigned int)*pea_total_len
));
521 *ea_list
= ea_list_head
;
525 /****************************************************************************
526 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
528 ****************************************************************************/
530 static unsigned int fill_ea_buffer(TALLOC_CTX
*mem_ctx
, char *pdata
, unsigned int total_data_size
,
531 connection_struct
*conn
, struct ea_list
*ea_list
)
533 unsigned int ret_data_size
= 4;
536 SMB_ASSERT(total_data_size
>= 4);
538 if (!lp_ea_support(SNUM(conn
))) {
543 for (p
= pdata
+ 4; ea_list
; ea_list
= ea_list
->next
) {
546 push_ascii_fstring(dos_ea_name
, ea_list
->ea
.name
);
547 dos_namelen
= strlen(dos_ea_name
);
548 if (dos_namelen
> 255 || dos_namelen
== 0) {
551 if (ea_list
->ea
.value
.length
> 65535) {
554 if (4 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
> total_data_size
) {
558 /* We know we have room. */
559 SCVAL(p
,0,ea_list
->ea
.flags
);
560 SCVAL(p
,1,dos_namelen
);
561 SSVAL(p
,2,ea_list
->ea
.value
.length
);
562 strlcpy(p
+4, dos_ea_name
, dos_namelen
+1);
563 if (ea_list
->ea
.value
.length
> 0) {
564 memcpy(p
+ 4 + dos_namelen
+ 1,
565 ea_list
->ea
.value
.data
,
566 ea_list
->ea
.value
.length
);
569 total_data_size
-= 4 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
;
570 p
+= 4 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
;
573 ret_data_size
= PTR_DIFF(p
, pdata
);
574 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size
));
575 SIVAL(pdata
,0,ret_data_size
);
576 return ret_data_size
;
579 static NTSTATUS
fill_ea_chained_buffer(TALLOC_CTX
*mem_ctx
,
581 unsigned int total_data_size
,
582 unsigned int *ret_data_size
,
583 connection_struct
*conn
,
584 struct ea_list
*ea_list
)
586 uint8_t *p
= (uint8_t *)pdata
;
587 uint8_t *last_start
= NULL
;
588 bool do_store_data
= (pdata
!= NULL
);
592 if (!lp_ea_support(SNUM(conn
))) {
593 return NT_STATUS_NO_EAS_ON_FILE
;
596 for (; ea_list
; ea_list
= ea_list
->next
) {
602 if (last_start
!= NULL
&& do_store_data
) {
603 SIVAL(last_start
, 0, PTR_DIFF(p
, last_start
));
607 push_ascii_fstring(dos_ea_name
, ea_list
->ea
.name
);
608 dos_namelen
= strlen(dos_ea_name
);
609 if (dos_namelen
> 255 || dos_namelen
== 0) {
610 return NT_STATUS_INTERNAL_ERROR
;
612 if (ea_list
->ea
.value
.length
> 65535) {
613 return NT_STATUS_INTERNAL_ERROR
;
616 this_size
= 0x08 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
;
619 pad
= (4 - (this_size
% 4)) % 4;
624 if (this_size
> total_data_size
) {
625 return NT_STATUS_INFO_LENGTH_MISMATCH
;
628 /* We know we have room. */
629 SIVAL(p
, 0x00, 0); /* next offset */
630 SCVAL(p
, 0x04, ea_list
->ea
.flags
);
631 SCVAL(p
, 0x05, dos_namelen
);
632 SSVAL(p
, 0x06, ea_list
->ea
.value
.length
);
633 strlcpy((char *)(p
+0x08), dos_ea_name
, dos_namelen
+1);
634 memcpy(p
+ 0x08 + dos_namelen
+ 1, ea_list
->ea
.value
.data
, ea_list
->ea
.value
.length
);
636 memset(p
+ 0x08 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
,
640 total_data_size
-= this_size
;
646 *ret_data_size
= PTR_DIFF(p
, pdata
);
647 DEBUG(10,("fill_ea_chained_buffer: data_size = %u\n", *ret_data_size
));
651 unsigned int estimate_ea_size(files_struct
*fsp
)
653 size_t total_ea_len
= 0;
655 struct ea_list
*ea_list
= NULL
;
663 if (!lp_ea_support(SNUM(fsp
->conn
))) {
667 mem_ctx
= talloc_stackframe();
669 /* If this is a stream fsp, then we need to instead find the
670 * estimated ea len from the main file, not the stream
671 * (streams cannot have EAs), but the estimate isn't just 0 in
673 fsp
= metadata_fsp(fsp
);
674 (void)get_ea_list_from_fsp(mem_ctx
,
679 if(fsp
->conn
->sconn
->using_smb2
) {
680 unsigned int ret_data_size
;
682 * We're going to be using fill_ea_chained_buffer() to
683 * marshall EA's - this size is significantly larger
684 * than the SMB1 buffer. Re-calculate the size without
687 status
= fill_ea_chained_buffer(mem_ctx
,
693 if (!NT_STATUS_IS_OK(status
)) {
696 total_ea_len
= ret_data_size
;
698 TALLOC_FREE(mem_ctx
);
702 /****************************************************************************
703 Ensure the EA name is case insensitive by matching any existing EA name.
704 ****************************************************************************/
706 static void canonicalize_ea_name(files_struct
*fsp
,
707 fstring unix_ea_name
)
710 TALLOC_CTX
*mem_ctx
= talloc_tos();
711 struct ea_list
*ea_list
;
712 NTSTATUS status
= get_ea_list_from_fsp(mem_ctx
,
716 if (!NT_STATUS_IS_OK(status
)) {
720 for (; ea_list
; ea_list
= ea_list
->next
) {
721 if (strequal(&unix_ea_name
[5], ea_list
->ea
.name
)) {
722 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
723 &unix_ea_name
[5], ea_list
->ea
.name
));
724 strlcpy(&unix_ea_name
[5], ea_list
->ea
.name
, sizeof(fstring
)-5);
730 /****************************************************************************
731 Set or delete an extended attribute.
732 ****************************************************************************/
734 NTSTATUS
set_ea(connection_struct
*conn
, files_struct
*fsp
,
735 struct ea_list
*ea_list
)
738 bool posix_pathnames
= false;
740 if (!lp_ea_support(SNUM(conn
))) {
741 return NT_STATUS_EAS_NOT_SUPPORTED
;
745 return NT_STATUS_INVALID_HANDLE
;
748 posix_pathnames
= (fsp
->fsp_name
->flags
& SMB_FILENAME_POSIX_PATH
);
750 status
= refuse_symlink_fsp(fsp
);
751 if (!NT_STATUS_IS_OK(status
)) {
755 status
= check_access_fsp(fsp
, FILE_WRITE_EA
);
756 if (!NT_STATUS_IS_OK(status
)) {
760 /* Setting EAs on streams isn't supported. */
761 if (fsp_is_alternate_stream(fsp
)) {
762 return NT_STATUS_INVALID_PARAMETER
;
766 * Filter out invalid Windows EA names - before
767 * we set *any* of them.
770 if (!posix_pathnames
&& ea_list_has_invalid_name(ea_list
)) {
771 return STATUS_INVALID_EA_NAME
;
774 for (;ea_list
; ea_list
= ea_list
->next
) {
776 fstring unix_ea_name
;
778 fstrcpy(unix_ea_name
, "user."); /* All EA's must start with user. */
779 fstrcat(unix_ea_name
, ea_list
->ea
.name
);
781 canonicalize_ea_name(fsp
, unix_ea_name
);
783 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name
, (unsigned int)ea_list
->ea
.value
.length
));
785 if (samba_private_attr_name(unix_ea_name
)) {
786 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name
));
787 return NT_STATUS_ACCESS_DENIED
;
790 if (ea_list
->ea
.value
.length
== 0) {
791 /* Remove the attribute. */
792 DBG_DEBUG("deleting ea name %s on "
793 "file %s by file descriptor.\n",
794 unix_ea_name
, fsp_str_dbg(fsp
));
795 ret
= SMB_VFS_FREMOVEXATTR(fsp
, unix_ea_name
);
797 /* Removing a non existent attribute always succeeds. */
798 if (ret
== -1 && errno
== ENOATTR
) {
799 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
805 DEBUG(10,("set_ea: setting ea name %s on file "
806 "%s by file descriptor.\n",
807 unix_ea_name
, fsp_str_dbg(fsp
)));
808 ret
= SMB_VFS_FSETXATTR(fsp
, unix_ea_name
,
809 ea_list
->ea
.value
.data
, ea_list
->ea
.value
.length
, 0);
814 if (errno
== ENOTSUP
) {
815 return NT_STATUS_EAS_NOT_SUPPORTED
;
818 return map_nt_error_from_unix(errno
);
825 /****************************************************************************
826 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
827 ****************************************************************************/
829 struct ea_list
*read_ea_list(TALLOC_CTX
*ctx
, const char *pdata
, size_t data_size
)
831 struct ea_list
*ea_list_head
= NULL
;
833 size_t bytes_used
= 0;
835 while (offset
< data_size
) {
836 struct ea_list
*eal
= read_ea_list_entry(ctx
, pdata
+ offset
, data_size
- offset
, &bytes_used
);
842 DLIST_ADD_END(ea_list_head
, eal
);
843 offset
+= bytes_used
;
849 /****************************************************************************
850 Count the total EA size needed.
851 ****************************************************************************/
853 static size_t ea_list_size(struct ea_list
*ealist
)
856 struct ea_list
*listp
;
859 for (listp
= ealist
; listp
; listp
= listp
->next
) {
860 push_ascii_fstring(dos_ea_name
, listp
->ea
.name
);
861 ret
+= 4 + strlen(dos_ea_name
) + 1 + listp
->ea
.value
.length
;
863 /* Add on 4 for total length. */
871 /****************************************************************************
872 Return a union of EA's from a file list and a list of names.
873 The TALLOC context for the two lists *MUST* be identical as we steal
874 memory from one list to add to another. JRA.
875 ****************************************************************************/
877 static struct ea_list
*ea_list_union(struct ea_list
*name_list
, struct ea_list
*file_list
, size_t *total_ea_len
)
879 struct ea_list
*nlistp
, *flistp
;
881 for (nlistp
= name_list
; nlistp
; nlistp
= nlistp
->next
) {
882 for (flistp
= file_list
; flistp
; flistp
= flistp
->next
) {
883 if (strequal(nlistp
->ea
.name
, flistp
->ea
.name
)) {
889 /* Copy the data from this entry. */
890 nlistp
->ea
.flags
= flistp
->ea
.flags
;
891 nlistp
->ea
.value
= flistp
->ea
.value
;
894 nlistp
->ea
.flags
= 0;
895 ZERO_STRUCT(nlistp
->ea
.value
);
899 *total_ea_len
= ea_list_size(name_list
);
903 /*********************************************************
904 Routine to check if a given string matches exactly.
905 as a special case a mask of "." does NOT match. That
906 is required for correct wildcard semantics
907 Case can be significant or not.
908 **********************************************************/
910 static bool exact_match(bool has_wild
,
915 if (mask
[0] == '.' && mask
[1] == 0) {
923 if (case_sensitive
) {
924 return strcmp(str
,mask
)==0;
926 return strcasecmp_m(str
,mask
) == 0;
930 /****************************************************************************
931 Return the filetype for UNIX extensions.
932 ****************************************************************************/
934 static uint32_t unix_filetype(mode_t mode
)
937 return UNIX_TYPE_FILE
;
938 else if(S_ISDIR(mode
))
939 return UNIX_TYPE_DIR
;
941 else if(S_ISLNK(mode
))
942 return UNIX_TYPE_SYMLINK
;
945 else if(S_ISCHR(mode
))
946 return UNIX_TYPE_CHARDEV
;
949 else if(S_ISBLK(mode
))
950 return UNIX_TYPE_BLKDEV
;
953 else if(S_ISFIFO(mode
))
954 return UNIX_TYPE_FIFO
;
957 else if(S_ISSOCK(mode
))
958 return UNIX_TYPE_SOCKET
;
961 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode
));
962 return UNIX_TYPE_UNKNOWN
;
965 /****************************************************************************
966 Map wire perms onto standard UNIX permissions. Obey share restrictions.
967 ****************************************************************************/
969 NTSTATUS
unix_perms_from_wire(connection_struct
*conn
,
970 const SMB_STRUCT_STAT
*psbuf
,
972 enum perm_type ptype
,
977 if (perms
== SMB_MODE_NO_CHANGE
) {
978 if (!VALID_STAT(*psbuf
)) {
979 return NT_STATUS_INVALID_PARAMETER
;
981 *ret_perms
= psbuf
->st_ex_mode
;
986 ret
= wire_perms_to_unix(perms
);
988 if (ptype
== PERM_NEW_FILE
) {
990 * "create mask"/"force create mode" are
991 * only applied to new files, not existing ones.
993 ret
&= lp_create_mask(SNUM(conn
));
994 /* Add in force bits */
995 ret
|= lp_force_create_mode(SNUM(conn
));
996 } else if (ptype
== PERM_NEW_DIR
) {
998 * "directory mask"/"force directory mode" are
999 * only applied to new directories, not existing ones.
1001 ret
&= lp_directory_mask(SNUM(conn
));
1002 /* Add in force bits */
1003 ret
|= lp_force_directory_mode(SNUM(conn
));
1007 return NT_STATUS_OK
;
1010 /****************************************************************************
1011 Needed to show the msdfs symlinks as directories. Modifies psbuf
1012 to be a directory if it's a msdfs link.
1013 ****************************************************************************/
1015 static bool check_msdfs_link(struct files_struct
*dirfsp
,
1016 struct smb_filename
*atname
,
1017 struct smb_filename
*smb_fname
)
1019 int saved_errno
= errno
;
1020 if(lp_host_msdfs() &&
1021 lp_msdfs_root(SNUM(dirfsp
->conn
)) &&
1022 is_msdfs_link(dirfsp
, atname
)) {
1025 * Copy the returned stat struct from the relative
1026 * to the full pathname.
1028 smb_fname
->st
= atname
->st
;
1030 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1032 smb_fname
->base_name
));
1033 smb_fname
->st
.st_ex_mode
=
1034 (smb_fname
->st
.st_ex_mode
& 0xFFF) | S_IFDIR
;
1035 errno
= saved_errno
;
1038 errno
= saved_errno
;
1043 /****************************************************************************
1044 Get a level dependent lanman2 dir entry.
1045 ****************************************************************************/
1047 struct smbd_dirptr_lanman2_state
{
1048 connection_struct
*conn
;
1049 uint32_t info_level
;
1050 bool check_mangled_names
;
1052 bool got_exact_match
;
1053 bool case_sensitive
;
1056 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX
*ctx
,
1062 struct smbd_dirptr_lanman2_state
*state
=
1063 (struct smbd_dirptr_lanman2_state
*)private_data
;
1065 char mangled_name
[13]; /* mangled 8.3 name. */
1069 /* Mangle fname if it's an illegal name. */
1070 if (mangle_must_mangle(dname
, state
->conn
->params
)) {
1072 * Slow path - ensure we can push the original name as UCS2. If
1073 * not, then just don't return this name.
1077 size_t len
= (strlen(dname
) + 2) * 4; /* Allow enough space. */
1078 uint8_t *tmp
= talloc_array(talloc_tos(),
1082 status
= srvstr_push(NULL
,
1083 FLAGS2_UNICODE_STRINGS
,
1092 if (!NT_STATUS_IS_OK(status
)) {
1096 ok
= name_to_8_3(dname
, mangled_name
,
1097 true, state
->conn
->params
);
1101 fname
= mangled_name
;
1106 got_match
= exact_match(state
->has_wild
,
1107 state
->case_sensitive
,
1109 state
->got_exact_match
= got_match
;
1111 got_match
= mask_match(fname
, mask
,
1112 state
->case_sensitive
);
1115 if(!got_match
&& state
->check_mangled_names
&&
1116 !mangle_is_8_3(fname
, false, state
->conn
->params
)) {
1118 * It turns out that NT matches wildcards against
1119 * both long *and* short names. This may explain some
1120 * of the wildcard wierdness from old DOS clients
1121 * that some people have been seeing.... JRA.
1123 /* Force the mangling into 8.3. */
1124 ok
= name_to_8_3(fname
, mangled_name
,
1125 false, state
->conn
->params
);
1130 got_match
= exact_match(state
->has_wild
,
1131 state
->case_sensitive
,
1132 mangled_name
, mask
);
1133 state
->got_exact_match
= got_match
;
1135 got_match
= mask_match(mangled_name
, mask
,
1136 state
->case_sensitive
);
1144 *_fname
= talloc_strdup(ctx
, fname
);
1145 if (*_fname
== NULL
) {
1152 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX
*ctx
,
1154 struct files_struct
*dirfsp
,
1155 struct smb_filename
*atname
,
1156 struct smb_filename
*smb_fname
,
1160 struct smbd_dirptr_lanman2_state
*state
=
1161 (struct smbd_dirptr_lanman2_state
*)private_data
;
1162 bool ms_dfs_link
= false;
1164 if (smb_fname
->flags
& SMB_FILENAME_POSIX_PATH
) {
1165 if (SMB_VFS_LSTAT(state
->conn
, smb_fname
) != 0) {
1166 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1167 "Couldn't lstat [%s] (%s)\n",
1168 smb_fname_str_dbg(smb_fname
),
1175 if (!VALID_STAT(smb_fname
->st
) &&
1176 SMB_VFS_STAT(state
->conn
, smb_fname
) != 0) {
1177 /* Needed to show the msdfs symlinks as
1180 ms_dfs_link
= check_msdfs_link(dirfsp
,
1184 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1185 "Couldn't stat [%s] (%s)\n",
1186 smb_fname_str_dbg(smb_fname
),
1191 *_mode
= dos_mode_msdfs(state
->conn
, smb_fname
);
1199 *_mode
= fdos_mode(smb_fname
->fsp
);
1200 smb_fname
->st
= smb_fname
->fsp
->fsp_name
->st
;
1205 static NTSTATUS
smbd_marshall_dir_entry(TALLOC_CTX
*ctx
,
1206 connection_struct
*conn
,
1208 uint32_t info_level
,
1209 struct ea_list
*name_list
,
1210 bool check_mangled_names
,
1211 bool requires_resume_key
,
1214 const struct smb_filename
*smb_fname
,
1215 int space_remaining
,
1221 uint64_t *last_entry_off
)
1223 char *p
, *q
, *pdata
= *ppdata
;
1225 uint64_t file_size
= 0;
1226 uint64_t allocation_size
= 0;
1227 uint64_t file_id
= 0;
1229 struct timespec mdate_ts
= {0};
1230 struct timespec adate_ts
= {0};
1231 struct timespec cdate_ts
= {0};
1232 struct timespec create_date_ts
= {0};
1233 time_t mdate
= (time_t)0, adate
= (time_t)0, create_date
= (time_t)0;
1235 char *last_entry_ptr
;
1240 struct readdir_attr_data
*readdir_attr_data
= NULL
;
1242 if (!(mode
& FILE_ATTRIBUTE_DIRECTORY
)) {
1243 file_size
= get_file_size_stat(&smb_fname
->st
);
1245 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
, NULL
, &smb_fname
->st
);
1248 * Skip SMB_VFS_FREADDIR_ATTR if the directory entry is a symlink or
1251 if (smb_fname
->fsp
!= NULL
&&
1252 !(mode
& FILE_ATTRIBUTE_REPARSE_POINT
)) {
1253 status
= SMB_VFS_FREADDIR_ATTR(smb_fname
->fsp
,
1255 &readdir_attr_data
);
1256 if (!NT_STATUS_IS_OK(status
)) {
1257 if (!NT_STATUS_EQUAL(NT_STATUS_NOT_SUPPORTED
,
1264 file_id
= SMB_VFS_FS_FILE_ID(conn
, &smb_fname
->st
);
1266 mdate_ts
= smb_fname
->st
.st_ex_mtime
;
1267 adate_ts
= smb_fname
->st
.st_ex_atime
;
1268 create_date_ts
= get_create_timespec(conn
, NULL
, smb_fname
);
1269 cdate_ts
= get_change_timespec(conn
, NULL
, smb_fname
);
1271 if (lp_dos_filetime_resolution(SNUM(conn
))) {
1272 dos_filetime_timespec(&create_date_ts
);
1273 dos_filetime_timespec(&mdate_ts
);
1274 dos_filetime_timespec(&adate_ts
);
1275 dos_filetime_timespec(&cdate_ts
);
1278 create_date
= convert_timespec_to_time_t(create_date_ts
);
1279 mdate
= convert_timespec_to_time_t(mdate_ts
);
1280 adate
= convert_timespec_to_time_t(adate_ts
);
1282 /* align the record */
1283 SMB_ASSERT(align
>= 1);
1285 off
= (int)PTR_DIFF(pdata
, base_data
);
1286 pad
= (off
+ (align
-1)) & ~(align
-1);
1289 if (pad
&& pad
> space_remaining
) {
1290 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1291 "for padding (wanted %u, had %d)\n",
1294 return STATUS_MORE_ENTRIES
; /* Not finished - just out of space */
1298 /* initialize padding to 0 */
1300 memset(pdata
, 0, pad
);
1302 space_remaining
-= pad
;
1304 DEBUG(10,("smbd_marshall_dir_entry: space_remaining = %d\n",
1314 switch (info_level
) {
1315 case SMB_FIND_INFO_STANDARD
:
1316 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1317 if(requires_resume_key
) {
1321 srv_put_dos_date2(p
,0,create_date
);
1322 srv_put_dos_date2(p
,4,adate
);
1323 srv_put_dos_date2(p
,8,mdate
);
1324 SIVAL(p
,12,(uint32_t)file_size
);
1325 SIVAL(p
,16,(uint32_t)allocation_size
);
1329 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1330 p
+= ucs2_align(base_data
, p
, 0);
1332 status
= srvstr_push(base_data
, flags2
, p
,
1333 fname
, PTR_DIFF(end_data
, p
),
1334 STR_TERMINATE
, &len
);
1335 if (!NT_STATUS_IS_OK(status
)) {
1338 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1340 SCVAL(nameptr
, -1, len
- 2);
1342 SCVAL(nameptr
, -1, 0);
1346 SCVAL(nameptr
, -1, len
- 1);
1348 SCVAL(nameptr
, -1, 0);
1354 case SMB_FIND_EA_SIZE
:
1355 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
1356 if (requires_resume_key
) {
1360 srv_put_dos_date2(p
,0,create_date
);
1361 srv_put_dos_date2(p
,4,adate
);
1362 srv_put_dos_date2(p
,8,mdate
);
1363 SIVAL(p
,12,(uint32_t)file_size
);
1364 SIVAL(p
,16,(uint32_t)allocation_size
);
1367 unsigned int ea_size
= estimate_ea_size(smb_fname
->fsp
);
1368 SIVAL(p
,22,ea_size
); /* Extended attributes */
1372 status
= srvstr_push(base_data
, flags2
,
1373 p
, fname
, PTR_DIFF(end_data
, p
),
1374 STR_TERMINATE
| STR_NOALIGN
, &len
);
1375 if (!NT_STATUS_IS_OK(status
)) {
1378 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1391 SCVAL(nameptr
,0,len
);
1393 SCVAL(p
,0,0); p
+= 1; /* Extra zero byte ? - why.. */
1396 case SMB_FIND_EA_LIST
:
1398 struct ea_list
*file_list
= NULL
;
1401 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
1403 return NT_STATUS_INVALID_PARAMETER
;
1405 if (requires_resume_key
) {
1409 srv_put_dos_date2(p
,0,create_date
);
1410 srv_put_dos_date2(p
,4,adate
);
1411 srv_put_dos_date2(p
,8,mdate
);
1412 SIVAL(p
,12,(uint32_t)file_size
);
1413 SIVAL(p
,16,(uint32_t)allocation_size
);
1415 p
+= 22; /* p now points to the EA area. */
1417 status
= get_ea_list_from_fsp(ctx
,
1419 &ea_len
, &file_list
);
1420 if (!NT_STATUS_IS_OK(status
)) {
1423 name_list
= ea_list_union(name_list
, file_list
, &ea_len
);
1425 /* We need to determine if this entry will fit in the space available. */
1426 /* Max string size is 255 bytes. */
1427 if (PTR_DIFF(p
+ 255 + ea_len
,pdata
) > space_remaining
) {
1428 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1429 "(wanted %u, had %d)\n",
1430 (unsigned int)PTR_DIFF(p
+ 255 + ea_len
,pdata
),
1432 return STATUS_MORE_ENTRIES
; /* Not finished - just out of space */
1435 /* Push the ea_data followed by the name. */
1436 p
+= fill_ea_buffer(ctx
, p
, space_remaining
, conn
, name_list
);
1438 status
= srvstr_push(base_data
, flags2
,
1439 p
+ 1, fname
, PTR_DIFF(end_data
, p
+1),
1440 STR_TERMINATE
| STR_NOALIGN
, &len
);
1441 if (!NT_STATUS_IS_OK(status
)) {
1444 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1457 SCVAL(nameptr
,0,len
);
1459 SCVAL(p
,0,0); p
+= 1; /* Extra zero byte ? - why.. */
1463 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
1464 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1465 was_8_3
= mangle_is_8_3(fname
, True
, conn
->params
);
1467 SIVAL(p
,0,reskey
); p
+= 4;
1468 put_long_date_full_timespec(conn
->ts_res
,p
,&create_date_ts
); p
+= 8;
1469 put_long_date_full_timespec(conn
->ts_res
,p
,&adate_ts
); p
+= 8;
1470 put_long_date_full_timespec(conn
->ts_res
,p
,&mdate_ts
); p
+= 8;
1471 put_long_date_full_timespec(conn
->ts_res
,p
,&cdate_ts
); p
+= 8;
1472 SOFF_T(p
,0,file_size
); p
+= 8;
1473 SOFF_T(p
,0,allocation_size
); p
+= 8;
1474 SIVAL(p
,0,mode
); p
+= 4;
1475 q
= p
; p
+= 4; /* q is placeholder for name length. */
1476 if (mode
& FILE_ATTRIBUTE_REPARSE_POINT
) {
1477 SIVAL(p
, 0, IO_REPARSE_TAG_DFS
);
1479 unsigned int ea_size
= estimate_ea_size(smb_fname
->fsp
);
1480 SIVAL(p
,0,ea_size
); /* Extended attributes */
1483 /* Clear the short name buffer. This is
1484 * IMPORTANT as not doing so will trigger
1485 * a Win2k client bug. JRA.
1487 if (!was_8_3
&& check_mangled_names
) {
1488 char mangled_name
[13]; /* mangled 8.3 name. */
1489 if (!name_to_8_3(fname
,mangled_name
,True
,
1491 /* Error - mangle failed ! */
1492 memset(mangled_name
,'\0',12);
1494 mangled_name
[12] = 0;
1495 status
= srvstr_push(base_data
, flags2
,
1496 p
+2, mangled_name
, 24,
1497 STR_UPPER
|STR_UNICODE
, &len
);
1498 if (!NT_STATUS_IS_OK(status
)) {
1502 memset(p
+ 2 + len
,'\0',24 - len
);
1509 status
= srvstr_push(base_data
, flags2
, p
,
1510 fname
, PTR_DIFF(end_data
, p
),
1511 STR_TERMINATE_ASCII
, &len
);
1512 if (!NT_STATUS_IS_OK(status
)) {
1518 len
= PTR_DIFF(p
, pdata
);
1519 pad
= (len
+ (align
-1)) & ~(align
-1);
1521 * offset to the next entry, the caller
1522 * will overwrite it for the last entry
1523 * that's why we always include the padding
1527 * set padding to zero
1530 memset(p
, 0, pad
- len
);
1537 case SMB_FIND_FILE_DIRECTORY_INFO
:
1538 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1540 SIVAL(p
,0,reskey
); p
+= 4;
1541 put_long_date_full_timespec(conn
->ts_res
,p
,&create_date_ts
); p
+= 8;
1542 put_long_date_full_timespec(conn
->ts_res
,p
,&adate_ts
); p
+= 8;
1543 put_long_date_full_timespec(conn
->ts_res
,p
,&mdate_ts
); p
+= 8;
1544 put_long_date_full_timespec(conn
->ts_res
,p
,&cdate_ts
); p
+= 8;
1545 SOFF_T(p
,0,file_size
); p
+= 8;
1546 SOFF_T(p
,0,allocation_size
); p
+= 8;
1547 SIVAL(p
,0,mode
); p
+= 4;
1548 status
= srvstr_push(base_data
, flags2
,
1549 p
+ 4, fname
, PTR_DIFF(end_data
, p
+4),
1550 STR_TERMINATE_ASCII
, &len
);
1551 if (!NT_STATUS_IS_OK(status
)) {
1557 len
= PTR_DIFF(p
, pdata
);
1558 pad
= (len
+ (align
-1)) & ~(align
-1);
1560 * offset to the next entry, the caller
1561 * will overwrite it for the last entry
1562 * that's why we always include the padding
1566 * set padding to zero
1569 memset(p
, 0, pad
- len
);
1576 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
1577 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1579 SIVAL(p
,0,reskey
); p
+= 4;
1580 put_long_date_full_timespec(conn
->ts_res
,p
,&create_date_ts
); p
+= 8;
1581 put_long_date_full_timespec(conn
->ts_res
,p
,&adate_ts
); p
+= 8;
1582 put_long_date_full_timespec(conn
->ts_res
,p
,&mdate_ts
); p
+= 8;
1583 put_long_date_full_timespec(conn
->ts_res
,p
,&cdate_ts
); p
+= 8;
1584 SOFF_T(p
,0,file_size
); p
+= 8;
1585 SOFF_T(p
,0,allocation_size
); p
+= 8;
1586 SIVAL(p
,0,mode
); p
+= 4;
1587 q
= p
; p
+= 4; /* q is placeholder for name length. */
1588 if (mode
& FILE_ATTRIBUTE_REPARSE_POINT
) {
1589 SIVAL(p
, 0, IO_REPARSE_TAG_DFS
);
1591 unsigned int ea_size
= estimate_ea_size(smb_fname
->fsp
);
1592 SIVAL(p
,0,ea_size
); /* Extended attributes */
1595 status
= srvstr_push(base_data
, flags2
, p
,
1596 fname
, PTR_DIFF(end_data
, p
),
1597 STR_TERMINATE_ASCII
, &len
);
1598 if (!NT_STATUS_IS_OK(status
)) {
1604 len
= PTR_DIFF(p
, pdata
);
1605 pad
= (len
+ (align
-1)) & ~(align
-1);
1607 * offset to the next entry, the caller
1608 * will overwrite it for the last entry
1609 * that's why we always include the padding
1613 * set padding to zero
1616 memset(p
, 0, pad
- len
);
1623 case SMB_FIND_FILE_NAMES_INFO
:
1624 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1626 SIVAL(p
,0,reskey
); p
+= 4;
1628 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1629 acl on a dir (tridge) */
1630 status
= srvstr_push(base_data
, flags2
, p
,
1631 fname
, PTR_DIFF(end_data
, p
),
1632 STR_TERMINATE_ASCII
, &len
);
1633 if (!NT_STATUS_IS_OK(status
)) {
1639 len
= PTR_DIFF(p
, pdata
);
1640 pad
= (len
+ (align
-1)) & ~(align
-1);
1642 * offset to the next entry, the caller
1643 * will overwrite it for the last entry
1644 * that's why we always include the padding
1648 * set padding to zero
1651 memset(p
, 0, pad
- len
);
1658 case SMB_FIND_ID_FULL_DIRECTORY_INFO
:
1659 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1661 SIVAL(p
,0,reskey
); p
+= 4;
1662 put_long_date_full_timespec(conn
->ts_res
,p
,&create_date_ts
); p
+= 8;
1663 put_long_date_full_timespec(conn
->ts_res
,p
,&adate_ts
); p
+= 8;
1664 put_long_date_full_timespec(conn
->ts_res
,p
,&mdate_ts
); p
+= 8;
1665 put_long_date_full_timespec(conn
->ts_res
,p
,&cdate_ts
); p
+= 8;
1666 SOFF_T(p
,0,file_size
); p
+= 8;
1667 SOFF_T(p
,0,allocation_size
); p
+= 8;
1668 SIVAL(p
,0,mode
); p
+= 4;
1669 q
= p
; p
+= 4; /* q is placeholder for name length. */
1670 if (mode
& FILE_ATTRIBUTE_REPARSE_POINT
) {
1671 SIVAL(p
, 0, IO_REPARSE_TAG_DFS
);
1673 unsigned int ea_size
= estimate_ea_size(smb_fname
->fsp
);
1674 SIVAL(p
,0,ea_size
); /* Extended attributes */
1677 SIVAL(p
,0,0); p
+= 4; /* Unknown - reserved ? */
1678 SBVAL(p
,0,file_id
); p
+= 8;
1679 status
= srvstr_push(base_data
, flags2
, p
,
1680 fname
, PTR_DIFF(end_data
, p
),
1681 STR_TERMINATE_ASCII
, &len
);
1682 if (!NT_STATUS_IS_OK(status
)) {
1688 len
= PTR_DIFF(p
, pdata
);
1689 pad
= (len
+ (align
-1)) & ~(align
-1);
1691 * offset to the next entry, the caller
1692 * will overwrite it for the last entry
1693 * that's why we always include the padding
1697 * set padding to zero
1700 memset(p
, 0, pad
- len
);
1707 case SMB_FIND_ID_BOTH_DIRECTORY_INFO
:
1708 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1709 was_8_3
= mangle_is_8_3(fname
, True
, conn
->params
);
1711 SIVAL(p
,0,reskey
); p
+= 4;
1712 put_long_date_full_timespec(conn
->ts_res
,p
,&create_date_ts
); p
+= 8;
1713 put_long_date_full_timespec(conn
->ts_res
,p
,&adate_ts
); p
+= 8;
1714 put_long_date_full_timespec(conn
->ts_res
,p
,&mdate_ts
); p
+= 8;
1715 put_long_date_full_timespec(conn
->ts_res
,p
,&cdate_ts
); p
+= 8;
1716 SOFF_T(p
,0,file_size
); p
+= 8;
1717 SOFF_T(p
,0,allocation_size
); p
+= 8;
1718 SIVAL(p
,0,mode
); p
+= 4;
1719 q
= p
; p
+= 4; /* q is placeholder for name length */
1720 if (mode
& FILE_ATTRIBUTE_REPARSE_POINT
) {
1721 SIVAL(p
, 0, IO_REPARSE_TAG_DFS
);
1722 } else if (readdir_attr_data
&&
1723 readdir_attr_data
->type
== RDATTR_AAPL
) {
1725 * OS X specific SMB2 extension negotiated via
1726 * AAPL create context: return max_access in
1729 SIVAL(p
, 0, readdir_attr_data
->attr_data
.aapl
.max_access
);
1731 unsigned int ea_size
= estimate_ea_size(smb_fname
->fsp
);
1732 SIVAL(p
,0,ea_size
); /* Extended attributes */
1736 if (readdir_attr_data
&&
1737 readdir_attr_data
->type
== RDATTR_AAPL
) {
1739 * OS X specific SMB2 extension negotiated via
1740 * AAPL create context: return resource fork
1741 * length and compressed FinderInfo in
1744 * According to documentation short_name_len
1745 * should be 0, but on the wire behaviour
1746 * shows its set to 24 by clients.
1750 /* Resourefork length */
1751 SBVAL(p
, 2, readdir_attr_data
->attr_data
.aapl
.rfork_size
);
1753 /* Compressed FinderInfo */
1754 memcpy(p
+ 10, &readdir_attr_data
->attr_data
.aapl
.finder_info
, 16);
1755 } else if (!was_8_3
&& check_mangled_names
) {
1756 char mangled_name
[13]; /* mangled 8.3 name. */
1757 if (!name_to_8_3(fname
,mangled_name
,True
,
1759 /* Error - mangle failed ! */
1760 memset(mangled_name
,'\0',12);
1762 mangled_name
[12] = 0;
1763 status
= srvstr_push(base_data
, flags2
,
1764 p
+2, mangled_name
, 24,
1765 STR_UPPER
|STR_UNICODE
, &len
);
1766 if (!NT_STATUS_IS_OK(status
)) {
1771 memset(p
+ 2 + len
,'\0',24 - len
);
1775 /* Clear the short name buffer. This is
1776 * IMPORTANT as not doing so will trigger
1777 * a Win2k client bug. JRA.
1784 if (readdir_attr_data
&&
1785 readdir_attr_data
->type
== RDATTR_AAPL
) {
1787 * OS X specific SMB2 extension negotiated via
1788 * AAPL create context: return UNIX mode in
1791 uint16_t aapl_mode
= (uint16_t)readdir_attr_data
->attr_data
.aapl
.unix_mode
;
1792 SSVAL(p
, 0, aapl_mode
);
1798 SBVAL(p
,0,file_id
); p
+= 8;
1799 status
= srvstr_push(base_data
, flags2
, p
,
1800 fname
, PTR_DIFF(end_data
, p
),
1801 STR_TERMINATE_ASCII
, &len
);
1802 if (!NT_STATUS_IS_OK(status
)) {
1808 len
= PTR_DIFF(p
, pdata
);
1809 pad
= (len
+ (align
-1)) & ~(align
-1);
1811 * offset to the next entry, the caller
1812 * will overwrite it for the last entry
1813 * that's why we always include the padding
1817 * set padding to zero
1820 memset(p
, 0, pad
- len
);
1827 /* CIFS UNIX Extension. */
1829 case SMB_FIND_FILE_UNIX
:
1830 case SMB_FIND_FILE_UNIX_INFO2
:
1832 SIVAL(p
,0,reskey
); p
+= 4; /* Used for continuing search. */
1834 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1836 if (info_level
== SMB_FIND_FILE_UNIX
) {
1837 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
1838 p
= store_file_unix_basic(conn
, p
,
1839 NULL
, &smb_fname
->st
);
1840 status
= srvstr_push(base_data
, flags2
, p
,
1841 fname
, PTR_DIFF(end_data
, p
),
1842 STR_TERMINATE
, &len
);
1843 if (!NT_STATUS_IS_OK(status
)) {
1847 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
1848 p
= store_file_unix_basic_info2(conn
, p
,
1849 NULL
, &smb_fname
->st
);
1852 status
= srvstr_push(base_data
, flags2
, p
, fname
,
1853 PTR_DIFF(end_data
, p
), 0, &len
);
1854 if (!NT_STATUS_IS_OK(status
)) {
1857 SIVAL(nameptr
, 0, len
);
1862 len
= PTR_DIFF(p
, pdata
);
1863 pad
= (len
+ (align
-1)) & ~(align
-1);
1865 * offset to the next entry, the caller
1866 * will overwrite it for the last entry
1867 * that's why we always include the padding
1871 * set padding to zero
1874 memset(p
, 0, pad
- len
);
1879 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1884 return NT_STATUS_INVALID_LEVEL
;
1887 if (PTR_DIFF(p
,pdata
) > space_remaining
) {
1888 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1889 "(wanted %u, had %d)\n",
1890 (unsigned int)PTR_DIFF(p
,pdata
),
1892 return STATUS_MORE_ENTRIES
; /* Not finished - just out of space */
1895 /* Setup the last entry pointer, as an offset from base_data */
1896 *last_entry_off
= PTR_DIFF(last_entry_ptr
,base_data
);
1897 /* Advance the data pointer to the next slot */
1900 return NT_STATUS_OK
;
1903 NTSTATUS
smbd_dirptr_lanman2_entry(TALLOC_CTX
*ctx
,
1904 connection_struct
*conn
,
1905 struct dptr_struct
*dirptr
,
1907 const char *path_mask
,
1910 int requires_resume_key
,
1919 int space_remaining
,
1920 struct smb_filename
**_smb_fname
,
1921 bool *got_exact_match
,
1922 int *_last_entry_off
,
1923 struct ea_list
*name_list
,
1924 struct file_id
*file_id
)
1927 const char *mask
= NULL
;
1928 long prev_dirpos
= 0;
1931 struct smb_filename
*smb_fname
= NULL
;
1932 struct smbd_dirptr_lanman2_state state
;
1934 uint64_t last_entry_off
= 0;
1936 enum mangled_names_options mangled_names
;
1937 bool marshall_with_83_names
;
1939 mangled_names
= lp_mangled_names(conn
->params
);
1943 state
.info_level
= info_level
;
1944 if (mangled_names
!= MANGLED_NAMES_NO
) {
1945 state
.check_mangled_names
= true;
1947 state
.has_wild
= dptr_has_wild(dirptr
);
1948 state
.got_exact_match
= false;
1949 state
.case_sensitive
= dptr_case_sensitive(dirptr
);
1951 *got_exact_match
= false;
1953 p
= strrchr_m(path_mask
,'/');
1964 ok
= smbd_dirptr_get_entry(ctx
,
1971 smbd_dirptr_lanman2_match_fn
,
1972 smbd_dirptr_lanman2_mode_fn
,
1979 return NT_STATUS_END_OF_FILE
;
1982 *got_exact_match
= state
.got_exact_match
;
1984 marshall_with_83_names
= (mangled_names
== MANGLED_NAMES_YES
);
1986 status
= smbd_marshall_dir_entry(ctx
,
1991 marshall_with_83_names
,
1992 requires_resume_key
,
2003 if (NT_STATUS_EQUAL(status
, NT_STATUS_ILLEGAL_CHARACTER
)) {
2004 DEBUG(1,("Conversion error: illegal character: %s\n",
2005 smb_fname_str_dbg(smb_fname
)));
2008 if (file_id
!= NULL
) {
2009 *file_id
= vfs_file_id_from_sbuf(conn
, &smb_fname
->st
);
2012 if (!NT_STATUS_IS_OK(status
) &&
2013 !NT_STATUS_EQUAL(status
, STATUS_MORE_ENTRIES
))
2015 TALLOC_FREE(smb_fname
);
2020 if (_smb_fname
!= NULL
) {
2022 * smb_fname is already talloc'ed off ctx.
2023 * We just need to make sure we don't return
2024 * any stream_name, and replace base_name
2025 * with fname in case base_name got mangled.
2026 * This allows us to preserve any smb_fname->fsp
2027 * for asynchronous handle lookups.
2029 TALLOC_FREE(smb_fname
->stream_name
);
2030 TALLOC_FREE(smb_fname
->base_name
);
2031 smb_fname
->base_name
= talloc_strdup(smb_fname
, fname
);
2033 if (smb_fname
->base_name
== NULL
) {
2034 TALLOC_FREE(smb_fname
);
2036 return NT_STATUS_NO_MEMORY
;
2038 *_smb_fname
= smb_fname
;
2040 TALLOC_FREE(smb_fname
);
2044 if (NT_STATUS_EQUAL(status
, STATUS_MORE_ENTRIES
)) {
2045 dptr_SeekDir(dirptr
, prev_dirpos
);
2049 *_last_entry_off
= last_entry_off
;
2050 return NT_STATUS_OK
;
2053 unsigned char *create_volume_objectid(connection_struct
*conn
, unsigned char objid
[16])
2055 const struct loadparm_substitution
*lp_sub
=
2056 loadparm_s3_global_substitution();
2058 E_md4hash(lp_servicename(talloc_tos(), lp_sub
, SNUM(conn
)),objid
);
2062 static void samba_extended_info_version(struct smb_extended_info
*extended_info
)
2064 SMB_ASSERT(extended_info
!= NULL
);
2066 extended_info
->samba_magic
= SAMBA_EXTENDED_INFO_MAGIC
;
2067 extended_info
->samba_version
= ((SAMBA_VERSION_MAJOR
& 0xff) << 24)
2068 | ((SAMBA_VERSION_MINOR
& 0xff) << 16)
2069 | ((SAMBA_VERSION_RELEASE
& 0xff) << 8);
2070 #ifdef SAMBA_VERSION_REVISION
2071 extended_info
->samba_version
|= (tolower(*SAMBA_VERSION_REVISION
) - 'a' + 1) & 0xff;
2073 extended_info
->samba_subversion
= 0;
2074 #ifdef SAMBA_VERSION_RC_RELEASE
2075 extended_info
->samba_subversion
|= (SAMBA_VERSION_RC_RELEASE
& 0xff) << 24;
2077 #ifdef SAMBA_VERSION_PRE_RELEASE
2078 extended_info
->samba_subversion
|= (SAMBA_VERSION_PRE_RELEASE
& 0xff) << 16;
2081 #ifdef SAMBA_VERSION_VENDOR_PATCH
2082 extended_info
->samba_subversion
|= (SAMBA_VERSION_VENDOR_PATCH
& 0xffff);
2084 extended_info
->samba_gitcommitdate
= 0;
2085 #ifdef SAMBA_VERSION_COMMIT_TIME
2086 unix_to_nt_time(&extended_info
->samba_gitcommitdate
, SAMBA_VERSION_COMMIT_TIME
);
2089 memset(extended_info
->samba_version_string
, 0,
2090 sizeof(extended_info
->samba_version_string
));
2092 snprintf (extended_info
->samba_version_string
,
2093 sizeof(extended_info
->samba_version_string
),
2094 "%s", samba_version_string());
2097 NTSTATUS
smbd_do_qfsinfo(struct smbXsrv_connection
*xconn
,
2098 connection_struct
*conn
,
2099 TALLOC_CTX
*mem_ctx
,
2100 uint16_t info_level
,
2102 unsigned int max_data_bytes
,
2103 size_t *fixed_portion
,
2104 struct smb_filename
*fname
,
2108 const struct loadparm_substitution
*lp_sub
=
2109 loadparm_s3_global_substitution();
2110 char *pdata
, *end_data
;
2113 const char *vname
= volume_label(talloc_tos(), SNUM(conn
));
2114 int snum
= SNUM(conn
);
2115 const char *fstype
= lp_fstype(SNUM(conn
));
2116 const char *filename
= NULL
;
2117 const uint64_t bytes_per_sector
= 512;
2118 uint32_t additional_flags
= 0;
2119 struct smb_filename smb_fname
;
2121 NTSTATUS status
= NT_STATUS_OK
;
2124 if (fname
== NULL
|| fname
->base_name
== NULL
) {
2127 filename
= fname
->base_name
;
2131 if (info_level
!= SMB_QUERY_CIFS_UNIX_INFO
) {
2132 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
2133 "info level (0x%x) on IPC$.\n",
2134 (unsigned int)info_level
));
2135 return NT_STATUS_ACCESS_DENIED
;
2139 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level
));
2141 smb_fname
= (struct smb_filename
) {
2142 .base_name
= discard_const_p(char, filename
),
2143 .flags
= fname
? fname
->flags
: 0,
2144 .twrp
= fname
? fname
->twrp
: 0,
2147 if(info_level
!= SMB_FS_QUOTA_INFORMATION
2148 && SMB_VFS_STAT(conn
, &smb_fname
) != 0) {
2149 DEBUG(2,("stat of . failed (%s)\n", strerror(errno
)));
2150 return map_nt_error_from_unix(errno
);
2155 if (max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
< max_data_bytes
) {
2156 return NT_STATUS_INVALID_PARAMETER
;
2159 *ppdata
= (char *)SMB_REALLOC(
2160 *ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
2161 if (*ppdata
== NULL
) {
2162 return NT_STATUS_NO_MEMORY
;
2166 memset((char *)pdata
,'\0',max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
2167 end_data
= pdata
+ max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
- 1;
2171 switch (info_level
) {
2172 case SMB_INFO_ALLOCATION
:
2174 uint64_t dfree
,dsize
,bsize
,block_size
,sectors_per_unit
;
2176 df_ret
= get_dfree_info(conn
, &smb_fname
, &bsize
,
2178 if (df_ret
== (uint64_t)-1) {
2179 return map_nt_error_from_unix(errno
);
2182 block_size
= lp_block_size(snum
);
2183 if (bsize
< block_size
) {
2184 uint64_t factor
= block_size
/bsize
;
2189 if (bsize
> block_size
) {
2190 uint64_t factor
= bsize
/block_size
;
2195 sectors_per_unit
= bsize
/bytes_per_sector
;
2197 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2198 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st
.st_ex_dev
, (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
2199 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
2202 * For large drives, return max values and not modulo.
2204 dsize
= MIN(dsize
, UINT32_MAX
);
2205 dfree
= MIN(dfree
, UINT32_MAX
);
2207 SIVAL(pdata
,l1_idFileSystem
,st
.st_ex_dev
);
2208 SIVAL(pdata
,l1_cSectorUnit
,sectors_per_unit
);
2209 SIVAL(pdata
,l1_cUnit
,dsize
);
2210 SIVAL(pdata
,l1_cUnitAvail
,dfree
);
2211 SSVAL(pdata
,l1_cbSector
,bytes_per_sector
);
2215 case SMB_INFO_VOLUME
:
2216 /* Return volume name */
2218 * Add volume serial number - hash of a combination of
2219 * the called hostname and the service name.
2221 SIVAL(pdata
,0,str_checksum(lp_servicename(talloc_tos(), lp_sub
, snum
)) ^ (str_checksum(get_local_machine_name())<<16) );
2223 * Win2k3 and previous mess this up by sending a name length
2224 * one byte short. I believe only older clients (OS/2 Win9x) use
2225 * this call so try fixing this by adding a terminating null to
2226 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2228 status
= srvstr_push(
2230 pdata
+l2_vol_szVolLabel
, vname
,
2231 PTR_DIFF(end_data
, pdata
+l2_vol_szVolLabel
),
2232 STR_NOALIGN
|STR_TERMINATE
, &len
);
2233 if (!NT_STATUS_IS_OK(status
)) {
2236 SCVAL(pdata
,l2_vol_cch
,len
);
2237 data_len
= l2_vol_szVolLabel
+ len
;
2238 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %u, name = %s\n",
2239 (unsigned)convert_timespec_to_time_t(st
.st_ex_ctime
),
2240 (unsigned)len
, vname
));
2243 case SMB_QUERY_FS_ATTRIBUTE_INFO
:
2244 case SMB_FS_ATTRIBUTE_INFORMATION
:
2246 additional_flags
= 0;
2247 #if defined(HAVE_SYS_QUOTAS)
2248 additional_flags
|= FILE_VOLUME_QUOTAS
;
2251 if(lp_nt_acl_support(SNUM(conn
))) {
2252 additional_flags
|= FILE_PERSISTENT_ACLS
;
2255 /* Capabilities are filled in at connection time through STATVFS call */
2256 additional_flags
|= conn
->fs_capabilities
;
2257 additional_flags
|= lp_parm_int(conn
->params
->service
,
2258 "share", "fake_fscaps",
2261 SIVAL(pdata
,0,FILE_CASE_PRESERVED_NAMES
|FILE_CASE_SENSITIVE_SEARCH
|
2262 FILE_SUPPORTS_OBJECT_IDS
|FILE_UNICODE_ON_DISK
|
2263 additional_flags
); /* FS ATTRIBUTES */
2265 SIVAL(pdata
,4,255); /* Max filename component length */
2266 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2267 and will think we can't do long filenames */
2268 status
= srvstr_push(pdata
, flags2
, pdata
+12, fstype
,
2269 PTR_DIFF(end_data
, pdata
+12),
2271 if (!NT_STATUS_IS_OK(status
)) {
2275 data_len
= 12 + len
;
2276 if (max_data_bytes
>= 16 && data_len
> max_data_bytes
) {
2277 /* the client only requested a portion of the
2279 data_len
= max_data_bytes
;
2280 status
= STATUS_BUFFER_OVERFLOW
;
2282 *fixed_portion
= 16;
2285 case SMB_QUERY_FS_LABEL_INFO
:
2286 case SMB_FS_LABEL_INFORMATION
:
2287 status
= srvstr_push(pdata
, flags2
, pdata
+4, vname
,
2288 PTR_DIFF(end_data
, pdata
+4), 0, &len
);
2289 if (!NT_STATUS_IS_OK(status
)) {
2296 case SMB_QUERY_FS_VOLUME_INFO
:
2297 case SMB_FS_VOLUME_INFORMATION
:
2300 * Add volume serial number - hash of a combination of
2301 * the called hostname and the service name.
2303 SIVAL(pdata
,8,str_checksum(lp_servicename(talloc_tos(), lp_sub
, snum
)) ^
2304 (str_checksum(get_local_machine_name())<<16));
2306 /* Max label len is 32 characters. */
2307 status
= srvstr_push(pdata
, flags2
, pdata
+18, vname
,
2308 PTR_DIFF(end_data
, pdata
+18),
2310 if (!NT_STATUS_IS_OK(status
)) {
2313 SIVAL(pdata
,12,len
);
2316 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
2317 (int)strlen(vname
),vname
,
2318 lp_servicename(talloc_tos(), lp_sub
, snum
)));
2319 if (max_data_bytes
>= 24 && data_len
> max_data_bytes
) {
2320 /* the client only requested a portion of the
2322 data_len
= max_data_bytes
;
2323 status
= STATUS_BUFFER_OVERFLOW
;
2325 *fixed_portion
= 24;
2328 case SMB_QUERY_FS_SIZE_INFO
:
2329 case SMB_FS_SIZE_INFORMATION
:
2331 uint64_t dfree
,dsize
,bsize
,block_size
,sectors_per_unit
;
2333 df_ret
= get_dfree_info(conn
, &smb_fname
, &bsize
,
2335 if (df_ret
== (uint64_t)-1) {
2336 return map_nt_error_from_unix(errno
);
2338 block_size
= lp_block_size(snum
);
2339 if (bsize
< block_size
) {
2340 uint64_t factor
= block_size
/bsize
;
2345 if (bsize
> block_size
) {
2346 uint64_t factor
= bsize
/block_size
;
2351 sectors_per_unit
= bsize
/bytes_per_sector
;
2352 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2353 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
2354 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
2355 SBIG_UINT(pdata
,0,dsize
);
2356 SBIG_UINT(pdata
,8,dfree
);
2357 SIVAL(pdata
,16,sectors_per_unit
);
2358 SIVAL(pdata
,20,bytes_per_sector
);
2359 *fixed_portion
= 24;
2363 case SMB_FS_FULL_SIZE_INFORMATION
:
2365 uint64_t dfree
,dsize
,bsize
,block_size
,sectors_per_unit
;
2367 df_ret
= get_dfree_info(conn
, &smb_fname
, &bsize
,
2369 if (df_ret
== (uint64_t)-1) {
2370 return map_nt_error_from_unix(errno
);
2372 block_size
= lp_block_size(snum
);
2373 if (bsize
< block_size
) {
2374 uint64_t factor
= block_size
/bsize
;
2379 if (bsize
> block_size
) {
2380 uint64_t factor
= bsize
/block_size
;
2385 sectors_per_unit
= bsize
/bytes_per_sector
;
2386 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2387 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
2388 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
2389 SBIG_UINT(pdata
,0,dsize
); /* Total Allocation units. */
2390 SBIG_UINT(pdata
,8,dfree
); /* Caller available allocation units. */
2391 SBIG_UINT(pdata
,16,dfree
); /* Actual available allocation units. */
2392 SIVAL(pdata
,24,sectors_per_unit
); /* Sectors per allocation unit. */
2393 SIVAL(pdata
,28,bytes_per_sector
); /* Bytes per sector. */
2394 *fixed_portion
= 32;
2398 case SMB_QUERY_FS_DEVICE_INFO
:
2399 case SMB_FS_DEVICE_INFORMATION
:
2401 uint32_t characteristics
= FILE_DEVICE_IS_MOUNTED
;
2403 if (!CAN_WRITE(conn
)) {
2404 characteristics
|= FILE_READ_ONLY_DEVICE
;
2407 SIVAL(pdata
,0,FILE_DEVICE_DISK
); /* dev type */
2408 SIVAL(pdata
,4,characteristics
);
2413 #ifdef HAVE_SYS_QUOTAS
2414 case SMB_FS_QUOTA_INFORMATION
:
2416 * what we have to send --metze:
2418 * Unknown1: 24 NULL bytes
2419 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
2420 * Hard Quota Limit: 8 bytes seems like uint64_t or so
2421 * Quota Flags: 2 byte :
2422 * Unknown3: 6 NULL bytes
2426 * details for Quota Flags:
2428 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2429 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2430 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2431 * 0x0001 Enable Quotas: enable quota for this fs
2435 /* we need to fake up a fsp here,
2436 * because its not send in this call
2439 SMB_NTQUOTA_STRUCT quotas
;
2442 ZERO_STRUCT(quotas
);
2445 fsp
.fnum
= FNUM_FIELD_INVALID
;
2448 if (get_current_uid(conn
) != 0) {
2449 DEBUG(0,("get_user_quota: access_denied "
2450 "service [%s] user [%s]\n",
2451 lp_servicename(talloc_tos(), lp_sub
, SNUM(conn
)),
2452 conn
->session_info
->unix_info
->unix_name
));
2453 return NT_STATUS_ACCESS_DENIED
;
2456 status
= vfs_get_ntquota(&fsp
, SMB_USER_FS_QUOTA_TYPE
,
2458 if (!NT_STATUS_IS_OK(status
)) {
2459 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), lp_sub
, SNUM(conn
))));
2465 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
2466 lp_servicename(talloc_tos(), lp_sub
, SNUM(conn
))));
2468 /* Unknown1 24 NULL bytes*/
2469 SBIG_UINT(pdata
,0,(uint64_t)0);
2470 SBIG_UINT(pdata
,8,(uint64_t)0);
2471 SBIG_UINT(pdata
,16,(uint64_t)0);
2473 /* Default Soft Quota 8 bytes */
2474 SBIG_UINT(pdata
,24,quotas
.softlim
);
2476 /* Default Hard Quota 8 bytes */
2477 SBIG_UINT(pdata
,32,quotas
.hardlim
);
2479 /* Quota flag 2 bytes */
2480 SSVAL(pdata
,40,quotas
.qflags
);
2482 /* Unknown3 6 NULL bytes */
2488 #endif /* HAVE_SYS_QUOTAS */
2489 case SMB_FS_OBJECTID_INFORMATION
:
2491 unsigned char objid
[16];
2492 struct smb_extended_info extended_info
;
2493 memcpy(pdata
,create_volume_objectid(conn
, objid
),16);
2494 samba_extended_info_version (&extended_info
);
2495 SIVAL(pdata
,16,extended_info
.samba_magic
);
2496 SIVAL(pdata
,20,extended_info
.samba_version
);
2497 SIVAL(pdata
,24,extended_info
.samba_subversion
);
2498 SBIG_UINT(pdata
,28,extended_info
.samba_gitcommitdate
);
2499 memcpy(pdata
+36,extended_info
.samba_version_string
,28);
2504 case SMB_FS_SECTOR_SIZE_INFORMATION
:
2508 * These values match a physical Windows Server 2012
2509 * share backed by NTFS atop spinning rust.
2511 DEBUG(5, ("SMB_FS_SECTOR_SIZE_INFORMATION:"));
2512 /* logical_bytes_per_sector */
2513 SIVAL(pdata
, 0, bytes_per_sector
);
2514 /* phys_bytes_per_sector_atomic */
2515 SIVAL(pdata
, 4, bytes_per_sector
);
2516 /* phys_bytes_per_sector_perf */
2517 SIVAL(pdata
, 8, bytes_per_sector
);
2518 /* fs_effective_phys_bytes_per_sector_atomic */
2519 SIVAL(pdata
, 12, bytes_per_sector
);
2521 SIVAL(pdata
, 16, SSINFO_FLAGS_ALIGNED_DEVICE
2522 | SSINFO_FLAGS_PARTITION_ALIGNED_ON_DEVICE
);
2523 /* byte_off_sector_align */
2524 SIVAL(pdata
, 20, 0);
2525 /* byte_off_partition_align */
2526 SIVAL(pdata
, 24, 0);
2527 *fixed_portion
= 28;
2532 #if defined(WITH_SMB1SERVER)
2534 * Query the version and capabilities of the CIFS UNIX extensions
2538 case SMB_QUERY_CIFS_UNIX_INFO
:
2540 bool large_write
= lp_min_receive_file_size() &&
2541 !smb1_srv_is_signing_active(xconn
);
2542 bool large_read
= !smb1_srv_is_signing_active(xconn
);
2543 int encrypt_caps
= 0;
2545 if (!lp_smb1_unix_extensions()) {
2546 return NT_STATUS_INVALID_LEVEL
;
2549 switch (conn
->encrypt_level
) {
2550 case SMB_SIGNING_OFF
:
2553 case SMB_SIGNING_DESIRED
:
2554 case SMB_SIGNING_IF_REQUIRED
:
2555 case SMB_SIGNING_DEFAULT
:
2556 encrypt_caps
= CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP
;
2558 case SMB_SIGNING_REQUIRED
:
2559 encrypt_caps
= CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP
|
2560 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP
;
2561 large_write
= false;
2567 SSVAL(pdata
,0,CIFS_UNIX_MAJOR_VERSION
);
2568 SSVAL(pdata
,2,CIFS_UNIX_MINOR_VERSION
);
2570 /* We have POSIX ACLs, pathname, encryption,
2571 * large read/write, and locking capability. */
2573 SBIG_UINT(pdata
,4,((uint64_t)(
2574 CIFS_UNIX_POSIX_ACLS_CAP
|
2575 CIFS_UNIX_POSIX_PATHNAMES_CAP
|
2576 CIFS_UNIX_FCNTL_LOCKS_CAP
|
2577 CIFS_UNIX_EXTATTR_CAP
|
2578 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP
|
2580 (large_read
? CIFS_UNIX_LARGE_READ_CAP
: 0) |
2582 CIFS_UNIX_LARGE_WRITE_CAP
: 0))));
2587 case SMB_QUERY_POSIX_FS_INFO
:
2590 vfs_statvfs_struct svfs
;
2592 if (!lp_smb1_unix_extensions()) {
2593 return NT_STATUS_INVALID_LEVEL
;
2596 rc
= SMB_VFS_STATVFS(conn
, &smb_fname
, &svfs
);
2600 SIVAL(pdata
,0,svfs
.OptimalTransferSize
);
2601 SIVAL(pdata
,4,svfs
.BlockSize
);
2602 SBIG_UINT(pdata
,8,svfs
.TotalBlocks
);
2603 SBIG_UINT(pdata
,16,svfs
.BlocksAvail
);
2604 SBIG_UINT(pdata
,24,svfs
.UserBlocksAvail
);
2605 SBIG_UINT(pdata
,32,svfs
.TotalFileNodes
);
2606 SBIG_UINT(pdata
,40,svfs
.FreeFileNodes
);
2607 SBIG_UINT(pdata
,48,svfs
.FsIdentifier
);
2608 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
2610 } else if (rc
== EOPNOTSUPP
) {
2611 return NT_STATUS_INVALID_LEVEL
;
2612 #endif /* EOPNOTSUPP */
2614 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(talloc_tos(), lp_sub
, SNUM(conn
))));
2615 return NT_STATUS_DOS(ERRSRV
, ERRerror
);
2620 case SMB_QUERY_POSIX_WHOAMI
:
2626 if (!lp_smb1_unix_extensions()) {
2627 return NT_STATUS_INVALID_LEVEL
;
2630 if (max_data_bytes
< 40) {
2631 return NT_STATUS_BUFFER_TOO_SMALL
;
2634 if (security_session_user_level(conn
->session_info
, NULL
) < SECURITY_USER
) {
2635 flags
|= SMB_WHOAMI_GUEST
;
2638 /* NOTE: 8 bytes for UID/GID, irrespective of native
2639 * platform size. This matches
2640 * SMB_QUERY_FILE_UNIX_BASIC and friends.
2642 data_len
= 4 /* flags */
2649 + 4 /* pad/reserved */
2650 + (conn
->session_info
->unix_token
->ngroups
* 8)
2652 + (conn
->session_info
->security_token
->num_sids
*
2656 SIVAL(pdata
, 0, flags
);
2657 SIVAL(pdata
, 4, SMB_WHOAMI_MASK
);
2659 (uint64_t)conn
->session_info
->unix_token
->uid
);
2660 SBIG_UINT(pdata
, 16,
2661 (uint64_t)conn
->session_info
->unix_token
->gid
);
2664 if (data_len
>= max_data_bytes
) {
2665 /* Potential overflow, skip the GIDs and SIDs. */
2667 SIVAL(pdata
, 24, 0); /* num_groups */
2668 SIVAL(pdata
, 28, 0); /* num_sids */
2669 SIVAL(pdata
, 32, 0); /* num_sid_bytes */
2670 SIVAL(pdata
, 36, 0); /* reserved */
2676 SIVAL(pdata
, 24, conn
->session_info
->unix_token
->ngroups
);
2677 SIVAL(pdata
, 28, conn
->session_info
->security_token
->num_sids
);
2679 /* We walk the SID list twice, but this call is fairly
2680 * infrequent, and I don't expect that it's performance
2681 * sensitive -- jpeach
2683 for (i
= 0, sid_bytes
= 0;
2684 i
< conn
->session_info
->security_token
->num_sids
; ++i
) {
2685 sid_bytes
+= ndr_size_dom_sid(
2686 &conn
->session_info
->security_token
->sids
[i
],
2690 /* SID list byte count */
2691 SIVAL(pdata
, 32, sid_bytes
);
2693 /* 4 bytes pad/reserved - must be zero */
2694 SIVAL(pdata
, 36, 0);
2698 for (i
= 0; i
< conn
->session_info
->unix_token
->ngroups
; ++i
) {
2699 SBIG_UINT(pdata
, data_len
,
2700 (uint64_t)conn
->session_info
->unix_token
->groups
[i
]);
2706 i
< conn
->session_info
->security_token
->num_sids
; ++i
) {
2707 int sid_len
= ndr_size_dom_sid(
2708 &conn
->session_info
->security_token
->sids
[i
],
2711 sid_linearize((uint8_t *)(pdata
+ data_len
),
2713 &conn
->session_info
->security_token
->sids
[i
]);
2714 data_len
+= sid_len
;
2720 case SMB_MAC_QUERY_FS_INFO
:
2722 * Thursby MAC extension... ONLY on NTFS filesystems
2723 * once we do streams then we don't need this
2725 if (strequal(lp_fstype(SNUM(conn
)),"NTFS")) {
2727 SIVAL(pdata
,84,0x100); /* Don't support mac... */
2733 return NT_STATUS_INVALID_LEVEL
;
2736 *ret_data_len
= data_len
;
2740 NTSTATUS
smb_set_fsquota(connection_struct
*conn
,
2741 struct smb_request
*req
,
2743 const DATA_BLOB
*qdata
)
2745 const struct loadparm_substitution
*lp_sub
=
2746 loadparm_s3_global_substitution();
2748 SMB_NTQUOTA_STRUCT quotas
;
2750 ZERO_STRUCT(quotas
);
2753 if ((get_current_uid(conn
) != 0) || !CAN_WRITE(conn
)) {
2754 DEBUG(3, ("set_fsquota: access_denied service [%s] user [%s]\n",
2755 lp_servicename(talloc_tos(), lp_sub
, SNUM(conn
)),
2756 conn
->session_info
->unix_info
->unix_name
));
2757 return NT_STATUS_ACCESS_DENIED
;
2760 if (!check_fsp_ntquota_handle(conn
, req
,
2762 DEBUG(1, ("set_fsquota: no valid QUOTA HANDLE\n"));
2763 return NT_STATUS_INVALID_HANDLE
;
2766 /* note: normally there're 48 bytes,
2767 * but we didn't use the last 6 bytes for now
2770 if (qdata
->length
< 42) {
2771 DEBUG(0,("set_fsquota: requires total_data(%u) >= 42 bytes!\n",
2772 (unsigned int)qdata
->length
));
2773 return NT_STATUS_INVALID_PARAMETER
;
2776 /* unknown_1 24 NULL bytes in pdata*/
2778 /* the soft quotas 8 bytes (uint64_t)*/
2779 quotas
.softlim
= BVAL(qdata
->data
,24);
2781 /* the hard quotas 8 bytes (uint64_t)*/
2782 quotas
.hardlim
= BVAL(qdata
->data
,32);
2784 /* quota_flags 2 bytes **/
2785 quotas
.qflags
= SVAL(qdata
->data
,40);
2787 /* unknown_2 6 NULL bytes follow*/
2789 /* now set the quotas */
2790 if (vfs_set_ntquota(fsp
, SMB_USER_FS_QUOTA_TYPE
, NULL
, "as
)!=0) {
2791 DEBUG(1, ("vfs_set_ntquota() failed for service [%s]\n",
2792 lp_servicename(talloc_tos(), lp_sub
, SNUM(conn
))));
2793 status
= map_nt_error_from_unix(errno
);
2795 status
= NT_STATUS_OK
;
2800 NTSTATUS
smbd_do_setfsinfo(connection_struct
*conn
,
2801 struct smb_request
*req
,
2802 TALLOC_CTX
*mem_ctx
,
2803 uint16_t info_level
,
2805 const DATA_BLOB
*pdata
)
2807 switch (info_level
) {
2808 case SMB_FS_QUOTA_INFORMATION
:
2810 return smb_set_fsquota(conn
,
2819 return NT_STATUS_INVALID_LEVEL
;
2822 #if defined(HAVE_POSIX_ACLS)
2823 /****************************************************************************
2824 Utility function to count the number of entries in a POSIX acl.
2825 ****************************************************************************/
2827 static unsigned int count_acl_entries(connection_struct
*conn
, SMB_ACL_T posix_acl
)
2829 unsigned int ace_count
= 0;
2830 int entry_id
= SMB_ACL_FIRST_ENTRY
;
2831 SMB_ACL_ENTRY_T entry
;
2833 while ( posix_acl
&& (sys_acl_get_entry(posix_acl
, entry_id
, &entry
) == 1)) {
2835 if (entry_id
== SMB_ACL_FIRST_ENTRY
) {
2836 entry_id
= SMB_ACL_NEXT_ENTRY
;
2843 /****************************************************************************
2844 Utility function to marshall a POSIX acl into wire format.
2845 ****************************************************************************/
2847 static bool marshall_posix_acl(connection_struct
*conn
, char *pdata
, SMB_STRUCT_STAT
*pst
, SMB_ACL_T posix_acl
)
2849 int entry_id
= SMB_ACL_FIRST_ENTRY
;
2850 SMB_ACL_ENTRY_T entry
;
2852 while ( posix_acl
&& (sys_acl_get_entry(posix_acl
, entry_id
, &entry
) == 1)) {
2853 SMB_ACL_TAG_T tagtype
;
2854 SMB_ACL_PERMSET_T permset
;
2855 unsigned char perms
= 0;
2856 unsigned int own_grp
;
2859 if (entry_id
== SMB_ACL_FIRST_ENTRY
) {
2860 entry_id
= SMB_ACL_NEXT_ENTRY
;
2863 if (sys_acl_get_tag_type(entry
, &tagtype
) == -1) {
2864 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
2868 if (sys_acl_get_permset(entry
, &permset
) == -1) {
2869 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
2873 perms
|= (sys_acl_get_perm(permset
, SMB_ACL_READ
) ? SMB_POSIX_ACL_READ
: 0);
2874 perms
|= (sys_acl_get_perm(permset
, SMB_ACL_WRITE
) ? SMB_POSIX_ACL_WRITE
: 0);
2875 perms
|= (sys_acl_get_perm(permset
, SMB_ACL_EXECUTE
) ? SMB_POSIX_ACL_EXECUTE
: 0);
2877 SCVAL(pdata
,1,perms
);
2880 case SMB_ACL_USER_OBJ
:
2881 SCVAL(pdata
,0,SMB_POSIX_ACL_USER_OBJ
);
2882 own_grp
= (unsigned int)pst
->st_ex_uid
;
2883 SIVAL(pdata
,2,own_grp
);
2888 uid_t
*puid
= (uid_t
*)sys_acl_get_qualifier(entry
);
2890 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
2893 own_grp
= (unsigned int)*puid
;
2894 SCVAL(pdata
,0,SMB_POSIX_ACL_USER
);
2895 SIVAL(pdata
,2,own_grp
);
2899 case SMB_ACL_GROUP_OBJ
:
2900 SCVAL(pdata
,0,SMB_POSIX_ACL_GROUP_OBJ
);
2901 own_grp
= (unsigned int)pst
->st_ex_gid
;
2902 SIVAL(pdata
,2,own_grp
);
2907 gid_t
*pgid
= (gid_t
*)sys_acl_get_qualifier(entry
);
2909 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
2912 own_grp
= (unsigned int)*pgid
;
2913 SCVAL(pdata
,0,SMB_POSIX_ACL_GROUP
);
2914 SIVAL(pdata
,2,own_grp
);
2919 SCVAL(pdata
,0,SMB_POSIX_ACL_MASK
);
2920 SIVAL(pdata
,2,0xFFFFFFFF);
2921 SIVAL(pdata
,6,0xFFFFFFFF);
2924 SCVAL(pdata
,0,SMB_POSIX_ACL_OTHER
);
2925 SIVAL(pdata
,2,0xFFFFFFFF);
2926 SIVAL(pdata
,6,0xFFFFFFFF);
2929 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
2932 pdata
+= SMB_POSIX_ACL_ENTRY_SIZE
;
2939 /****************************************************************************
2940 Store the FILE_UNIX_BASIC info.
2941 ****************************************************************************/
2943 static char *store_file_unix_basic(connection_struct
*conn
,
2946 const SMB_STRUCT_STAT
*psbuf
)
2950 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
2951 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf
->st_ex_mode
));
2953 SOFF_T(pdata
,0,get_file_size_stat(psbuf
)); /* File size 64 Bit */
2956 SOFF_T(pdata
,0,SMB_VFS_GET_ALLOC_SIZE(conn
,fsp
,psbuf
)); /* Number of bytes used on disk - 64 Bit */
2959 put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER
, pdata
, &psbuf
->st_ex_ctime
); /* Change Time 64 Bit */
2960 put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER
,pdata
+8, &psbuf
->st_ex_atime
); /* Last access time 64 Bit */
2961 put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER
, pdata
+16, &psbuf
->st_ex_mtime
); /* Last modification time 64 Bit */
2964 SIVAL(pdata
,0,psbuf
->st_ex_uid
); /* user id for the owner */
2968 SIVAL(pdata
,0,psbuf
->st_ex_gid
); /* group id of owner */
2972 SIVAL(pdata
,0,unix_filetype(psbuf
->st_ex_mode
));
2975 if (S_ISBLK(psbuf
->st_ex_mode
) || S_ISCHR(psbuf
->st_ex_mode
)) {
2976 devno
= psbuf
->st_ex_rdev
;
2978 devno
= psbuf
->st_ex_dev
;
2981 SIVAL(pdata
,0,unix_dev_major(devno
)); /* Major device number if type is device */
2985 SIVAL(pdata
,0,unix_dev_minor(devno
)); /* Minor device number if type is device */
2989 SINO_T_VAL(pdata
, 0, psbuf
->st_ex_ino
); /* inode number */
2992 SIVAL(pdata
,0, unix_perms_to_wire(psbuf
->st_ex_mode
)); /* Standard UNIX file permissions */
2996 SIVAL(pdata
,0,psbuf
->st_ex_nlink
); /* number of hard links */
3003 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3004 * the chflags(2) (or equivalent) flags.
3006 * XXX: this really should be behind the VFS interface. To do this, we would
3007 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3008 * Each VFS module could then implement its own mapping as appropriate for the
3009 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3011 static const struct {unsigned stat_fflag
; unsigned smb_fflag
;}
3015 { UF_NODUMP
, EXT_DO_NOT_BACKUP
},
3019 { UF_IMMUTABLE
, EXT_IMMUTABLE
},
3023 { UF_APPEND
, EXT_OPEN_APPEND_ONLY
},
3027 { UF_HIDDEN
, EXT_HIDDEN
},
3030 /* Do not remove. We need to guarantee that this array has at least one
3031 * entry to build on HP-UX.
3037 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT
*psbuf
,
3038 uint32_t *smb_fflags
, uint32_t *smb_fmask
)
3042 for (i
= 0; i
< ARRAY_SIZE(info2_flags_map
); ++i
) {
3043 *smb_fmask
|= info2_flags_map
[i
].smb_fflag
;
3044 if (psbuf
->st_ex_flags
& info2_flags_map
[i
].stat_fflag
) {
3045 *smb_fflags
|= info2_flags_map
[i
].smb_fflag
;
3050 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT
*psbuf
,
3051 const uint32_t smb_fflags
,
3052 const uint32_t smb_fmask
,
3055 uint32_t max_fmask
= 0;
3058 *stat_fflags
= psbuf
->st_ex_flags
;
3060 /* For each flags requested in smb_fmask, check the state of the
3061 * corresponding flag in smb_fflags and set or clear the matching
3065 for (i
= 0; i
< ARRAY_SIZE(info2_flags_map
); ++i
) {
3066 max_fmask
|= info2_flags_map
[i
].smb_fflag
;
3067 if (smb_fmask
& info2_flags_map
[i
].smb_fflag
) {
3068 if (smb_fflags
& info2_flags_map
[i
].smb_fflag
) {
3069 *stat_fflags
|= info2_flags_map
[i
].stat_fflag
;
3071 *stat_fflags
&= ~info2_flags_map
[i
].stat_fflag
;
3076 /* If smb_fmask is asking to set any bits that are not supported by
3077 * our flag mappings, we should fail.
3079 if ((smb_fmask
& max_fmask
) != smb_fmask
) {
3087 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
3088 * of file flags and birth (create) time.
3090 static char *store_file_unix_basic_info2(connection_struct
*conn
,
3093 const SMB_STRUCT_STAT
*psbuf
)
3095 uint32_t file_flags
= 0;
3096 uint32_t flags_mask
= 0;
3098 pdata
= store_file_unix_basic(conn
, pdata
, fsp
, psbuf
);
3100 /* Create (birth) time 64 bit */
3101 put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER
,pdata
, &psbuf
->st_ex_btime
);
3104 map_info2_flags_from_sbuf(psbuf
, &file_flags
, &flags_mask
);
3105 SIVAL(pdata
, 0, file_flags
); /* flags */
3106 SIVAL(pdata
, 4, flags_mask
); /* mask */
3112 static NTSTATUS
marshall_stream_info(unsigned int num_streams
,
3113 const struct stream_struct
*streams
,
3115 unsigned int max_data_bytes
,
3116 unsigned int *data_size
)
3119 unsigned int ofs
= 0;
3121 if (max_data_bytes
< 32) {
3122 return NT_STATUS_INFO_LENGTH_MISMATCH
;
3125 for (i
= 0; i
< num_streams
; i
++) {
3126 unsigned int next_offset
;
3128 smb_ucs2_t
*namebuf
;
3130 if (!push_ucs2_talloc(talloc_tos(), &namebuf
,
3131 streams
[i
].name
, &namelen
) ||
3134 return NT_STATUS_INVALID_PARAMETER
;
3138 * name_buf is now null-terminated, we need to marshall as not
3145 * We cannot overflow ...
3147 if ((ofs
+ 24 + namelen
) > max_data_bytes
) {
3148 DEBUG(10, ("refusing to overflow reply at stream %u\n",
3150 TALLOC_FREE(namebuf
);
3151 return STATUS_BUFFER_OVERFLOW
;
3154 SIVAL(data
, ofs
+4, namelen
);
3155 SOFF_T(data
, ofs
+8, streams
[i
].size
);
3156 SOFF_T(data
, ofs
+16, streams
[i
].alloc_size
);
3157 memcpy(data
+ofs
+24, namebuf
, namelen
);
3158 TALLOC_FREE(namebuf
);
3160 next_offset
= ofs
+ 24 + namelen
;
3162 if (i
== num_streams
-1) {
3163 SIVAL(data
, ofs
, 0);
3166 unsigned int align
= ndr_align_size(next_offset
, 8);
3168 if ((next_offset
+ align
) > max_data_bytes
) {
3169 DEBUG(10, ("refusing to overflow align "
3170 "reply at stream %u\n",
3172 TALLOC_FREE(namebuf
);
3173 return STATUS_BUFFER_OVERFLOW
;
3176 memset(data
+next_offset
, 0, align
);
3177 next_offset
+= align
;
3179 SIVAL(data
, ofs
, next_offset
- ofs
);
3186 DEBUG(10, ("max_data: %u, data_size: %u\n", max_data_bytes
, ofs
));
3190 return NT_STATUS_OK
;
3193 static NTSTATUS
smb_unix_read_symlink(connection_struct
*conn
,
3194 struct smb_request
*req
,
3195 struct smb_filename
*smb_fname
,
3197 unsigned int data_size_in
,
3198 unsigned int *pdata_size_out
)
3203 struct smb_filename
*parent_fname
= NULL
;
3204 struct smb_filename
*base_name
= NULL
;
3206 char *buffer
= talloc_array(talloc_tos(), char, PATH_MAX
+1);
3209 return NT_STATUS_NO_MEMORY
;
3212 DBG_DEBUG("SMB_QUERY_FILE_UNIX_LINK for file %s\n",
3213 smb_fname_str_dbg(smb_fname
));
3215 if(!S_ISLNK(smb_fname
->st
.st_ex_mode
)) {
3216 TALLOC_FREE(buffer
);
3217 return NT_STATUS_DOS(ERRSRV
, ERRbadlink
);
3220 status
= parent_pathref(talloc_tos(),
3225 if (!NT_STATUS_IS_OK(status
)) {
3226 TALLOC_FREE(buffer
);
3230 link_len
= SMB_VFS_READLINKAT(conn
,
3236 TALLOC_FREE(parent_fname
);
3238 if (link_len
== -1) {
3239 TALLOC_FREE(buffer
);
3240 return map_nt_error_from_unix(errno
);
3243 buffer
[link_len
] = 0;
3244 status
= srvstr_push(pdata
,
3251 TALLOC_FREE(buffer
);
3252 if (!NT_STATUS_IS_OK(status
)) {
3255 *pdata_size_out
= len
;
3257 return NT_STATUS_OK
;
3260 #if defined(HAVE_POSIX_ACLS)
3261 static NTSTATUS
smb_query_posix_acl(connection_struct
*conn
,
3262 struct smb_request
*req
,
3264 struct smb_filename
*smb_fname
,
3266 unsigned int data_size_in
,
3267 unsigned int *pdata_size_out
)
3269 SMB_ACL_T file_acl
= NULL
;
3270 SMB_ACL_T def_acl
= NULL
;
3271 uint16_t num_file_acls
= 0;
3272 uint16_t num_def_acls
= 0;
3273 unsigned int size_needed
= 0;
3276 bool close_fsp
= false;
3279 * Ensure we always operate on a file descriptor, not just
3282 if (fsp
== NULL
|| !fsp
->fsp_flags
.is_fsa
) {
3283 uint32_t access_mask
= SEC_STD_READ_CONTROL
|
3284 FILE_READ_ATTRIBUTES
|
3285 FILE_WRITE_ATTRIBUTES
;
3287 status
= get_posix_fsp(conn
,
3293 if (!NT_STATUS_IS_OK(status
)) {
3299 SMB_ASSERT(fsp
!= NULL
);
3301 status
= refuse_symlink_fsp(fsp
);
3302 if (!NT_STATUS_IS_OK(status
)) {
3306 file_acl
= SMB_VFS_SYS_ACL_GET_FD(fsp
, SMB_ACL_TYPE_ACCESS
,
3309 if (file_acl
== NULL
&& no_acl_syscall_error(errno
)) {
3310 DBG_INFO("ACLs not implemented on "
3311 "filesystem containing %s\n",
3313 status
= NT_STATUS_NOT_IMPLEMENTED
;
3317 if (S_ISDIR(fsp
->fsp_name
->st
.st_ex_mode
)) {
3319 * We can only have default POSIX ACLs on
3322 if (!fsp
->fsp_flags
.is_directory
) {
3323 DBG_INFO("Non-directory open %s\n",
3325 status
= NT_STATUS_INVALID_HANDLE
;
3328 def_acl
= SMB_VFS_SYS_ACL_GET_FD(fsp
,
3329 SMB_ACL_TYPE_DEFAULT
,
3331 def_acl
= free_empty_sys_acl(conn
, def_acl
);
3334 num_file_acls
= count_acl_entries(conn
, file_acl
);
3335 num_def_acls
= count_acl_entries(conn
, def_acl
);
3338 if (num_file_acls
+ num_def_acls
< num_file_acls
) {
3339 status
= NT_STATUS_INVALID_PARAMETER
;
3343 size_needed
= num_file_acls
+ num_def_acls
;
3346 * (size_needed * SMB_POSIX_ACL_ENTRY_SIZE) must be less
3347 * than UINT_MAX, so check by division.
3349 if (size_needed
> (UINT_MAX
/SMB_POSIX_ACL_ENTRY_SIZE
)) {
3350 status
= NT_STATUS_INVALID_PARAMETER
;
3354 size_needed
= size_needed
*SMB_POSIX_ACL_ENTRY_SIZE
;
3355 if (size_needed
+ SMB_POSIX_ACL_HEADER_SIZE
< size_needed
) {
3356 status
= NT_STATUS_INVALID_PARAMETER
;
3359 size_needed
+= SMB_POSIX_ACL_HEADER_SIZE
;
3361 if ( data_size_in
< size_needed
) {
3362 DBG_INFO("data_size too small (%u) need %u\n",
3365 status
= NT_STATUS_BUFFER_TOO_SMALL
;
3369 SSVAL(pdata
,0,SMB_POSIX_ACL_VERSION
);
3370 SSVAL(pdata
,2,num_file_acls
);
3371 SSVAL(pdata
,4,num_def_acls
);
3372 pdata
+= SMB_POSIX_ACL_HEADER_SIZE
;
3374 ok
= marshall_posix_acl(conn
,
3379 status
= NT_STATUS_INTERNAL_ERROR
;
3382 pdata
+= (num_file_acls
*SMB_POSIX_ACL_ENTRY_SIZE
);
3384 ok
= marshall_posix_acl(conn
,
3389 status
= NT_STATUS_INTERNAL_ERROR
;
3393 *pdata_size_out
= size_needed
;
3394 status
= NT_STATUS_OK
;
3400 * Ensure the stat struct in smb_fname is up to
3401 * date. Structure copy.
3403 smb_fname
->st
= fsp
->fsp_name
->st
;
3404 (void)close_file_free(req
, &fsp
, NORMAL_CLOSE
);
3407 TALLOC_FREE(file_acl
);
3408 TALLOC_FREE(def_acl
);
3413 NTSTATUS
smbd_do_qfilepathinfo(connection_struct
*conn
,
3414 TALLOC_CTX
*mem_ctx
,
3415 struct smb_request
*req
,
3416 uint16_t info_level
,
3418 struct smb_filename
*smb_fname
,
3419 bool delete_pending
,
3420 struct timespec write_time_ts
,
3421 struct ea_list
*ea_list
,
3422 int lock_data_count
,
3425 unsigned int max_data_bytes
,
3426 size_t *fixed_portion
,
3428 unsigned int *pdata_size
)
3430 char *pdata
= *ppdata
;
3431 char *dstart
, *dend
;
3432 unsigned int data_size
;
3433 struct timespec create_time_ts
, mtime_ts
, atime_ts
, ctime_ts
;
3434 time_t create_time
, mtime
, atime
, c_time
;
3435 SMB_STRUCT_STAT
*psbuf
= NULL
;
3436 SMB_STRUCT_STAT
*base_sp
= NULL
;
3443 uint64_t file_size
= 0;
3445 uint64_t allocation_size
= 0;
3446 uint64_t file_id
= 0;
3447 uint32_t access_mask
= 0;
3450 if (INFO_LEVEL_IS_UNIX(info_level
)) {
3451 if (!lp_smb1_unix_extensions()) {
3452 return NT_STATUS_INVALID_LEVEL
;
3454 if (!req
->posix_pathnames
) {
3455 return NT_STATUS_INVALID_LEVEL
;
3459 DEBUG(5,("smbd_do_qfilepathinfo: %s (%s) level=%d max_data=%u\n",
3460 smb_fname_str_dbg(smb_fname
),
3462 info_level
, max_data_bytes
));
3465 * In case of querying a symlink in POSIX context,
3466 * fsp will be NULL. fdos_mode() deals with it.
3469 smb_fname
= fsp
->fsp_name
;
3471 mode
= fdos_mode(fsp
);
3472 psbuf
= &smb_fname
->st
;
3475 base_sp
= fsp
->base_fsp
?
3476 &fsp
->base_fsp
->fsp_name
->st
:
3479 base_sp
= &smb_fname
->st
;
3482 nlink
= psbuf
->st_ex_nlink
;
3484 if (nlink
&& (mode
&FILE_ATTRIBUTE_DIRECTORY
)) {
3488 if ((nlink
> 0) && delete_pending
) {
3492 if (max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
< max_data_bytes
) {
3493 return NT_STATUS_INVALID_PARAMETER
;
3496 data_size
= max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
;
3497 *ppdata
= (char *)SMB_REALLOC(*ppdata
, data_size
);
3498 if (*ppdata
== NULL
) {
3499 return NT_STATUS_NO_MEMORY
;
3503 dend
= dstart
+ data_size
- 1;
3505 if (!is_omit_timespec(&write_time_ts
) &&
3506 !INFO_LEVEL_IS_UNIX(info_level
))
3508 update_stat_ex_mtime(psbuf
, write_time_ts
);
3511 create_time_ts
= get_create_timespec(conn
, fsp
, smb_fname
);
3512 mtime_ts
= psbuf
->st_ex_mtime
;
3513 atime_ts
= psbuf
->st_ex_atime
;
3514 ctime_ts
= get_change_timespec(conn
, fsp
, smb_fname
);
3516 if (lp_dos_filetime_resolution(SNUM(conn
))) {
3517 dos_filetime_timespec(&create_time_ts
);
3518 dos_filetime_timespec(&mtime_ts
);
3519 dos_filetime_timespec(&atime_ts
);
3520 dos_filetime_timespec(&ctime_ts
);
3523 create_time
= convert_timespec_to_time_t(create_time_ts
);
3524 mtime
= convert_timespec_to_time_t(mtime_ts
);
3525 atime
= convert_timespec_to_time_t(atime_ts
);
3526 c_time
= convert_timespec_to_time_t(ctime_ts
);
3528 p
= strrchr_m(smb_fname
->base_name
,'/');
3530 base_name
= smb_fname
->base_name
;
3534 /* NT expects the name to be in an exact form of the *full*
3535 filename. See the trans2 torture test */
3536 if (ISDOT(base_name
)) {
3537 dos_fname
= talloc_strdup(mem_ctx
, "\\");
3539 return NT_STATUS_NO_MEMORY
;
3542 dos_fname
= talloc_asprintf(mem_ctx
,
3544 smb_fname
->base_name
);
3546 return NT_STATUS_NO_MEMORY
;
3548 if (is_named_stream(smb_fname
)) {
3549 dos_fname
= talloc_asprintf(dos_fname
, "%s",
3550 smb_fname
->stream_name
);
3552 return NT_STATUS_NO_MEMORY
;
3556 string_replace(dos_fname
, '/', '\\');
3559 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
, fsp
, psbuf
);
3561 if (fsp
== NULL
|| !fsp
->fsp_flags
.is_fsa
) {
3562 /* Do we have this path open ? */
3564 struct file_id fileid
= vfs_file_id_from_sbuf(conn
, psbuf
);
3565 fsp1
= file_find_di_first(conn
->sconn
, fileid
, true);
3566 if (fsp1
&& fsp1
->initial_allocation_size
) {
3567 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
, fsp1
, psbuf
);
3571 if (!(mode
& FILE_ATTRIBUTE_DIRECTORY
)) {
3572 file_size
= get_file_size_stat(psbuf
);
3576 pos
= fh_get_position_information(fsp
->fh
);
3580 access_mask
= fsp
->access_mask
;
3582 /* GENERIC_EXECUTE mapping from Windows */
3583 access_mask
= 0x12019F;
3586 /* This should be an index number - looks like
3589 I think this causes us to fail the IFSKIT
3590 BasicFileInformationTest. -tpot */
3591 file_id
= SMB_VFS_FS_FILE_ID(conn
, base_sp
);
3595 switch (info_level
) {
3596 case SMB_INFO_STANDARD
:
3597 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
3599 srv_put_dos_date2(pdata
,l1_fdateCreation
,create_time
);
3600 srv_put_dos_date2(pdata
,l1_fdateLastAccess
,atime
);
3601 srv_put_dos_date2(pdata
,l1_fdateLastWrite
,mtime
); /* write time */
3602 SIVAL(pdata
,l1_cbFile
,(uint32_t)file_size
);
3603 SIVAL(pdata
,l1_cbFileAlloc
,(uint32_t)allocation_size
);
3604 SSVAL(pdata
,l1_attrFile
,mode
);
3607 case SMB_INFO_QUERY_EA_SIZE
:
3609 unsigned int ea_size
=
3610 estimate_ea_size(smb_fname
->fsp
);
3611 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
3613 srv_put_dos_date2(pdata
,0,create_time
);
3614 srv_put_dos_date2(pdata
,4,atime
);
3615 srv_put_dos_date2(pdata
,8,mtime
); /* write time */
3616 SIVAL(pdata
,12,(uint32_t)file_size
);
3617 SIVAL(pdata
,16,(uint32_t)allocation_size
);
3618 SSVAL(pdata
,20,mode
);
3619 SIVAL(pdata
,22,ea_size
);
3623 case SMB_INFO_IS_NAME_VALID
:
3624 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
3626 /* os/2 needs this ? really ?*/
3627 return NT_STATUS_DOS(ERRDOS
, ERRbadfunc
);
3629 /* This is only reached for qpathinfo */
3633 case SMB_INFO_QUERY_EAS_FROM_LIST
:
3635 size_t total_ea_len
= 0;
3636 struct ea_list
*ea_file_list
= NULL
;
3637 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
3640 get_ea_list_from_fsp(mem_ctx
,
3642 &total_ea_len
, &ea_file_list
);
3643 if (!NT_STATUS_IS_OK(status
)) {
3647 ea_list
= ea_list_union(ea_list
, ea_file_list
, &total_ea_len
);
3649 if (!ea_list
|| (total_ea_len
> data_size
)) {
3651 SIVAL(pdata
,0,4); /* EA List Length must be set to 4 if no EA's. */
3655 data_size
= fill_ea_buffer(mem_ctx
, pdata
, data_size
, conn
, ea_list
);
3659 case SMB_INFO_QUERY_ALL_EAS
:
3661 /* We have data_size bytes to put EA's into. */
3662 size_t total_ea_len
= 0;
3663 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
3665 status
= get_ea_list_from_fsp(mem_ctx
,
3667 &total_ea_len
, &ea_list
);
3668 if (!NT_STATUS_IS_OK(status
)) {
3672 if (!ea_list
|| (total_ea_len
> data_size
)) {
3674 SIVAL(pdata
,0,4); /* EA List Length must be set to 4 if no EA's. */
3678 data_size
= fill_ea_buffer(mem_ctx
, pdata
, data_size
, conn
, ea_list
);
3682 case SMB2_FILE_FULL_EA_INFORMATION
:
3684 /* We have data_size bytes to put EA's into. */
3685 size_t total_ea_len
= 0;
3686 struct ea_list
*ea_file_list
= NULL
;
3688 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
3690 /*TODO: add filtering and index handling */
3693 get_ea_list_from_fsp(mem_ctx
,
3695 &total_ea_len
, &ea_file_list
);
3696 if (!NT_STATUS_IS_OK(status
)) {
3699 if (!ea_file_list
) {
3700 return NT_STATUS_NO_EAS_ON_FILE
;
3703 status
= fill_ea_chained_buffer(mem_ctx
,
3707 conn
, ea_file_list
);
3708 if (!NT_STATUS_IS_OK(status
)) {
3714 case SMB_FILE_BASIC_INFORMATION
:
3715 case SMB_QUERY_FILE_BASIC_INFO
:
3717 if (info_level
== SMB_QUERY_FILE_BASIC_INFO
) {
3718 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
3719 data_size
= 36; /* w95 returns 40 bytes not 36 - why ?. */
3721 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
3725 put_long_date_full_timespec(conn
->ts_res
,pdata
,&create_time_ts
);
3726 put_long_date_full_timespec(conn
->ts_res
,pdata
+8,&atime_ts
);
3727 put_long_date_full_timespec(conn
->ts_res
,pdata
+16,&mtime_ts
); /* write time */
3728 put_long_date_full_timespec(conn
->ts_res
,pdata
+24,&ctime_ts
); /* change time */
3729 SIVAL(pdata
,32,mode
);
3731 DEBUG(5,("SMB_QFBI - "));
3732 DEBUG(5,("create: %s ", ctime(&create_time
)));
3733 DEBUG(5,("access: %s ", ctime(&atime
)));
3734 DEBUG(5,("write: %s ", ctime(&mtime
)));
3735 DEBUG(5,("change: %s ", ctime(&c_time
)));
3736 DEBUG(5,("mode: %x\n", mode
));
3737 *fixed_portion
= data_size
;
3740 case SMB_FILE_STANDARD_INFORMATION
:
3741 case SMB_QUERY_FILE_STANDARD_INFO
:
3743 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
3745 SOFF_T(pdata
,0,allocation_size
);
3746 SOFF_T(pdata
,8,file_size
);
3747 SIVAL(pdata
,16,nlink
);
3748 SCVAL(pdata
,20,delete_pending
?1:0);
3749 SCVAL(pdata
,21,(mode
&FILE_ATTRIBUTE_DIRECTORY
)?1:0);
3750 SSVAL(pdata
,22,0); /* Padding. */
3751 *fixed_portion
= 24;
3754 case SMB_FILE_EA_INFORMATION
:
3755 case SMB_QUERY_FILE_EA_INFO
:
3757 unsigned int ea_size
=
3758 estimate_ea_size(smb_fname
->fsp
);
3759 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
3762 SIVAL(pdata
,0,ea_size
);
3766 /* Get the 8.3 name - used if NT SMB was negotiated. */
3767 case SMB_QUERY_FILE_ALT_NAME_INFO
:
3768 case SMB_FILE_ALTERNATE_NAME_INFORMATION
:
3770 char mangled_name
[13];
3771 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
3772 if (!name_to_8_3(base_name
,mangled_name
,
3773 True
,conn
->params
)) {
3774 return NT_STATUS_NO_MEMORY
;
3776 status
= srvstr_push(dstart
, flags2
,
3777 pdata
+4, mangled_name
,
3778 PTR_DIFF(dend
, pdata
+4),
3780 if (!NT_STATUS_IS_OK(status
)) {
3783 data_size
= 4 + len
;
3789 case SMB_QUERY_FILE_NAME_INFO
:
3792 this must be *exactly* right for ACLs on mapped drives to work
3794 status
= srvstr_push(dstart
, flags2
,
3796 PTR_DIFF(dend
, pdata
+4),
3798 if (!NT_STATUS_IS_OK(status
)) {
3801 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
3802 data_size
= 4 + len
;
3807 case SMB_FILE_NORMALIZED_NAME_INFORMATION
:
3809 char *nfname
= NULL
;
3811 if (fsp
== NULL
|| !fsp
->conn
->sconn
->using_smb2
) {
3812 return NT_STATUS_INVALID_LEVEL
;
3815 nfname
= talloc_strdup(mem_ctx
, smb_fname
->base_name
);
3816 if (nfname
== NULL
) {
3817 return NT_STATUS_NO_MEMORY
;
3820 if (ISDOT(nfname
)) {
3823 string_replace(nfname
, '/', '\\');
3825 if (fsp_is_alternate_stream(fsp
)) {
3826 const char *s
= smb_fname
->stream_name
;
3827 const char *e
= NULL
;
3830 SMB_ASSERT(s
[0] != '\0');
3833 * smb_fname->stream_name is in form
3834 * of ':StrEam:$DATA', but we should only
3835 * append ':StrEam' here.
3838 e
= strchr(&s
[1], ':');
3844 nfname
= talloc_strndup_append(nfname
, s
, n
);
3845 if (nfname
== NULL
) {
3846 return NT_STATUS_NO_MEMORY
;
3850 status
= srvstr_push(dstart
, flags2
,
3852 PTR_DIFF(dend
, pdata
+4),
3854 if (!NT_STATUS_IS_OK(status
)) {
3857 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NORMALIZED_NAME_INFORMATION\n"));
3858 data_size
= 4 + len
;
3864 case SMB_FILE_ALLOCATION_INFORMATION
:
3865 case SMB_QUERY_FILE_ALLOCATION_INFO
:
3866 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
3868 SOFF_T(pdata
,0,allocation_size
);
3871 case SMB_FILE_END_OF_FILE_INFORMATION
:
3872 case SMB_QUERY_FILE_END_OF_FILEINFO
:
3873 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
3875 SOFF_T(pdata
,0,file_size
);
3878 case SMB_QUERY_FILE_ALL_INFO
:
3879 case SMB_FILE_ALL_INFORMATION
:
3881 unsigned int ea_size
=
3882 estimate_ea_size(smb_fname
->fsp
);
3883 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
3884 put_long_date_full_timespec(conn
->ts_res
,pdata
,&create_time_ts
);
3885 put_long_date_full_timespec(conn
->ts_res
,pdata
+8,&atime_ts
);
3886 put_long_date_full_timespec(conn
->ts_res
,pdata
+16,&mtime_ts
); /* write time */
3887 put_long_date_full_timespec(conn
->ts_res
,pdata
+24,&ctime_ts
); /* change time */
3888 SIVAL(pdata
,32,mode
);
3889 SIVAL(pdata
,36,0); /* padding. */
3891 SOFF_T(pdata
,0,allocation_size
);
3892 SOFF_T(pdata
,8,file_size
);
3893 SIVAL(pdata
,16,nlink
);
3894 SCVAL(pdata
,20,delete_pending
);
3895 SCVAL(pdata
,21,(mode
&FILE_ATTRIBUTE_DIRECTORY
)?1:0);
3898 SIVAL(pdata
,0,ea_size
);
3899 pdata
+= 4; /* EA info */
3900 status
= srvstr_push(dstart
, flags2
,
3902 PTR_DIFF(dend
, pdata
+4),
3904 if (!NT_STATUS_IS_OK(status
)) {
3909 data_size
= PTR_DIFF(pdata
,(*ppdata
));
3910 *fixed_portion
= 10;
3914 case SMB2_FILE_ALL_INFORMATION
:
3916 unsigned int ea_size
=
3917 estimate_ea_size(smb_fname
->fsp
);
3918 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
3919 put_long_date_full_timespec(conn
->ts_res
,pdata
+0x00,&create_time_ts
);
3920 put_long_date_full_timespec(conn
->ts_res
,pdata
+0x08,&atime_ts
);
3921 put_long_date_full_timespec(conn
->ts_res
,pdata
+0x10,&mtime_ts
); /* write time */
3922 put_long_date_full_timespec(conn
->ts_res
,pdata
+0x18,&ctime_ts
); /* change time */
3923 SIVAL(pdata
, 0x20, mode
);
3924 SIVAL(pdata
, 0x24, 0); /* padding. */
3925 SBVAL(pdata
, 0x28, allocation_size
);
3926 SBVAL(pdata
, 0x30, file_size
);
3927 SIVAL(pdata
, 0x38, nlink
);
3928 SCVAL(pdata
, 0x3C, delete_pending
);
3929 SCVAL(pdata
, 0x3D, (mode
&FILE_ATTRIBUTE_DIRECTORY
)?1:0);
3930 SSVAL(pdata
, 0x3E, 0); /* padding */
3931 SBVAL(pdata
, 0x40, file_id
);
3932 SIVAL(pdata
, 0x48, ea_size
);
3933 SIVAL(pdata
, 0x4C, access_mask
);
3934 SBVAL(pdata
, 0x50, pos
);
3935 SIVAL(pdata
, 0x58, mode
); /*TODO: mode != mode fix this!!! */
3936 SIVAL(pdata
, 0x5C, 0); /* No alignment needed. */
3940 status
= srvstr_push(dstart
, flags2
,
3942 PTR_DIFF(dend
, pdata
+4),
3944 if (!NT_STATUS_IS_OK(status
)) {
3949 data_size
= PTR_DIFF(pdata
,(*ppdata
));
3950 *fixed_portion
= 104;
3953 case SMB_FILE_INTERNAL_INFORMATION
:
3955 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
3956 SBVAL(pdata
, 0, file_id
);
3961 case SMB_FILE_ACCESS_INFORMATION
:
3962 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
3963 SIVAL(pdata
, 0, access_mask
);
3968 case SMB_FILE_NAME_INFORMATION
:
3969 /* Pathname with leading '\'. */
3972 byte_len
= dos_PutUniCode(pdata
+4,dos_fname
,(size_t)max_data_bytes
,False
);
3973 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
3974 SIVAL(pdata
,0,byte_len
);
3975 data_size
= 4 + byte_len
;
3979 case SMB_FILE_DISPOSITION_INFORMATION
:
3980 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
3982 SCVAL(pdata
,0,delete_pending
);
3986 case SMB_FILE_POSITION_INFORMATION
:
3987 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
3989 SOFF_T(pdata
,0,pos
);
3993 case SMB_FILE_MODE_INFORMATION
:
3994 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
3995 SIVAL(pdata
,0,mode
);
4000 case SMB_FILE_ALIGNMENT_INFORMATION
:
4001 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4002 SIVAL(pdata
,0,0); /* No alignment needed. */
4008 * NT4 server just returns "invalid query" to this - if we try
4009 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4012 /* The first statement above is false - verified using Thursby
4013 * client against NT4 -- gcolley.
4015 case SMB_QUERY_FILE_STREAM_INFO
:
4016 case SMB_FILE_STREAM_INFORMATION
: {
4017 unsigned int num_streams
= 0;
4018 struct stream_struct
*streams
= NULL
;
4020 DEBUG(10,("smbd_do_qfilepathinfo: "
4021 "SMB_FILE_STREAM_INFORMATION\n"));
4023 if (is_ntfs_stream_smb_fname(smb_fname
)) {
4024 return NT_STATUS_INVALID_PARAMETER
;
4027 status
= vfs_fstreaminfo(fsp
,
4032 if (!NT_STATUS_IS_OK(status
)) {
4033 DEBUG(10, ("could not get stream info: %s\n",
4034 nt_errstr(status
)));
4038 status
= marshall_stream_info(num_streams
, streams
,
4039 pdata
, max_data_bytes
,
4042 if (!NT_STATUS_IS_OK(status
)) {
4043 DEBUG(10, ("marshall_stream_info failed: %s\n",
4044 nt_errstr(status
)));
4045 TALLOC_FREE(streams
);
4049 TALLOC_FREE(streams
);
4051 *fixed_portion
= 32;
4055 case SMB_QUERY_COMPRESSION_INFO
:
4056 case SMB_FILE_COMPRESSION_INFORMATION
:
4057 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4058 SOFF_T(pdata
,0,file_size
);
4059 SIVAL(pdata
,8,0); /* ??? */
4060 SIVAL(pdata
,12,0); /* ??? */
4062 *fixed_portion
= 16;
4065 case SMB_FILE_NETWORK_OPEN_INFORMATION
:
4066 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4067 put_long_date_full_timespec(conn
->ts_res
,pdata
,&create_time_ts
);
4068 put_long_date_full_timespec(conn
->ts_res
,pdata
+8,&atime_ts
);
4069 put_long_date_full_timespec(conn
->ts_res
,pdata
+16,&mtime_ts
); /* write time */
4070 put_long_date_full_timespec(conn
->ts_res
,pdata
+24,&ctime_ts
); /* change time */
4071 SOFF_T(pdata
,32,allocation_size
);
4072 SOFF_T(pdata
,40,file_size
);
4073 SIVAL(pdata
,48,mode
);
4074 SIVAL(pdata
,52,0); /* ??? */
4076 *fixed_portion
= 56;
4079 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION
:
4080 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4081 SIVAL(pdata
,0,mode
);
4088 * CIFS UNIX Extensions.
4091 case SMB_QUERY_FILE_UNIX_BASIC
:
4093 pdata
= store_file_unix_basic(conn
, pdata
, fsp
, psbuf
);
4094 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4096 DEBUG(4,("smbd_do_qfilepathinfo: "
4097 "SMB_QUERY_FILE_UNIX_BASIC\n"));
4098 dump_data(4, (uint8_t *)(*ppdata
), data_size
);
4102 case SMB_QUERY_FILE_UNIX_INFO2
:
4104 pdata
= store_file_unix_basic_info2(conn
, pdata
, fsp
, psbuf
);
4105 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4109 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4111 for (i
=0; i
<100; i
++)
4112 DEBUG(4,("%d=%x, ",i
, (*ppdata
)[i
]));
4118 case SMB_QUERY_FILE_UNIX_LINK
:
4120 status
= smb_unix_read_symlink(conn
,
4126 if (!NT_STATUS_IS_OK(status
)) {
4132 #if defined(HAVE_POSIX_ACLS)
4133 case SMB_QUERY_POSIX_ACL
:
4135 status
= smb_query_posix_acl(conn
,
4142 if (!NT_STATUS_IS_OK(status
)) {
4150 case SMB_QUERY_POSIX_LOCK
:
4155 enum brl_type lock_type
;
4157 /* We need an open file with a real fd for this. */
4159 fsp
->fsp_flags
.is_pathref
||
4160 fsp_get_io_fd(fsp
) == -1)
4162 return NT_STATUS_INVALID_LEVEL
;
4165 if (lock_data_count
!= POSIX_LOCK_DATA_SIZE
) {
4166 return NT_STATUS_INVALID_PARAMETER
;
4169 switch (SVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
)) {
4170 case POSIX_LOCK_TYPE_READ
:
4171 lock_type
= READ_LOCK
;
4173 case POSIX_LOCK_TYPE_WRITE
:
4174 lock_type
= WRITE_LOCK
;
4176 case POSIX_LOCK_TYPE_UNLOCK
:
4178 /* There's no point in asking for an unlock... */
4179 return NT_STATUS_INVALID_PARAMETER
;
4182 smblctx
= (uint64_t)IVAL(pdata
, POSIX_LOCK_PID_OFFSET
);
4183 offset
= BVAL(pdata
,POSIX_LOCK_START_OFFSET
);
4184 count
= BVAL(pdata
,POSIX_LOCK_LEN_OFFSET
);
4186 status
= query_lock(fsp
,
4193 if (ERROR_WAS_LOCK_DENIED(status
)) {
4194 /* Here we need to report who has it locked... */
4195 data_size
= POSIX_LOCK_DATA_SIZE
;
4197 SSVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
, lock_type
);
4198 SSVAL(pdata
, POSIX_LOCK_FLAGS_OFFSET
, 0);
4199 SIVAL(pdata
, POSIX_LOCK_PID_OFFSET
, (uint32_t)smblctx
);
4200 SBVAL(pdata
, POSIX_LOCK_START_OFFSET
, offset
);
4201 SBVAL(pdata
, POSIX_LOCK_LEN_OFFSET
, count
);
4203 } else if (NT_STATUS_IS_OK(status
)) {
4204 /* For success we just return a copy of what we sent
4205 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4206 data_size
= POSIX_LOCK_DATA_SIZE
;
4207 memcpy(pdata
, lock_data
, POSIX_LOCK_DATA_SIZE
);
4208 SSVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
, POSIX_LOCK_TYPE_UNLOCK
);
4216 return NT_STATUS_INVALID_LEVEL
;
4219 *pdata_size
= data_size
;
4220 return NT_STATUS_OK
;
4223 /****************************************************************************
4224 Set a hard link (called by UNIX extensions and by NT rename with HARD link
4226 ****************************************************************************/
4228 NTSTATUS
hardlink_internals(TALLOC_CTX
*ctx
,
4229 connection_struct
*conn
,
4230 struct smb_request
*req
,
4231 bool overwrite_if_exists
,
4232 const struct smb_filename
*smb_fname_old
,
4233 struct smb_filename
*smb_fname_new
)
4235 NTSTATUS status
= NT_STATUS_OK
;
4238 struct smb_filename
*parent_fname_old
= NULL
;
4239 struct smb_filename
*base_name_old
= NULL
;
4240 struct smb_filename
*parent_fname_new
= NULL
;
4241 struct smb_filename
*base_name_new
= NULL
;
4243 /* source must already exist. */
4244 if (!VALID_STAT(smb_fname_old
->st
)) {
4245 status
= NT_STATUS_OBJECT_NAME_NOT_FOUND
;
4249 /* No links from a directory. */
4250 if (S_ISDIR(smb_fname_old
->st
.st_ex_mode
)) {
4251 status
= NT_STATUS_FILE_IS_A_DIRECTORY
;
4255 /* Setting a hardlink to/from a stream isn't currently supported. */
4256 ok
= is_ntfs_stream_smb_fname(smb_fname_old
);
4258 DBG_DEBUG("Old name has streams\n");
4259 status
= NT_STATUS_INVALID_PARAMETER
;
4262 ok
= is_ntfs_stream_smb_fname(smb_fname_new
);
4264 DBG_DEBUG("New name has streams\n");
4265 status
= NT_STATUS_INVALID_PARAMETER
;
4269 status
= parent_pathref(talloc_tos(),
4274 if (!NT_STATUS_IS_OK(status
)) {
4278 status
= parent_pathref(talloc_tos(),
4283 if (!NT_STATUS_IS_OK(status
)) {
4287 if (VALID_STAT(smb_fname_new
->st
)) {
4288 if (overwrite_if_exists
) {
4289 if (S_ISDIR(smb_fname_new
->st
.st_ex_mode
)) {
4290 status
= NT_STATUS_FILE_IS_A_DIRECTORY
;
4293 status
= unlink_internals(conn
,
4295 FILE_ATTRIBUTE_NORMAL
,
4297 if (!NT_STATUS_IS_OK(status
)) {
4301 /* Disallow if newname already exists. */
4302 status
= NT_STATUS_OBJECT_NAME_COLLISION
;
4307 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
4308 smb_fname_old
->base_name
, smb_fname_new
->base_name
));
4310 ret
= SMB_VFS_LINKAT(conn
,
4311 parent_fname_old
->fsp
,
4313 parent_fname_new
->fsp
,
4318 status
= map_nt_error_from_unix(errno
);
4319 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
4320 nt_errstr(status
), smb_fname_old
->base_name
,
4321 smb_fname_new
->base_name
));
4326 TALLOC_FREE(parent_fname_old
);
4327 TALLOC_FREE(parent_fname_new
);
4331 /****************************************************************************
4332 Deal with setting the time from any of the setfilepathinfo functions.
4333 NOTE !!!! The check for FILE_WRITE_ATTRIBUTES access must be done *before*
4334 calling this function.
4335 ****************************************************************************/
4337 NTSTATUS
smb_set_file_time(connection_struct
*conn
,
4339 struct smb_filename
*smb_fname
,
4340 struct smb_file_time
*ft
,
4341 bool setting_write_time
)
4343 struct files_struct
*set_fsp
= NULL
;
4344 struct timeval_buf tbuf
[4];
4346 FILE_NOTIFY_CHANGE_LAST_ACCESS
4347 |FILE_NOTIFY_CHANGE_LAST_WRITE
4348 |FILE_NOTIFY_CHANGE_CREATION
;
4351 if (!VALID_STAT(smb_fname
->st
)) {
4352 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
4357 return NT_STATUS_OK
;
4360 set_fsp
= metadata_fsp(fsp
);
4362 /* get some defaults (no modifications) if any info is zero or -1. */
4363 if (is_omit_timespec(&ft
->create_time
)) {
4364 action
&= ~FILE_NOTIFY_CHANGE_CREATION
;
4367 if (is_omit_timespec(&ft
->atime
)) {
4368 action
&= ~FILE_NOTIFY_CHANGE_LAST_ACCESS
;
4371 if (is_omit_timespec(&ft
->mtime
)) {
4372 action
&= ~FILE_NOTIFY_CHANGE_LAST_WRITE
;
4375 if (!setting_write_time
) {
4376 /* ft->mtime comes from change time, not write time. */
4377 action
&= ~FILE_NOTIFY_CHANGE_LAST_WRITE
;
4380 /* Ensure the resolution is the correct for
4381 * what we can store on this filesystem. */
4383 round_timespec(conn
->ts_res
, &ft
->create_time
);
4384 round_timespec(conn
->ts_res
, &ft
->ctime
);
4385 round_timespec(conn
->ts_res
, &ft
->atime
);
4386 round_timespec(conn
->ts_res
, &ft
->mtime
);
4388 DBG_DEBUG("smb_set_filetime: actime: %s\n ",
4389 timespec_string_buf(&ft
->atime
, true, &tbuf
[0]));
4390 DBG_DEBUG("smb_set_filetime: modtime: %s\n ",
4391 timespec_string_buf(&ft
->mtime
, true, &tbuf
[1]));
4392 DBG_DEBUG("smb_set_filetime: ctime: %s\n ",
4393 timespec_string_buf(&ft
->ctime
, true, &tbuf
[2]));
4394 DBG_DEBUG("smb_set_file_time: createtime: %s\n ",
4395 timespec_string_buf(&ft
->create_time
, true, &tbuf
[3]));
4397 if (setting_write_time
) {
4399 * This was a Windows setfileinfo on an open file.
4400 * NT does this a lot. We also need to
4401 * set the time here, as it can be read by
4402 * FindFirst/FindNext and with the patch for bug #2045
4403 * in smbd/fileio.c it ensures that this timestamp is
4404 * kept sticky even after a write. We save the request
4405 * away and will set it on file close and after a write. JRA.
4408 DBG_DEBUG("setting pending modtime to %s\n",
4409 timespec_string_buf(&ft
->mtime
, true, &tbuf
[0]));
4411 if (set_fsp
!= NULL
) {
4412 set_sticky_write_time_fsp(set_fsp
, ft
->mtime
);
4414 set_sticky_write_time_path(
4415 vfs_file_id_from_sbuf(conn
, &smb_fname
->st
),
4420 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
4422 ret
= file_ntimes(conn
, set_fsp
, ft
);
4424 return map_nt_error_from_unix(errno
);
4427 notify_fname(conn
, NOTIFY_ACTION_MODIFIED
, action
,
4428 smb_fname
->base_name
);
4429 return NT_STATUS_OK
;
4432 /****************************************************************************
4433 Deal with setting the dosmode from any of the setfilepathinfo functions.
4434 NB. The check for FILE_WRITE_ATTRIBUTES access on this path must have been
4435 done before calling this function.
4436 ****************************************************************************/
4438 static NTSTATUS
smb_set_file_dosmode(connection_struct
*conn
,
4439 struct files_struct
*fsp
,
4442 struct files_struct
*dos_fsp
= NULL
;
4443 uint32_t current_dosmode
;
4446 if (!VALID_STAT(fsp
->fsp_name
->st
)) {
4447 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
4450 dos_fsp
= metadata_fsp(fsp
);
4453 if (S_ISDIR(fsp
->fsp_name
->st
.st_ex_mode
)) {
4454 dosmode
|= FILE_ATTRIBUTE_DIRECTORY
;
4456 dosmode
&= ~FILE_ATTRIBUTE_DIRECTORY
;
4460 DBG_DEBUG("dosmode: 0x%" PRIx32
"\n", dosmode
);
4462 /* check the mode isn't different, before changing it */
4464 return NT_STATUS_OK
;
4466 current_dosmode
= fdos_mode(dos_fsp
);
4467 if (dosmode
== current_dosmode
) {
4468 return NT_STATUS_OK
;
4471 DBG_DEBUG("file %s : setting dos mode 0x%" PRIx32
"\n",
4472 fsp_str_dbg(dos_fsp
), dosmode
);
4474 ret
= file_set_dosmode(conn
, dos_fsp
->fsp_name
, dosmode
, NULL
, false);
4476 DBG_WARNING("file_set_dosmode of %s failed: %s\n",
4477 fsp_str_dbg(dos_fsp
), strerror(errno
));
4478 return map_nt_error_from_unix(errno
);
4481 return NT_STATUS_OK
;
4484 /****************************************************************************
4485 Deal with setting the size from any of the setfilepathinfo functions.
4486 ****************************************************************************/
4488 static NTSTATUS
smb_set_file_size(connection_struct
*conn
,
4489 struct smb_request
*req
,
4491 struct smb_filename
*smb_fname
,
4492 const SMB_STRUCT_STAT
*psbuf
,
4494 bool fail_after_createfile
)
4496 NTSTATUS status
= NT_STATUS_OK
;
4497 files_struct
*new_fsp
= NULL
;
4499 if (!VALID_STAT(*psbuf
)) {
4500 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
4503 DBG_INFO("size: %"PRIu64
", file_size_stat=%"PRIu64
"\n",
4505 get_file_size_stat(psbuf
));
4507 if (size
== get_file_size_stat(psbuf
)) {
4509 return NT_STATUS_OK
;
4511 if (!fsp
->fsp_flags
.modified
) {
4512 return NT_STATUS_OK
;
4514 trigger_write_time_update_immediate(fsp
);
4515 return NT_STATUS_OK
;
4518 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
4519 smb_fname_str_dbg(smb_fname
), (double)size
));
4522 !fsp
->fsp_flags
.is_pathref
&&
4523 fsp_get_io_fd(fsp
) != -1)
4525 /* Handle based call. */
4526 if (!(fsp
->access_mask
& FILE_WRITE_DATA
)) {
4527 return NT_STATUS_ACCESS_DENIED
;
4530 if (vfs_set_filelen(fsp
, size
) == -1) {
4531 return map_nt_error_from_unix(errno
);
4533 trigger_write_time_update_immediate(fsp
);
4534 return NT_STATUS_OK
;
4537 status
= SMB_VFS_CREATE_FILE(
4540 smb_fname
, /* fname */
4541 FILE_WRITE_DATA
, /* access_mask */
4542 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
4544 FILE_OPEN
, /* create_disposition*/
4545 0, /* create_options */
4546 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
4547 0, /* oplock_request */
4549 0, /* allocation_size */
4550 0, /* private_flags */
4553 &new_fsp
, /* result */
4555 NULL
, NULL
); /* create context */
4557 if (!NT_STATUS_IS_OK(status
)) {
4558 /* NB. We check for open_was_deferred in the caller. */
4562 /* See RAW-SFILEINFO-END-OF-FILE */
4563 if (fail_after_createfile
) {
4564 close_file_free(req
, &new_fsp
, NORMAL_CLOSE
);
4565 return NT_STATUS_INVALID_LEVEL
;
4568 if (vfs_set_filelen(new_fsp
, size
) == -1) {
4569 status
= map_nt_error_from_unix(errno
);
4570 close_file_free(req
, &new_fsp
, NORMAL_CLOSE
);
4574 trigger_write_time_update_immediate(new_fsp
);
4575 close_file_free(req
, &new_fsp
, NORMAL_CLOSE
);
4576 return NT_STATUS_OK
;
4579 /****************************************************************************
4580 Deal with SMB_INFO_SET_EA.
4581 ****************************************************************************/
4583 static NTSTATUS
smb_info_set_ea(connection_struct
*conn
,
4587 struct smb_filename
*smb_fname
)
4589 struct ea_list
*ea_list
= NULL
;
4590 TALLOC_CTX
*ctx
= NULL
;
4591 NTSTATUS status
= NT_STATUS_OK
;
4593 if (total_data
< 10) {
4595 /* OS/2 workplace shell seems to send SET_EA requests of "null"
4596 length. They seem to have no effect. Bug #3212. JRA */
4598 if ((total_data
== 4) && (IVAL(pdata
,0) == 4)) {
4599 /* We're done. We only get EA info in this call. */
4600 return NT_STATUS_OK
;
4603 return NT_STATUS_INVALID_PARAMETER
;
4606 if (IVAL(pdata
,0) > total_data
) {
4607 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
4608 IVAL(pdata
,0), (unsigned int)total_data
));
4609 return NT_STATUS_INVALID_PARAMETER
;
4613 ea_list
= read_ea_list(ctx
, pdata
+ 4, total_data
- 4);
4615 return NT_STATUS_INVALID_PARAMETER
;
4620 * The only way fsp can be NULL here is if
4621 * smb_fname points at a symlink and
4622 * and we're in POSIX context.
4623 * Ensure this is the case.
4625 * In this case we cannot set the EA.
4627 SMB_ASSERT(smb_fname
->flags
& SMB_FILENAME_POSIX_PATH
);
4628 return NT_STATUS_ACCESS_DENIED
;
4631 status
= set_ea(conn
, fsp
, ea_list
);
4636 /****************************************************************************
4637 Deal with SMB_FILE_FULL_EA_INFORMATION set.
4638 ****************************************************************************/
4640 static NTSTATUS
smb_set_file_full_ea_info(connection_struct
*conn
,
4645 struct ea_list
*ea_list
= NULL
;
4649 return NT_STATUS_INVALID_HANDLE
;
4652 if (!lp_ea_support(SNUM(conn
))) {
4653 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
4654 "EA's not supported.\n",
4655 (unsigned int)total_data
));
4656 return NT_STATUS_EAS_NOT_SUPPORTED
;
4659 if (total_data
< 10) {
4660 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
4662 (unsigned int)total_data
));
4663 return NT_STATUS_INVALID_PARAMETER
;
4666 ea_list
= read_nttrans_ea_list(talloc_tos(),
4671 return NT_STATUS_INVALID_PARAMETER
;
4674 status
= set_ea(conn
, fsp
, ea_list
);
4676 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
4677 smb_fname_str_dbg(fsp
->fsp_name
),
4678 nt_errstr(status
) ));
4684 /****************************************************************************
4685 Deal with SMB_SET_FILE_DISPOSITION_INFO.
4686 ****************************************************************************/
4688 static NTSTATUS
smb_set_file_disposition_info(connection_struct
*conn
,
4692 struct smb_filename
*smb_fname
)
4694 NTSTATUS status
= NT_STATUS_OK
;
4695 bool delete_on_close
;
4696 uint32_t dosmode
= 0;
4698 if (total_data
< 1) {
4699 return NT_STATUS_INVALID_PARAMETER
;
4703 return NT_STATUS_INVALID_HANDLE
;
4706 delete_on_close
= (CVAL(pdata
,0) ? True
: False
);
4707 dosmode
= fdos_mode(fsp
);
4709 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
4710 "delete_on_close = %u\n",
4711 smb_fname_str_dbg(smb_fname
),
4712 (unsigned int)dosmode
,
4713 (unsigned int)delete_on_close
));
4715 if (delete_on_close
) {
4716 status
= can_set_delete_on_close(fsp
, dosmode
);
4717 if (!NT_STATUS_IS_OK(status
)) {
4722 /* The set is across all open files on this dev/inode pair. */
4723 if (!set_delete_on_close(fsp
, delete_on_close
,
4724 conn
->session_info
->security_token
,
4725 conn
->session_info
->unix_token
)) {
4726 return NT_STATUS_ACCESS_DENIED
;
4728 return NT_STATUS_OK
;
4731 /****************************************************************************
4732 Deal with SMB_FILE_POSITION_INFORMATION.
4733 ****************************************************************************/
4735 static NTSTATUS
smb_file_position_information(connection_struct
*conn
,
4740 uint64_t position_information
;
4742 if (total_data
< 8) {
4743 return NT_STATUS_INVALID_PARAMETER
;
4747 /* Ignore on pathname based set. */
4748 return NT_STATUS_OK
;
4751 position_information
= (uint64_t)IVAL(pdata
,0);
4752 position_information
|= (((uint64_t)IVAL(pdata
,4)) << 32);
4754 DEBUG(10,("smb_file_position_information: Set file position "
4755 "information for file %s to %.0f\n", fsp_str_dbg(fsp
),
4756 (double)position_information
));
4757 fh_set_position_information(fsp
->fh
, position_information
);
4758 return NT_STATUS_OK
;
4761 /****************************************************************************
4762 Deal with SMB_FILE_MODE_INFORMATION.
4763 ****************************************************************************/
4765 static NTSTATUS
smb_file_mode_information(connection_struct
*conn
,
4771 if (total_data
< 4) {
4772 return NT_STATUS_INVALID_PARAMETER
;
4774 mode
= IVAL(pdata
,0);
4775 if (mode
!= 0 && mode
!= 2 && mode
!= 4 && mode
!= 6) {
4776 return NT_STATUS_INVALID_PARAMETER
;
4778 return NT_STATUS_OK
;
4781 /****************************************************************************
4782 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
4783 ****************************************************************************/
4785 static NTSTATUS
smb_set_file_unix_link(connection_struct
*conn
,
4786 struct smb_request
*req
,
4789 struct smb_filename
*new_smb_fname
)
4791 char *link_target
= NULL
;
4792 struct smb_filename target_fname
;
4793 TALLOC_CTX
*ctx
= talloc_tos();
4796 struct smb_filename
*parent_fname
= NULL
;
4797 struct smb_filename
*base_name
= NULL
;
4799 /* Set a symbolic link. */
4800 /* Don't allow this if follow links is false. */
4802 if (total_data
== 0) {
4803 return NT_STATUS_INVALID_PARAMETER
;
4806 if (!lp_follow_symlinks(SNUM(conn
))) {
4807 return NT_STATUS_ACCESS_DENIED
;
4810 srvstr_pull_talloc(ctx
, pdata
, req
->flags2
, &link_target
, pdata
,
4811 total_data
, STR_TERMINATE
);
4814 return NT_STATUS_INVALID_PARAMETER
;
4817 target_fname
= (struct smb_filename
) {
4818 .base_name
= link_target
,
4821 /* Removes @GMT tokens if any */
4822 status
= canonicalize_snapshot_path(&target_fname
, UCF_GMT_PATHNAME
, 0);
4823 if (!NT_STATUS_IS_OK(status
)) {
4827 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
4828 new_smb_fname
->base_name
, link_target
));
4830 status
= parent_pathref(talloc_tos(),
4835 if (!NT_STATUS_IS_OK(status
)) {
4839 ret
= SMB_VFS_SYMLINKAT(conn
,
4844 TALLOC_FREE(parent_fname
);
4845 return map_nt_error_from_unix(errno
);
4848 TALLOC_FREE(parent_fname
);
4849 return NT_STATUS_OK
;
4852 /****************************************************************************
4853 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
4854 ****************************************************************************/
4856 static NTSTATUS
smb_set_file_unix_hlink(connection_struct
*conn
,
4857 struct smb_request
*req
,
4858 const char *pdata
, int total_data
,
4859 struct smb_filename
*smb_fname_new
)
4861 char *oldname
= NULL
;
4862 struct smb_filename
*smb_fname_old
= NULL
;
4863 uint32_t ucf_flags
= ucf_flags_from_smb_request(req
);
4864 TALLOC_CTX
*ctx
= talloc_tos();
4865 NTSTATUS status
= NT_STATUS_OK
;
4867 /* Set a hard link. */
4868 if (total_data
== 0) {
4869 return NT_STATUS_INVALID_PARAMETER
;
4872 if (req
->posix_pathnames
) {
4873 srvstr_get_path_posix(ctx
,
4882 srvstr_get_path(ctx
,
4891 if (!NT_STATUS_IS_OK(status
)) {
4895 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
4896 smb_fname_str_dbg(smb_fname_new
), oldname
));
4898 status
= filename_convert(ctx
,
4904 if (!NT_STATUS_IS_OK(status
)) {
4908 return hardlink_internals(ctx
, conn
, req
, false,
4909 smb_fname_old
, smb_fname_new
);
4912 /****************************************************************************
4913 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
4914 ****************************************************************************/
4916 static NTSTATUS
smb2_file_rename_information(connection_struct
*conn
,
4917 struct smb_request
*req
,
4921 struct smb_filename
*smb_fname_src
)
4925 char *newname
= NULL
;
4926 struct smb_filename
*smb_fname_dst
= NULL
;
4927 const char *dst_original_lcomp
= NULL
;
4928 uint32_t ucf_flags
= ucf_flags_from_smb_request(req
);
4929 NTSTATUS status
= NT_STATUS_OK
;
4930 TALLOC_CTX
*ctx
= talloc_tos();
4933 return NT_STATUS_INVALID_HANDLE
;
4936 if (total_data
< 20) {
4937 return NT_STATUS_INVALID_PARAMETER
;
4940 overwrite
= (CVAL(pdata
,0) ? True
: False
);
4941 len
= IVAL(pdata
,16);
4943 if (len
> (total_data
- 20) || (len
== 0)) {
4944 return NT_STATUS_INVALID_PARAMETER
;
4947 if (req
->posix_pathnames
) {
4948 srvstr_get_path_posix(ctx
,
4957 srvstr_get_path(ctx
,
4966 if (!NT_STATUS_IS_OK(status
)) {
4970 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
4973 status
= filename_convert(ctx
,
4979 if (!NT_STATUS_IS_OK(status
)) {
4983 if (fsp
->base_fsp
) {
4984 /* newname must be a stream name. */
4985 if (newname
[0] != ':') {
4986 return NT_STATUS_NOT_SUPPORTED
;
4989 /* Create an smb_fname to call rename_internals_fsp() with. */
4990 smb_fname_dst
= synthetic_smb_fname(talloc_tos(),
4991 fsp
->base_fsp
->fsp_name
->base_name
,
4994 fsp
->base_fsp
->fsp_name
->twrp
,
4995 fsp
->base_fsp
->fsp_name
->flags
);
4996 if (smb_fname_dst
== NULL
) {
4997 status
= NT_STATUS_NO_MEMORY
;
5003 * Set the original last component, since
5004 * rename_internals_fsp() requires it.
5006 dst_original_lcomp
= get_original_lcomp(smb_fname_dst
,
5010 if (dst_original_lcomp
== NULL
) {
5011 status
= NT_STATUS_NO_MEMORY
;
5015 DEBUG(10,("smb2_file_rename_information: "
5016 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
5017 fsp_fnum_dbg(fsp
), fsp_str_dbg(fsp
),
5018 smb_fname_str_dbg(smb_fname_dst
)));
5019 status
= rename_internals_fsp(conn
,
5023 (FILE_ATTRIBUTE_HIDDEN
|FILE_ATTRIBUTE_SYSTEM
),
5027 TALLOC_FREE(smb_fname_dst
);
5031 static NTSTATUS
smb_file_link_information(connection_struct
*conn
,
5032 struct smb_request
*req
,
5036 struct smb_filename
*smb_fname_src
)
5040 char *newname
= NULL
;
5041 struct smb_filename
*smb_fname_dst
= NULL
;
5042 NTSTATUS status
= NT_STATUS_OK
;
5043 uint32_t ucf_flags
= ucf_flags_from_smb_request(req
);
5044 TALLOC_CTX
*ctx
= talloc_tos();
5047 return NT_STATUS_INVALID_HANDLE
;
5050 if (total_data
< 20) {
5051 return NT_STATUS_INVALID_PARAMETER
;
5054 overwrite
= (CVAL(pdata
,0) ? true : false);
5055 len
= IVAL(pdata
,16);
5057 if (len
> (total_data
- 20) || (len
== 0)) {
5058 return NT_STATUS_INVALID_PARAMETER
;
5061 if (smb_fname_src
->flags
& SMB_FILENAME_POSIX_PATH
) {
5062 srvstr_get_path_posix(ctx
,
5070 ucf_flags
|= UCF_POSIX_PATHNAMES
;
5072 srvstr_get_path(ctx
,
5081 if (!NT_STATUS_IS_OK(status
)) {
5085 DEBUG(10,("smb_file_link_information: got name |%s|\n",
5088 status
= filename_convert(ctx
,
5094 if (!NT_STATUS_IS_OK(status
)) {
5098 if (fsp
->base_fsp
) {
5099 /* No stream names. */
5100 return NT_STATUS_NOT_SUPPORTED
;
5103 DEBUG(10,("smb_file_link_information: "
5104 "SMB_FILE_LINK_INFORMATION (%s) %s -> %s\n",
5105 fsp_fnum_dbg(fsp
), fsp_str_dbg(fsp
),
5106 smb_fname_str_dbg(smb_fname_dst
)));
5107 status
= hardlink_internals(ctx
,
5114 TALLOC_FREE(smb_fname_dst
);
5118 /****************************************************************************
5119 Deal with SMB_FILE_RENAME_INFORMATION.
5120 ****************************************************************************/
5122 static NTSTATUS
smb_file_rename_information(connection_struct
*conn
,
5123 struct smb_request
*req
,
5127 struct smb_filename
*smb_fname_src
)
5132 char *newname
= NULL
;
5133 struct smb_filename
*smb_fname_dst
= NULL
;
5134 const char *dst_original_lcomp
= NULL
;
5135 NTSTATUS status
= NT_STATUS_OK
;
5137 TALLOC_CTX
*ctx
= talloc_tos();
5139 if (total_data
< 13) {
5140 return NT_STATUS_INVALID_PARAMETER
;
5143 overwrite
= (CVAL(pdata
,0) ? True
: False
);
5144 root_fid
= IVAL(pdata
,4);
5145 len
= IVAL(pdata
,8);
5147 if (len
> (total_data
- 12) || (len
== 0) || (root_fid
!= 0)) {
5148 return NT_STATUS_INVALID_PARAMETER
;
5151 if (req
->posix_pathnames
) {
5152 srvstr_get_path_posix(ctx
,
5161 srvstr_get_path(ctx
,
5170 if (!NT_STATUS_IS_OK(status
)) {
5174 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
5177 /* Check the new name has no '/' characters. */
5178 if (strchr_m(newname
, '/')) {
5179 return NT_STATUS_NOT_SUPPORTED
;
5182 if (fsp
&& fsp
->base_fsp
) {
5183 /* newname must be a stream name. */
5184 if (newname
[0] != ':') {
5185 return NT_STATUS_NOT_SUPPORTED
;
5188 /* Create an smb_fname to call rename_internals_fsp() with. */
5189 smb_fname_dst
= synthetic_smb_fname(talloc_tos(),
5190 fsp
->base_fsp
->fsp_name
->base_name
,
5193 fsp
->base_fsp
->fsp_name
->twrp
,
5194 fsp
->base_fsp
->fsp_name
->flags
);
5195 if (smb_fname_dst
== NULL
) {
5196 status
= NT_STATUS_NO_MEMORY
;
5201 * Get the original last component, since
5202 * rename_internals_fsp() requires it.
5204 dst_original_lcomp
= get_original_lcomp(smb_fname_dst
,
5208 if (dst_original_lcomp
== NULL
) {
5209 status
= NT_STATUS_NO_MEMORY
;
5215 * Build up an smb_fname_dst based on the filename passed in.
5216 * We basically just strip off the last component, and put on
5217 * the newname instead.
5219 char *base_name
= NULL
;
5220 uint32_t ucf_flags
= ucf_flags_from_smb_request(req
);
5222 /* newname must *not* be a stream name. */
5223 if (newname
[0] == ':') {
5224 return NT_STATUS_NOT_SUPPORTED
;
5228 * Strip off the last component (filename) of the path passed
5231 base_name
= talloc_strdup(ctx
, smb_fname_src
->base_name
);
5233 return NT_STATUS_NO_MEMORY
;
5235 p
= strrchr_m(base_name
, '/');
5239 base_name
= talloc_strdup(ctx
, "");
5241 return NT_STATUS_NO_MEMORY
;
5244 /* Append the new name. */
5245 base_name
= talloc_asprintf_append(base_name
,
5249 return NT_STATUS_NO_MEMORY
;
5252 status
= filename_convert(ctx
,
5259 if (!NT_STATUS_IS_OK(status
)) {
5262 dst_original_lcomp
= get_original_lcomp(smb_fname_dst
,
5266 if (dst_original_lcomp
== NULL
) {
5267 status
= NT_STATUS_NO_MEMORY
;
5272 if (fsp
!= NULL
&& fsp
->fsp_flags
.is_fsa
) {
5273 DEBUG(10,("smb_file_rename_information: "
5274 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
5275 fsp_fnum_dbg(fsp
), fsp_str_dbg(fsp
),
5276 smb_fname_str_dbg(smb_fname_dst
)));
5277 status
= rename_internals_fsp(conn
,
5284 DEBUG(10,("smb_file_rename_information: "
5285 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
5286 smb_fname_str_dbg(smb_fname_src
),
5287 smb_fname_str_dbg(smb_fname_dst
)));
5288 status
= rename_internals(ctx
,
5296 FILE_WRITE_ATTRIBUTES
);
5299 TALLOC_FREE(smb_fname_dst
);
5303 /****************************************************************************
5304 Deal with SMB_SET_POSIX_ACL.
5305 ****************************************************************************/
5307 #if defined(HAVE_POSIX_ACLS)
5308 static NTSTATUS
smb_set_posix_acl(connection_struct
*conn
,
5309 struct smb_request
*req
,
5313 struct smb_filename
*smb_fname
)
5315 uint16_t posix_acl_version
;
5316 uint16_t num_file_acls
;
5317 uint16_t num_def_acls
;
5318 bool valid_file_acls
= true;
5319 bool valid_def_acls
= true;
5321 unsigned int size_needed
;
5322 unsigned int total_data
;
5323 bool close_fsp
= false;
5325 if (total_data_in
< 0) {
5326 status
= NT_STATUS_INVALID_PARAMETER
;
5330 total_data
= total_data_in
;
5332 if (total_data
< SMB_POSIX_ACL_HEADER_SIZE
) {
5333 status
= NT_STATUS_INVALID_PARAMETER
;
5336 posix_acl_version
= SVAL(pdata
,0);
5337 num_file_acls
= SVAL(pdata
,2);
5338 num_def_acls
= SVAL(pdata
,4);
5340 if (num_file_acls
== SMB_POSIX_IGNORE_ACE_ENTRIES
) {
5341 valid_file_acls
= false;
5345 if (num_def_acls
== SMB_POSIX_IGNORE_ACE_ENTRIES
) {
5346 valid_def_acls
= false;
5350 if (posix_acl_version
!= SMB_POSIX_ACL_VERSION
) {
5351 status
= NT_STATUS_INVALID_PARAMETER
;
5356 if (num_file_acls
+ num_def_acls
< num_file_acls
) {
5357 status
= NT_STATUS_INVALID_PARAMETER
;
5361 size_needed
= num_file_acls
+ num_def_acls
;
5364 * (size_needed * SMB_POSIX_ACL_ENTRY_SIZE) must be less
5365 * than UINT_MAX, so check by division.
5367 if (size_needed
> (UINT_MAX
/SMB_POSIX_ACL_ENTRY_SIZE
)) {
5368 status
= NT_STATUS_INVALID_PARAMETER
;
5372 size_needed
= size_needed
*SMB_POSIX_ACL_ENTRY_SIZE
;
5373 if (size_needed
+ SMB_POSIX_ACL_HEADER_SIZE
< size_needed
) {
5374 status
= NT_STATUS_INVALID_PARAMETER
;
5377 size_needed
+= SMB_POSIX_ACL_HEADER_SIZE
;
5379 if (total_data
< size_needed
) {
5380 status
= NT_STATUS_INVALID_PARAMETER
;
5385 * Ensure we always operate on a file descriptor, not just
5388 if (fsp
== NULL
|| !fsp
->fsp_flags
.is_fsa
) {
5389 uint32_t access_mask
= SEC_STD_WRITE_OWNER
|
5391 SEC_STD_READ_CONTROL
|
5392 FILE_READ_ATTRIBUTES
|
5393 FILE_WRITE_ATTRIBUTES
;
5395 status
= get_posix_fsp(conn
,
5401 if (!NT_STATUS_IS_OK(status
)) {
5407 /* Here we know fsp != NULL */
5408 SMB_ASSERT(fsp
!= NULL
);
5410 status
= refuse_symlink_fsp(fsp
);
5411 if (!NT_STATUS_IS_OK(status
)) {
5415 /* If we have a default acl, this *must* be a directory. */
5416 if (valid_def_acls
&& !fsp
->fsp_flags
.is_directory
) {
5417 DBG_INFO("Can't set default acls on "
5418 "non-directory %s\n",
5420 return NT_STATUS_INVALID_HANDLE
;
5423 DBG_DEBUG("file %s num_file_acls = %"PRIu16
", "
5424 "num_def_acls = %"PRIu16
"\n",
5429 /* Move pdata to the start of the file ACL entries. */
5430 pdata
+= SMB_POSIX_ACL_HEADER_SIZE
;
5432 if (valid_file_acls
) {
5433 status
= set_unix_posix_acl(conn
,
5437 if (!NT_STATUS_IS_OK(status
)) {
5442 /* Move pdata to the start of the default ACL entries. */
5443 pdata
+= (num_file_acls
*SMB_POSIX_ACL_ENTRY_SIZE
);
5445 if (valid_def_acls
) {
5446 status
= set_unix_posix_default_acl(conn
,
5450 if (!NT_STATUS_IS_OK(status
)) {
5455 status
= NT_STATUS_OK
;
5460 (void)close_file_free(req
, &fsp
, NORMAL_CLOSE
);
5466 /****************************************************************************
5467 Deal with SMB_SET_FILE_BASIC_INFO.
5468 ****************************************************************************/
5470 static NTSTATUS
smb_set_file_basic_info(connection_struct
*conn
,
5474 struct smb_filename
*smb_fname
)
5476 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
5477 struct smb_file_time ft
;
5478 uint32_t dosmode
= 0;
5479 NTSTATUS status
= NT_STATUS_OK
;
5481 init_smb_file_time(&ft
);
5483 if (total_data
< 36) {
5484 return NT_STATUS_INVALID_PARAMETER
;
5488 return NT_STATUS_INVALID_HANDLE
;
5491 status
= check_access_fsp(fsp
, FILE_WRITE_ATTRIBUTES
);
5492 if (!NT_STATUS_IS_OK(status
)) {
5496 /* Set the attributes */
5497 dosmode
= IVAL(pdata
,32);
5498 status
= smb_set_file_dosmode(conn
, fsp
, dosmode
);
5499 if (!NT_STATUS_IS_OK(status
)) {
5504 ft
.create_time
= pull_long_date_full_timespec(pdata
);
5507 ft
.atime
= pull_long_date_full_timespec(pdata
+8);
5510 ft
.mtime
= pull_long_date_full_timespec(pdata
+16);
5513 ft
.ctime
= pull_long_date_full_timespec(pdata
+24);
5515 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
5516 smb_fname_str_dbg(smb_fname
)));
5518 status
= smb_set_file_time(conn
, fsp
, smb_fname
, &ft
, true);
5519 if (!NT_STATUS_IS_OK(status
)) {
5523 if (fsp
->fsp_flags
.modified
) {
5524 trigger_write_time_update_immediate(fsp
);
5526 return NT_STATUS_OK
;
5529 /****************************************************************************
5530 Deal with SMB_INFO_STANDARD.
5531 ****************************************************************************/
5533 static NTSTATUS
smb_set_info_standard(connection_struct
*conn
,
5537 struct smb_filename
*smb_fname
)
5540 struct smb_file_time ft
;
5542 init_smb_file_time(&ft
);
5544 if (total_data
< 12) {
5545 return NT_STATUS_INVALID_PARAMETER
;
5549 return NT_STATUS_INVALID_HANDLE
;
5553 ft
.create_time
= time_t_to_full_timespec(srv_make_unix_date2(pdata
));
5555 ft
.atime
= time_t_to_full_timespec(srv_make_unix_date2(pdata
+4));
5557 ft
.mtime
= time_t_to_full_timespec(srv_make_unix_date2(pdata
+8));
5559 DEBUG(10,("smb_set_info_standard: file %s\n",
5560 smb_fname_str_dbg(smb_fname
)));
5562 status
= check_access_fsp(fsp
, FILE_WRITE_ATTRIBUTES
);
5563 if (!NT_STATUS_IS_OK(status
)) {
5567 status
= smb_set_file_time(conn
, fsp
, smb_fname
, &ft
, true);
5568 if (!NT_STATUS_IS_OK(status
)) {
5572 if (fsp
->fsp_flags
.modified
) {
5573 trigger_write_time_update_immediate(fsp
);
5575 return NT_STATUS_OK
;
5578 /****************************************************************************
5579 Deal with SMB_SET_FILE_ALLOCATION_INFO.
5580 ****************************************************************************/
5582 static NTSTATUS
smb_set_file_allocation_info(connection_struct
*conn
,
5583 struct smb_request
*req
,
5587 struct smb_filename
*smb_fname
)
5589 uint64_t allocation_size
= 0;
5590 NTSTATUS status
= NT_STATUS_OK
;
5591 files_struct
*new_fsp
= NULL
;
5593 if (!VALID_STAT(smb_fname
->st
)) {
5594 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5597 if (total_data
< 8) {
5598 return NT_STATUS_INVALID_PARAMETER
;
5601 allocation_size
= (uint64_t)IVAL(pdata
,0);
5602 allocation_size
|= (((uint64_t)IVAL(pdata
,4)) << 32);
5603 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
5604 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname
),
5605 (double)allocation_size
));
5607 if (allocation_size
) {
5608 allocation_size
= smb_roundup(conn
, allocation_size
);
5611 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
5612 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname
),
5613 (double)allocation_size
));
5616 !fsp
->fsp_flags
.is_pathref
&&
5617 fsp_get_io_fd(fsp
) != -1)
5619 /* Open file handle. */
5620 if (!(fsp
->access_mask
& FILE_WRITE_DATA
)) {
5621 return NT_STATUS_ACCESS_DENIED
;
5624 /* Only change if needed. */
5625 if (allocation_size
!= get_file_size_stat(&smb_fname
->st
)) {
5626 if (vfs_allocate_file_space(fsp
, allocation_size
) == -1) {
5627 return map_nt_error_from_unix(errno
);
5630 /* But always update the time. */
5632 * This is equivalent to a write. Ensure it's seen immediately
5633 * if there are no pending writes.
5635 trigger_write_time_update_immediate(fsp
);
5636 return NT_STATUS_OK
;
5639 /* Pathname or stat or directory file. */
5640 status
= SMB_VFS_CREATE_FILE(
5643 smb_fname
, /* fname */
5644 FILE_WRITE_DATA
, /* access_mask */
5645 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
5647 FILE_OPEN
, /* create_disposition*/
5648 0, /* create_options */
5649 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
5650 0, /* oplock_request */
5652 0, /* allocation_size */
5653 0, /* private_flags */
5656 &new_fsp
, /* result */
5658 NULL
, NULL
); /* create context */
5660 if (!NT_STATUS_IS_OK(status
)) {
5661 /* NB. We check for open_was_deferred in the caller. */
5665 /* Only change if needed. */
5666 if (allocation_size
!= get_file_size_stat(&smb_fname
->st
)) {
5667 if (vfs_allocate_file_space(new_fsp
, allocation_size
) == -1) {
5668 status
= map_nt_error_from_unix(errno
);
5669 close_file_free(req
, &new_fsp
, NORMAL_CLOSE
);
5674 /* Changing the allocation size should set the last mod time. */
5676 * This is equivalent to a write. Ensure it's seen immediately
5677 * if there are no pending writes.
5679 trigger_write_time_update_immediate(new_fsp
);
5680 close_file_free(req
, &new_fsp
, NORMAL_CLOSE
);
5681 return NT_STATUS_OK
;
5684 /****************************************************************************
5685 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
5686 ****************************************************************************/
5688 static NTSTATUS
smb_set_file_end_of_file_info(connection_struct
*conn
,
5689 struct smb_request
*req
,
5693 struct smb_filename
*smb_fname
,
5694 bool fail_after_createfile
)
5698 if (total_data
< 8) {
5699 return NT_STATUS_INVALID_PARAMETER
;
5702 size
= IVAL(pdata
,0);
5703 size
|= (((off_t
)IVAL(pdata
,4)) << 32);
5704 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
5705 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname
),
5708 return smb_set_file_size(conn
, req
,
5713 fail_after_createfile
);
5716 /****************************************************************************
5717 Allow a UNIX info mknod.
5718 ****************************************************************************/
5720 static NTSTATUS
smb_unix_mknod(connection_struct
*conn
,
5723 const struct smb_filename
*smb_fname
)
5725 uint32_t file_type
= IVAL(pdata
,56);
5726 #if defined(HAVE_MAKEDEV)
5727 uint32_t dev_major
= IVAL(pdata
,60);
5728 uint32_t dev_minor
= IVAL(pdata
,68);
5730 SMB_DEV_T dev
= (SMB_DEV_T
)0;
5731 uint32_t raw_unixmode
= IVAL(pdata
,84);
5735 struct smb_filename
*parent_fname
= NULL
;
5736 struct smb_filename
*base_name
= NULL
;
5738 if (total_data
< 100) {
5739 return NT_STATUS_INVALID_PARAMETER
;
5742 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
5743 PERM_NEW_FILE
, &unixmode
);
5744 if (!NT_STATUS_IS_OK(status
)) {
5748 #if defined(HAVE_MAKEDEV)
5749 dev
= makedev(dev_major
, dev_minor
);
5752 switch (file_type
) {
5753 /* We can't create other objects here. */
5754 case UNIX_TYPE_FILE
:
5756 case UNIX_TYPE_SYMLINK
:
5757 return NT_STATUS_ACCESS_DENIED
;
5758 #if defined(S_IFIFO)
5759 case UNIX_TYPE_FIFO
:
5760 unixmode
|= S_IFIFO
;
5763 #if defined(S_IFSOCK)
5764 case UNIX_TYPE_SOCKET
:
5765 unixmode
|= S_IFSOCK
;
5768 #if defined(S_IFCHR)
5769 case UNIX_TYPE_CHARDEV
:
5770 /* This is only allowed for root. */
5771 if (get_current_uid(conn
) != sec_initial_uid()) {
5772 return NT_STATUS_ACCESS_DENIED
;
5774 unixmode
|= S_IFCHR
;
5777 #if defined(S_IFBLK)
5778 case UNIX_TYPE_BLKDEV
:
5779 if (get_current_uid(conn
) != sec_initial_uid()) {
5780 return NT_STATUS_ACCESS_DENIED
;
5782 unixmode
|= S_IFBLK
;
5786 return NT_STATUS_INVALID_PARAMETER
;
5789 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
5790 "%.0f mode 0%o for file %s\n", (double)dev
,
5791 (unsigned int)unixmode
, smb_fname_str_dbg(smb_fname
)));
5793 status
= parent_pathref(talloc_tos(),
5798 if (!NT_STATUS_IS_OK(status
)) {
5802 /* Ok - do the mknod. */
5803 ret
= SMB_VFS_MKNODAT(conn
,
5810 TALLOC_FREE(parent_fname
);
5811 return map_nt_error_from_unix(errno
);
5814 /* If any of the other "set" calls fail we
5815 * don't want to end up with a half-constructed mknod.
5818 if (lp_inherit_permissions(SNUM(conn
))) {
5819 inherit_access_posix_acl(conn
,
5824 TALLOC_FREE(parent_fname
);
5826 return NT_STATUS_OK
;
5829 /****************************************************************************
5830 Deal with SMB_SET_FILE_UNIX_BASIC.
5831 ****************************************************************************/
5833 static NTSTATUS
smb_set_file_unix_basic(connection_struct
*conn
,
5834 struct smb_request
*req
,
5838 struct smb_filename
*smb_fname
)
5840 struct smb_file_time ft
;
5841 uint32_t raw_unixmode
;
5844 uid_t set_owner
= (uid_t
)SMB_UID_NO_CHANGE
;
5845 gid_t set_grp
= (uid_t
)SMB_GID_NO_CHANGE
;
5846 NTSTATUS status
= NT_STATUS_OK
;
5847 enum perm_type ptype
;
5848 files_struct
*all_fsps
= NULL
;
5849 bool modify_mtime
= true;
5851 SMB_STRUCT_STAT sbuf
;
5853 init_smb_file_time(&ft
);
5855 if (total_data
< 100) {
5856 return NT_STATUS_INVALID_PARAMETER
;
5859 if(IVAL(pdata
, 0) != SMB_SIZE_NO_CHANGE_LO
&&
5860 IVAL(pdata
, 4) != SMB_SIZE_NO_CHANGE_HI
) {
5861 size
=IVAL(pdata
,0); /* first 8 Bytes are size */
5862 size
|= (((off_t
)IVAL(pdata
,4)) << 32);
5865 ft
.atime
= pull_long_date_full_timespec(pdata
+24); /* access_time */
5866 ft
.mtime
= pull_long_date_full_timespec(pdata
+32); /* modification_time */
5867 set_owner
= (uid_t
)IVAL(pdata
,40);
5868 set_grp
= (gid_t
)IVAL(pdata
,48);
5869 raw_unixmode
= IVAL(pdata
,84);
5871 if (VALID_STAT(smb_fname
->st
)) {
5872 if (S_ISDIR(smb_fname
->st
.st_ex_mode
)) {
5873 ptype
= PERM_EXISTING_DIR
;
5875 ptype
= PERM_EXISTING_FILE
;
5878 ptype
= PERM_NEW_FILE
;
5881 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
5883 if (!NT_STATUS_IS_OK(status
)) {
5887 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
5888 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
5889 smb_fname_str_dbg(smb_fname
), (double)size
,
5890 (unsigned int)set_owner
, (unsigned int)set_grp
,
5891 (int)raw_unixmode
));
5893 sbuf
= smb_fname
->st
;
5895 if (!VALID_STAT(sbuf
)) {
5897 * The only valid use of this is to create character and block
5898 * devices, and named pipes. This is deprecated (IMHO) and
5899 * a new info level should be used for mknod. JRA.
5902 return smb_unix_mknod(conn
,
5909 /* Horrible backwards compatibility hack as an old server bug
5910 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
5914 size
= get_file_size_stat(&sbuf
);
5919 * Deal with the UNIX specific mode set.
5922 if (raw_unixmode
!= SMB_MODE_NO_CHANGE
) {
5925 if (fsp
== NULL
|| S_ISLNK(smb_fname
->st
.st_ex_mode
)) {
5926 DBG_WARNING("Can't set mode on symlink %s\n",
5927 smb_fname_str_dbg(smb_fname
));
5928 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5931 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
5932 "setting mode 0%o for file %s\n",
5933 (unsigned int)unixmode
,
5934 smb_fname_str_dbg(smb_fname
)));
5935 ret
= SMB_VFS_FCHMOD(fsp
, unixmode
);
5937 return map_nt_error_from_unix(errno
);
5942 * Deal with the UNIX specific uid set.
5945 if ((set_owner
!= (uid_t
)SMB_UID_NO_CHANGE
) &&
5946 (sbuf
.st_ex_uid
!= set_owner
)) {
5949 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
5950 "changing owner %u for path %s\n",
5951 (unsigned int)set_owner
,
5952 smb_fname_str_dbg(smb_fname
)));
5955 !fsp
->fsp_flags
.is_pathref
&&
5956 fsp_get_io_fd(fsp
) != -1)
5958 ret
= SMB_VFS_FCHOWN(fsp
, set_owner
, (gid_t
)-1);
5961 * UNIX extensions calls must always operate
5964 ret
= SMB_VFS_LCHOWN(conn
, smb_fname
,
5965 set_owner
, (gid_t
)-1);
5969 status
= map_nt_error_from_unix(errno
);
5975 * Deal with the UNIX specific gid set.
5978 if ((set_grp
!= (uid_t
)SMB_GID_NO_CHANGE
) &&
5979 (sbuf
.st_ex_gid
!= set_grp
)) {
5982 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
5983 "changing group %u for file %s\n",
5984 (unsigned int)set_grp
,
5985 smb_fname_str_dbg(smb_fname
)));
5987 !fsp
->fsp_flags
.is_pathref
&&
5988 fsp_get_io_fd(fsp
) != -1)
5990 ret
= SMB_VFS_FCHOWN(fsp
, (uid_t
)-1, set_grp
);
5993 * UNIX extensions calls must always operate
5996 ret
= SMB_VFS_LCHOWN(conn
, smb_fname
, (uid_t
)-1,
6000 status
= map_nt_error_from_unix(errno
);
6005 /* Deal with any size changes. */
6007 if (S_ISREG(sbuf
.st_ex_mode
)) {
6008 status
= smb_set_file_size(conn
, req
,
6014 if (!NT_STATUS_IS_OK(status
)) {
6019 /* Deal with any time changes. */
6020 if (is_omit_timespec(&ft
.mtime
) && is_omit_timespec(&ft
.atime
)) {
6021 /* No change, don't cancel anything. */
6025 id
= vfs_file_id_from_sbuf(conn
, &sbuf
);
6026 for(all_fsps
= file_find_di_first(conn
->sconn
, id
, true); all_fsps
;
6027 all_fsps
= file_find_di_next(all_fsps
, true)) {
6029 * We're setting the time explicitly for UNIX.
6030 * Cancel any pending changes over all handles.
6032 all_fsps
->fsp_flags
.update_write_time_on_close
= false;
6033 TALLOC_FREE(all_fsps
->update_write_time_event
);
6037 * Override the "setting_write_time"
6038 * parameter here as it almost does what
6039 * we need. Just remember if we modified
6040 * mtime and send the notify ourselves.
6042 if (is_omit_timespec(&ft
.mtime
)) {
6043 modify_mtime
= false;
6046 status
= smb_set_file_time(conn
,
6052 notify_fname(conn
, NOTIFY_ACTION_MODIFIED
,
6053 FILE_NOTIFY_CHANGE_LAST_WRITE
, smb_fname
->base_name
);
6058 /****************************************************************************
6059 Deal with SMB_SET_FILE_UNIX_INFO2.
6060 ****************************************************************************/
6062 static NTSTATUS
smb_set_file_unix_info2(connection_struct
*conn
,
6063 struct smb_request
*req
,
6067 struct smb_filename
*smb_fname
)
6070 uint32_t smb_fflags
;
6073 if (total_data
< 116) {
6074 return NT_STATUS_INVALID_PARAMETER
;
6077 /* Start by setting all the fields that are common between UNIX_BASIC
6080 status
= smb_set_file_unix_basic(conn
, req
, pdata
, total_data
,
6082 if (!NT_STATUS_IS_OK(status
)) {
6086 smb_fflags
= IVAL(pdata
, 108);
6087 smb_fmask
= IVAL(pdata
, 112);
6089 /* NB: We should only attempt to alter the file flags if the client
6090 * sends a non-zero mask.
6092 if (smb_fmask
!= 0) {
6093 int stat_fflags
= 0;
6095 if (!map_info2_flags_to_sbuf(&smb_fname
->st
, smb_fflags
,
6096 smb_fmask
, &stat_fflags
)) {
6097 /* Client asked to alter a flag we don't understand. */
6098 return NT_STATUS_INVALID_PARAMETER
;
6101 if (fsp
== NULL
|| S_ISLNK(smb_fname
->st
.st_ex_mode
)) {
6102 DBG_WARNING("Can't change flags on symlink %s\n",
6103 smb_fname_str_dbg(smb_fname
));
6104 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
6106 if (SMB_VFS_FCHFLAGS(fsp
, stat_fflags
) != 0) {
6107 return map_nt_error_from_unix(errno
);
6111 /* XXX: need to add support for changing the create_time here. You
6112 * can do this for paths on Darwin with setattrlist(2). The right way
6113 * to hook this up is probably by extending the VFS utimes interface.
6116 return NT_STATUS_OK
;
6119 /****************************************************************************
6120 Create a directory with POSIX semantics.
6121 ****************************************************************************/
6123 static NTSTATUS
smb_posix_mkdir(connection_struct
*conn
,
6124 struct smb_request
*req
,
6127 struct smb_filename
*smb_fname
,
6128 int *pdata_return_size
)
6130 NTSTATUS status
= NT_STATUS_OK
;
6131 uint32_t raw_unixmode
= 0;
6132 mode_t unixmode
= (mode_t
)0;
6133 files_struct
*fsp
= NULL
;
6134 uint16_t info_level_return
= 0;
6136 char *pdata
= *ppdata
;
6137 struct smb2_create_blobs
*posx
= NULL
;
6139 if (total_data
< 18) {
6140 return NT_STATUS_INVALID_PARAMETER
;
6143 raw_unixmode
= IVAL(pdata
,8);
6144 /* Next 4 bytes are not yet defined. */
6146 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
6147 PERM_NEW_DIR
, &unixmode
);
6148 if (!NT_STATUS_IS_OK(status
)) {
6152 status
= make_smb2_posix_create_ctx(talloc_tos(), &posx
, unixmode
);
6153 if (!NT_STATUS_IS_OK(status
)) {
6154 DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
6159 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
6160 smb_fname_str_dbg(smb_fname
), (unsigned int)unixmode
));
6162 status
= SMB_VFS_CREATE_FILE(
6165 smb_fname
, /* fname */
6166 FILE_READ_ATTRIBUTES
, /* access_mask */
6167 FILE_SHARE_NONE
, /* share_access */
6168 FILE_CREATE
, /* create_disposition*/
6169 FILE_DIRECTORY_FILE
, /* create_options */
6170 0, /* file_attributes */
6171 0, /* oplock_request */
6173 0, /* allocation_size */
6174 0, /* private_flags */
6179 posx
, /* in_context_blobs */
6180 NULL
); /* out_context_blobs */
6184 if (NT_STATUS_IS_OK(status
)) {
6185 close_file_free(req
, &fsp
, NORMAL_CLOSE
);
6188 info_level_return
= SVAL(pdata
,16);
6190 if (info_level_return
== SMB_QUERY_FILE_UNIX_BASIC
) {
6191 *pdata_return_size
= 12 + SMB_FILE_UNIX_BASIC_SIZE
;
6192 } else if (info_level_return
== SMB_QUERY_FILE_UNIX_INFO2
) {
6193 *pdata_return_size
= 12 + SMB_FILE_UNIX_INFO2_SIZE
;
6195 *pdata_return_size
= 12;
6198 /* Realloc the data size */
6199 *ppdata
= (char *)SMB_REALLOC(*ppdata
,*pdata_return_size
);
6200 if (*ppdata
== NULL
) {
6201 *pdata_return_size
= 0;
6202 return NT_STATUS_NO_MEMORY
;
6206 SSVAL(pdata
,0,NO_OPLOCK_RETURN
);
6207 SSVAL(pdata
,2,0); /* No fnum. */
6208 SIVAL(pdata
,4,info
); /* Was directory created. */
6210 switch (info_level_return
) {
6211 case SMB_QUERY_FILE_UNIX_BASIC
:
6212 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_BASIC
);
6213 SSVAL(pdata
,10,0); /* Padding. */
6214 store_file_unix_basic(conn
, pdata
+ 12, fsp
,
6217 case SMB_QUERY_FILE_UNIX_INFO2
:
6218 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_INFO2
);
6219 SSVAL(pdata
,10,0); /* Padding. */
6220 store_file_unix_basic_info2(conn
, pdata
+ 12, fsp
,
6224 SSVAL(pdata
,8,SMB_NO_INFO_LEVEL_RETURNED
);
6225 SSVAL(pdata
,10,0); /* Padding. */
6232 /****************************************************************************
6233 Open/Create a file with POSIX semantics.
6234 ****************************************************************************/
6236 #define SMB_O_RDONLY_MAPPING (FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA)
6237 #define SMB_O_WRONLY_MAPPING (FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA)
6239 static NTSTATUS
smb_posix_open(connection_struct
*conn
,
6240 struct smb_request
*req
,
6243 struct smb_filename
*smb_fname
,
6244 int *pdata_return_size
)
6246 bool extended_oplock_granted
= False
;
6247 char *pdata
= *ppdata
;
6249 uint32_t wire_open_mode
= 0;
6250 uint32_t raw_unixmode
= 0;
6251 uint32_t attributes
= 0;
6252 uint32_t create_disp
= 0;
6253 uint32_t access_mask
= 0;
6254 uint32_t create_options
= FILE_NON_DIRECTORY_FILE
;
6255 NTSTATUS status
= NT_STATUS_OK
;
6256 mode_t unixmode
= (mode_t
)0;
6257 files_struct
*fsp
= NULL
;
6258 int oplock_request
= 0;
6260 uint16_t info_level_return
= 0;
6261 struct smb2_create_blobs
*posx
= NULL
;
6263 if (total_data
< 18) {
6264 return NT_STATUS_INVALID_PARAMETER
;
6267 flags
= IVAL(pdata
,0);
6268 oplock_request
= (flags
& REQUEST_OPLOCK
) ? EXCLUSIVE_OPLOCK
: 0;
6269 if (oplock_request
) {
6270 oplock_request
|= (flags
& REQUEST_BATCH_OPLOCK
) ? BATCH_OPLOCK
: 0;
6273 wire_open_mode
= IVAL(pdata
,4);
6275 if (wire_open_mode
== (SMB_O_CREAT
|SMB_O_DIRECTORY
)) {
6276 return smb_posix_mkdir(conn
, req
,
6283 switch (wire_open_mode
& SMB_ACCMODE
) {
6285 access_mask
= SMB_O_RDONLY_MAPPING
;
6288 access_mask
= SMB_O_WRONLY_MAPPING
;
6291 access_mask
= (SMB_O_RDONLY_MAPPING
|
6292 SMB_O_WRONLY_MAPPING
);
6295 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
6296 (unsigned int)wire_open_mode
));
6297 return NT_STATUS_INVALID_PARAMETER
;
6300 wire_open_mode
&= ~SMB_ACCMODE
;
6302 /* First take care of O_CREAT|O_EXCL interactions. */
6303 switch (wire_open_mode
& (SMB_O_CREAT
| SMB_O_EXCL
)) {
6304 case (SMB_O_CREAT
| SMB_O_EXCL
):
6305 /* File exists fail. File not exist create. */
6306 create_disp
= FILE_CREATE
;
6309 /* File exists open. File not exist create. */
6310 create_disp
= FILE_OPEN_IF
;
6313 /* O_EXCL on its own without O_CREAT is undefined.
6314 We deliberately ignore it as some versions of
6315 Linux CIFSFS can send a bare O_EXCL on the
6316 wire which other filesystems in the kernel
6317 ignore. See bug 9519 for details. */
6322 /* File exists open. File not exist fail. */
6323 create_disp
= FILE_OPEN
;
6326 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
6327 (unsigned int)wire_open_mode
));
6328 return NT_STATUS_INVALID_PARAMETER
;
6331 /* Next factor in the effects of O_TRUNC. */
6332 wire_open_mode
&= ~(SMB_O_CREAT
| SMB_O_EXCL
);
6334 if (wire_open_mode
& SMB_O_TRUNC
) {
6335 switch (create_disp
) {
6337 /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
6338 /* Leave create_disp alone as
6339 (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
6341 /* File exists fail. File not exist create. */
6344 /* SMB_O_CREAT | SMB_O_TRUNC */
6345 /* File exists overwrite. File not exist create. */
6346 create_disp
= FILE_OVERWRITE_IF
;
6350 /* File exists overwrite. File not exist fail. */
6351 create_disp
= FILE_OVERWRITE
;
6354 /* Cannot get here. */
6355 smb_panic("smb_posix_open: logic error");
6356 return NT_STATUS_INVALID_PARAMETER
;
6360 raw_unixmode
= IVAL(pdata
,8);
6361 /* Next 4 bytes are not yet defined. */
6363 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
6364 (VALID_STAT(smb_fname
->st
) ?
6365 PERM_EXISTING_FILE
: PERM_NEW_FILE
),
6368 if (!NT_STATUS_IS_OK(status
)) {
6372 status
= make_smb2_posix_create_ctx(talloc_tos(), &posx
, unixmode
);
6373 if (!NT_STATUS_IS_OK(status
)) {
6374 DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
6379 if (wire_open_mode
& SMB_O_SYNC
) {
6380 create_options
|= FILE_WRITE_THROUGH
;
6382 if (wire_open_mode
& SMB_O_APPEND
) {
6383 access_mask
|= FILE_APPEND_DATA
;
6385 if (wire_open_mode
& SMB_O_DIRECT
) {
6386 attributes
|= FILE_FLAG_NO_BUFFERING
;
6389 if ((wire_open_mode
& SMB_O_DIRECTORY
) ||
6390 VALID_STAT_OF_DIR(smb_fname
->st
)) {
6391 if (access_mask
!= SMB_O_RDONLY_MAPPING
) {
6392 return NT_STATUS_FILE_IS_A_DIRECTORY
;
6394 create_options
&= ~FILE_NON_DIRECTORY_FILE
;
6395 create_options
|= FILE_DIRECTORY_FILE
;
6398 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
6399 smb_fname_str_dbg(smb_fname
),
6400 (unsigned int)wire_open_mode
,
6401 (unsigned int)unixmode
));
6403 status
= SMB_VFS_CREATE_FILE(
6406 smb_fname
, /* fname */
6407 access_mask
, /* access_mask */
6408 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
6410 create_disp
, /* create_disposition*/
6411 create_options
, /* create_options */
6412 attributes
, /* file_attributes */
6413 oplock_request
, /* oplock_request */
6415 0, /* allocation_size */
6416 0, /* private_flags */
6421 posx
, /* in_context_blobs */
6422 NULL
); /* out_context_blobs */
6426 if (!NT_STATUS_IS_OK(status
)) {
6430 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
6431 extended_oplock_granted
= True
;
6434 if(oplock_request
&& EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
6435 extended_oplock_granted
= True
;
6438 info_level_return
= SVAL(pdata
,16);
6440 /* Allocate the correct return size. */
6442 if (info_level_return
== SMB_QUERY_FILE_UNIX_BASIC
) {
6443 *pdata_return_size
= 12 + SMB_FILE_UNIX_BASIC_SIZE
;
6444 } else if (info_level_return
== SMB_QUERY_FILE_UNIX_INFO2
) {
6445 *pdata_return_size
= 12 + SMB_FILE_UNIX_INFO2_SIZE
;
6447 *pdata_return_size
= 12;
6450 /* Realloc the data size */
6451 *ppdata
= (char *)SMB_REALLOC(*ppdata
,*pdata_return_size
);
6452 if (*ppdata
== NULL
) {
6453 close_file_free(req
, &fsp
, ERROR_CLOSE
);
6454 *pdata_return_size
= 0;
6455 return NT_STATUS_NO_MEMORY
;
6459 if (extended_oplock_granted
) {
6460 if (flags
& REQUEST_BATCH_OPLOCK
) {
6461 SSVAL(pdata
,0, BATCH_OPLOCK_RETURN
);
6463 SSVAL(pdata
,0, EXCLUSIVE_OPLOCK_RETURN
);
6465 } else if (fsp
->oplock_type
== LEVEL_II_OPLOCK
) {
6466 SSVAL(pdata
,0, LEVEL_II_OPLOCK_RETURN
);
6468 SSVAL(pdata
,0,NO_OPLOCK_RETURN
);
6471 SSVAL(pdata
,2,fsp
->fnum
);
6472 SIVAL(pdata
,4,info
); /* Was file created etc. */
6474 switch (info_level_return
) {
6475 case SMB_QUERY_FILE_UNIX_BASIC
:
6476 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_BASIC
);
6477 SSVAL(pdata
,10,0); /* padding. */
6478 store_file_unix_basic(conn
, pdata
+ 12, fsp
,
6481 case SMB_QUERY_FILE_UNIX_INFO2
:
6482 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_INFO2
);
6483 SSVAL(pdata
,10,0); /* padding. */
6484 store_file_unix_basic_info2(conn
, pdata
+ 12, fsp
,
6488 SSVAL(pdata
,8,SMB_NO_INFO_LEVEL_RETURNED
);
6489 SSVAL(pdata
,10,0); /* padding. */
6492 return NT_STATUS_OK
;
6495 /****************************************************************************
6496 Delete a file with POSIX semantics.
6497 ****************************************************************************/
6499 static NTSTATUS
smb_posix_unlink(connection_struct
*conn
,
6500 struct smb_request
*req
,
6503 struct smb_filename
*smb_fname
)
6505 NTSTATUS status
= NT_STATUS_OK
;
6506 files_struct
*fsp
= NULL
;
6510 int create_options
= 0;
6511 struct share_mode_lock
*lck
= NULL
;
6512 bool other_nonposix_opens
;
6513 struct smb2_create_blobs
*posx
= NULL
;
6515 if (total_data
< 2) {
6516 return NT_STATUS_INVALID_PARAMETER
;
6519 flags
= SVAL(pdata
,0);
6521 if (!VALID_STAT(smb_fname
->st
)) {
6522 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
6525 if ((flags
== SMB_POSIX_UNLINK_DIRECTORY_TARGET
) &&
6526 !VALID_STAT_OF_DIR(smb_fname
->st
)) {
6527 return NT_STATUS_NOT_A_DIRECTORY
;
6530 DEBUG(10,("smb_posix_unlink: %s %s\n",
6531 (flags
== SMB_POSIX_UNLINK_DIRECTORY_TARGET
) ? "directory" : "file",
6532 smb_fname_str_dbg(smb_fname
)));
6534 if (VALID_STAT_OF_DIR(smb_fname
->st
)) {
6535 create_options
|= FILE_DIRECTORY_FILE
;
6538 status
= make_smb2_posix_create_ctx(talloc_tos(), &posx
, 0777);
6539 if (!NT_STATUS_IS_OK(status
)) {
6540 DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
6545 status
= SMB_VFS_CREATE_FILE(
6548 smb_fname
, /* fname */
6549 DELETE_ACCESS
, /* access_mask */
6550 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
6552 FILE_OPEN
, /* create_disposition*/
6553 create_options
, /* create_options */
6554 0, /* file_attributes */
6555 0, /* oplock_request */
6557 0, /* allocation_size */
6558 0, /* private_flags */
6563 posx
, /* in_context_blobs */
6564 NULL
); /* out_context_blobs */
6568 if (!NT_STATUS_IS_OK(status
)) {
6573 * Don't lie to client. If we can't really delete due to
6574 * non-POSIX opens return SHARING_VIOLATION.
6577 lck
= get_existing_share_mode_lock(talloc_tos(), fsp
->file_id
);
6579 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
6580 "lock for file %s\n", fsp_str_dbg(fsp
)));
6581 close_file_free(req
, &fsp
, NORMAL_CLOSE
);
6582 return NT_STATUS_INVALID_PARAMETER
;
6585 other_nonposix_opens
= has_other_nonposix_opens(lck
, fsp
);
6586 if (other_nonposix_opens
) {
6587 /* Fail with sharing violation. */
6589 close_file_free(req
, &fsp
, NORMAL_CLOSE
);
6590 return NT_STATUS_SHARING_VIOLATION
;
6594 * Set the delete on close.
6596 status
= smb_set_file_disposition_info(conn
,
6604 if (!NT_STATUS_IS_OK(status
)) {
6605 close_file_free(req
, &fsp
, NORMAL_CLOSE
);
6608 return close_file_free(req
, &fsp
, NORMAL_CLOSE
);
6611 static NTSTATUS
smbd_do_posix_setfilepathinfo(struct connection_struct
*conn
,
6612 struct smb_request
*req
,
6613 TALLOC_CTX
*mem_ctx
,
6614 uint16_t info_level
,
6615 struct smb_filename
*smb_fname
,
6621 char *pdata
= *ppdata
;
6622 NTSTATUS status
= NT_STATUS_OK
;
6623 int data_return_size
= 0;
6627 if (!CAN_WRITE(conn
)) {
6628 /* Allow POSIX opens. The open path will deny
6629 * any non-readonly opens. */
6630 if (info_level
!= SMB_POSIX_PATH_OPEN
) {
6631 return NT_STATUS_DOS(ERRSRV
, ERRaccess
);
6635 DBG_DEBUG("file=%s (%s) info_level=%d totdata=%d\n",
6636 smb_fname_str_dbg(smb_fname
),
6641 switch (info_level
) {
6642 case SMB_SET_FILE_UNIX_BASIC
:
6644 status
= smb_set_file_unix_basic(conn
, req
,
6652 case SMB_SET_FILE_UNIX_INFO2
:
6654 status
= smb_set_file_unix_info2(conn
, req
,
6662 case SMB_SET_FILE_UNIX_LINK
:
6664 if (smb_fname
== NULL
) {
6665 /* We must have a pathname for this. */
6666 return NT_STATUS_INVALID_LEVEL
;
6668 status
= smb_set_file_unix_link(conn
, req
, pdata
,
6669 total_data
, smb_fname
);
6673 case SMB_SET_FILE_UNIX_HLINK
:
6675 if (smb_fname
== NULL
) {
6676 /* We must have a pathname for this. */
6677 return NT_STATUS_INVALID_LEVEL
;
6679 status
= smb_set_file_unix_hlink(conn
, req
,
6685 #if defined(HAVE_POSIX_ACLS)
6686 case SMB_SET_POSIX_ACL
:
6688 status
= smb_set_posix_acl(conn
,
6698 #if defined(WITH_SMB1SERVER)
6699 case SMB_SET_POSIX_LOCK
:
6702 return NT_STATUS_INVALID_LEVEL
;
6704 status
= smb_set_posix_lock(conn
, req
,
6705 pdata
, total_data
, fsp
);
6710 case SMB_POSIX_PATH_OPEN
:
6712 if (smb_fname
== NULL
) {
6713 /* We must have a pathname for this. */
6714 return NT_STATUS_INVALID_LEVEL
;
6717 status
= smb_posix_open(conn
, req
,
6725 case SMB_POSIX_PATH_UNLINK
:
6727 if (smb_fname
== NULL
) {
6728 /* We must have a pathname for this. */
6729 return NT_STATUS_INVALID_LEVEL
;
6732 status
= smb_posix_unlink(conn
, req
,
6740 return NT_STATUS_INVALID_LEVEL
;
6743 if (!NT_STATUS_IS_OK(status
)) {
6747 *ret_data_size
= data_return_size
;
6748 return NT_STATUS_OK
;
6751 NTSTATUS
smbd_do_setfilepathinfo(connection_struct
*conn
,
6752 struct smb_request
*req
,
6753 TALLOC_CTX
*mem_ctx
,
6754 uint16_t info_level
,
6756 struct smb_filename
*smb_fname
,
6757 char **ppdata
, int total_data
,
6760 char *pdata
= *ppdata
;
6761 NTSTATUS status
= NT_STATUS_OK
;
6762 int data_return_size
= 0;
6764 if (INFO_LEVEL_IS_UNIX(info_level
)) {
6765 if (!lp_smb1_unix_extensions()) {
6766 return NT_STATUS_INVALID_LEVEL
;
6768 if (!req
->posix_pathnames
) {
6769 return NT_STATUS_INVALID_LEVEL
;
6771 status
= smbd_do_posix_setfilepathinfo(conn
,
6780 if (!NT_STATUS_IS_OK(status
)) {
6783 *ret_data_size
= data_return_size
;
6784 return NT_STATUS_OK
;
6789 DEBUG(3,("smbd_do_setfilepathinfo: %s (%s) info_level=%d "
6790 "totdata=%d\n", smb_fname_str_dbg(smb_fname
),
6792 info_level
, total_data
));
6794 switch (info_level
) {
6796 case SMB_INFO_STANDARD
:
6798 status
= smb_set_info_standard(conn
,
6806 case SMB_INFO_SET_EA
:
6808 status
= smb_info_set_ea(conn
,
6816 case SMB_SET_FILE_BASIC_INFO
:
6817 case SMB_FILE_BASIC_INFORMATION
:
6819 status
= smb_set_file_basic_info(conn
,
6827 case SMB_FILE_ALLOCATION_INFORMATION
:
6828 case SMB_SET_FILE_ALLOCATION_INFO
:
6830 status
= smb_set_file_allocation_info(conn
, req
,
6838 case SMB_FILE_END_OF_FILE_INFORMATION
:
6839 case SMB_SET_FILE_END_OF_FILE_INFO
:
6842 * XP/Win7 both fail after the createfile with
6843 * SMB_SET_FILE_END_OF_FILE_INFO but not
6844 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
6845 * The level is known here, so pass it down
6849 (info_level
== SMB_SET_FILE_END_OF_FILE_INFO
);
6851 status
= smb_set_file_end_of_file_info(conn
, req
,
6860 case SMB_FILE_DISPOSITION_INFORMATION
:
6861 case SMB_SET_FILE_DISPOSITION_INFO
: /* Set delete on close for open file. */
6864 /* JRA - We used to just ignore this on a path ?
6865 * Shouldn't this be invalid level on a pathname
6868 if (tran_call
!= TRANSACT2_SETFILEINFO
) {
6869 return ERROR_NT(NT_STATUS_INVALID_LEVEL
);
6872 status
= smb_set_file_disposition_info(conn
,
6880 case SMB_FILE_POSITION_INFORMATION
:
6882 status
= smb_file_position_information(conn
,
6889 case SMB_FILE_FULL_EA_INFORMATION
:
6891 status
= smb_set_file_full_ea_info(conn
,
6898 /* From tridge Samba4 :
6899 * MODE_INFORMATION in setfileinfo (I have no
6900 * idea what "mode information" on a file is - it takes a value of 0,
6901 * 2, 4 or 6. What could it be?).
6904 case SMB_FILE_MODE_INFORMATION
:
6906 status
= smb_file_mode_information(conn
,
6912 /* [MS-SMB2] 3.3.5.21.1 states we MUST fail with STATUS_NOT_SUPPORTED. */
6913 case SMB_FILE_VALID_DATA_LENGTH_INFORMATION
:
6914 case SMB_FILE_SHORT_NAME_INFORMATION
:
6915 return NT_STATUS_NOT_SUPPORTED
;
6917 case SMB_FILE_RENAME_INFORMATION
:
6919 status
= smb_file_rename_information(conn
, req
,
6925 case SMB2_FILE_RENAME_INFORMATION_INTERNAL
:
6927 /* SMB2 rename information. */
6928 status
= smb2_file_rename_information(conn
, req
,
6934 case SMB_FILE_LINK_INFORMATION
:
6936 status
= smb_file_link_information(conn
, req
,
6943 return NT_STATUS_INVALID_LEVEL
;
6946 if (!NT_STATUS_IS_OK(status
)) {
6950 *ret_data_size
= data_return_size
;
6951 return NT_STATUS_OK
;