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"
30 #include "smbd/smbd.h"
31 #include "smbd/globals.h"
32 #include "../libcli/auth/libcli_auth.h"
33 #include "../librpc/gen_ndr/xattr.h"
34 #include "../librpc/gen_ndr/ndr_security.h"
35 #include "../librpc/gen_ndr/open_files.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 #define DIR_ENTRY_SAFETY_MARGIN 4096
47 static char *store_file_unix_basic(connection_struct
*conn
,
50 const SMB_STRUCT_STAT
*psbuf
);
52 static char *store_file_unix_basic_info2(connection_struct
*conn
,
55 const SMB_STRUCT_STAT
*psbuf
);
57 /****************************************************************************
58 Check if an open file handle or smb_fname is a symlink.
59 ****************************************************************************/
61 static NTSTATUS
refuse_symlink(connection_struct
*conn
,
62 const files_struct
*fsp
,
63 const struct smb_filename
*smb_fname
)
66 const SMB_STRUCT_STAT
*pst
= NULL
;
69 pst
= &fsp
->fsp_name
->st
;
74 if (!VALID_STAT(*pst
)) {
75 int ret
= vfs_stat_smb_basename(conn
,
78 if (ret
== -1 && errno
!= ENOENT
) {
79 return map_nt_error_from_unix(errno
);
80 } else if (ret
== -1) {
81 /* it's not a symlink.. */
87 if (S_ISLNK(pst
->st_ex_mode
)) {
88 return NT_STATUS_ACCESS_DENIED
;
93 NTSTATUS
check_access_fsp(const struct files_struct
*fsp
,
96 if (!(fsp
->access_mask
& access_mask
)) {
97 return NT_STATUS_ACCESS_DENIED
;
102 /********************************************************************
103 The canonical "check access" based on object handle or path function.
104 ********************************************************************/
106 NTSTATUS
check_access(connection_struct
*conn
,
108 const struct smb_filename
*smb_fname
,
109 uint32_t access_mask
)
114 status
= check_access_fsp(fsp
, access_mask
);
116 status
= smbd_check_access_rights(conn
, smb_fname
,
123 /********************************************************************
124 Roundup a value to the nearest allocation roundup size boundary.
125 Only do this for Windows clients.
126 ********************************************************************/
128 uint64_t smb_roundup(connection_struct
*conn
, uint64_t val
)
130 uint64_t rval
= lp_allocation_roundup_size(SNUM(conn
));
132 /* Only roundup for Windows clients. */
133 enum remote_arch_types ra_type
= get_remote_arch();
134 if (rval
&& (ra_type
!= RA_SAMBA
) && (ra_type
!= RA_CIFSFS
)) {
135 val
= SMB_ROUNDUP(val
,rval
);
140 /********************************************************************
141 Create a 64 bit FileIndex. If the file is on the same device as
142 the root of the share, just return the 64-bit inode. If it isn't,
143 mangle as we used to do.
144 ********************************************************************/
146 uint64_t get_FileIndex(connection_struct
*conn
, const SMB_STRUCT_STAT
*psbuf
)
149 if (conn
->sconn
->aapl_zero_file_id
) {
152 if (conn
->base_share_dev
== psbuf
->st_ex_dev
) {
153 return (uint64_t)psbuf
->st_ex_ino
;
155 file_index
= ((psbuf
->st_ex_ino
) & UINT32_MAX
); /* FileIndexLow */
156 file_index
|= ((uint64_t)((psbuf
->st_ex_dev
) & UINT32_MAX
)) << 32; /* FileIndexHigh */
161 /********************************************************************
162 Globally (for this connection / multi-channel) disable file-ID
163 calculation. This is required to be global because it serves
164 Macs in AAPL mode, which is globally set.
165 ********************************************************************/
166 void aapl_force_zero_file_id(struct smbd_server_connection
*sconn
)
168 sconn
->aapl_zero_file_id
= true;
171 /****************************************************************************
172 Utility functions for dealing with extended attributes.
173 ****************************************************************************/
175 /****************************************************************************
176 Refuse to allow clients to overwrite our private xattrs.
177 ****************************************************************************/
179 bool samba_private_attr_name(const char *unix_ea_name
)
181 static const char * const prohibited_ea_names
[] = {
182 SAMBA_POSIX_INHERITANCE_EA_NAME
,
183 SAMBA_XATTR_DOS_ATTRIB
,
191 for (i
= 0; prohibited_ea_names
[i
]; i
++) {
192 if (strequal( prohibited_ea_names
[i
], unix_ea_name
))
195 if (strncasecmp_m(unix_ea_name
, SAMBA_XATTR_DOSSTREAM_PREFIX
,
196 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX
)) == 0) {
202 /****************************************************************************
203 Get one EA value. Fill in a struct ea_struct.
204 ****************************************************************************/
206 NTSTATUS
get_ea_value(TALLOC_CTX
*mem_ctx
,
207 connection_struct
*conn
,
209 const struct smb_filename
*smb_fname
,
211 struct ea_struct
*pea
)
213 /* Get the value of this xattr. Max size is 64k. */
214 size_t attr_size
= 256;
220 val
= talloc_realloc(mem_ctx
, val
, char, attr_size
);
222 return NT_STATUS_NO_MEMORY
;
225 if (fsp
&& fsp
->fh
->fd
!= -1) {
226 sizeret
= SMB_VFS_FGETXATTR(fsp
, ea_name
, val
, attr_size
);
228 sizeret
= SMB_VFS_GETXATTR(conn
, smb_fname
,
229 ea_name
, val
, attr_size
);
232 if (sizeret
== -1 && errno
== ERANGE
&& attr_size
!= 65536) {
238 return map_nt_error_from_unix(errno
);
241 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name
, (unsigned int)sizeret
));
242 dump_data(10, (uint8_t *)val
, sizeret
);
245 if (strnequal(ea_name
, "user.", 5)) {
246 pea
->name
= talloc_strdup(mem_ctx
, &ea_name
[5]);
248 pea
->name
= talloc_strdup(mem_ctx
, ea_name
);
250 if (pea
->name
== NULL
) {
252 return NT_STATUS_NO_MEMORY
;
254 pea
->value
.data
= (unsigned char *)val
;
255 pea
->value
.length
= (size_t)sizeret
;
259 NTSTATUS
get_ea_names_from_file(TALLOC_CTX
*mem_ctx
,
260 connection_struct
*conn
,
262 const struct smb_filename
*smb_fname
,
267 /* Get a list of all xattrs. Max namesize is 64k. */
268 size_t ea_namelist_size
= 1024;
269 char *ea_namelist
= smallbuf
;
270 char *to_free
= NULL
;
275 ssize_t sizeret
= -1;
283 status
= refuse_symlink(conn
, fsp
, smb_fname
);
284 if (!NT_STATUS_IS_OK(status
)) {
286 * Just return no EA's on a symlink.
291 if (fsp
&& fsp
->fh
->fd
!= -1) {
292 sizeret
= SMB_VFS_FLISTXATTR(fsp
, ea_namelist
,
295 sizeret
= SMB_VFS_LISTXATTR(conn
,
301 if ((sizeret
== -1) && (errno
== ERANGE
)) {
302 ea_namelist_size
= 65536;
303 ea_namelist
= talloc_array(mem_ctx
, char, ea_namelist_size
);
304 if (ea_namelist
== NULL
) {
305 return NT_STATUS_NO_MEMORY
;
307 to_free
= ea_namelist
;
309 if (fsp
&& fsp
->fh
->fd
!= -1) {
310 sizeret
= SMB_VFS_FLISTXATTR(fsp
, ea_namelist
,
313 sizeret
= SMB_VFS_LISTXATTR(conn
,
321 status
= map_nt_error_from_unix(errno
);
322 TALLOC_FREE(to_free
);
326 DBG_DEBUG("ea_namelist size = %zd\n", sizeret
);
329 TALLOC_FREE(to_free
);
334 * Ensure the result is 0-terminated
337 if (ea_namelist
[sizeret
-1] != '\0') {
338 TALLOC_FREE(to_free
);
339 return NT_STATUS_INTERNAL_ERROR
;
347 for (p
= ea_namelist
; p
- ea_namelist
< sizeret
; p
+= strlen(p
)+1) {
351 *pnum_names
= num_names
;
353 if (pnames
== NULL
) {
354 TALLOC_FREE(to_free
);
358 names
= talloc_array(mem_ctx
, char *, num_names
);
360 DEBUG(0, ("talloc failed\n"));
361 TALLOC_FREE(to_free
);
362 return NT_STATUS_NO_MEMORY
;
365 if (ea_namelist
== smallbuf
) {
366 ea_namelist
= talloc_memdup(names
, smallbuf
, sizeret
);
367 if (ea_namelist
== NULL
) {
369 return NT_STATUS_NO_MEMORY
;
372 talloc_steal(names
, ea_namelist
);
374 ea_namelist
= talloc_realloc(names
, ea_namelist
, char,
376 if (ea_namelist
== NULL
) {
378 return NT_STATUS_NO_MEMORY
;
384 for (p
= ea_namelist
; p
- ea_namelist
< sizeret
; p
+= strlen(p
)+1) {
385 names
[num_names
++] = p
;
393 /****************************************************************************
394 Return a linked list of the total EA's. Plus the total size
395 ****************************************************************************/
397 static NTSTATUS
get_ea_list_from_file_path(TALLOC_CTX
*mem_ctx
,
398 connection_struct
*conn
,
400 const struct smb_filename
*smb_fname
,
401 size_t *pea_total_len
,
402 struct ea_list
**ea_list
)
404 /* Get a list of all xattrs. Max namesize is 64k. */
407 struct ea_list
*ea_list_head
= NULL
;
408 bool posix_pathnames
= false;
414 if (!lp_ea_support(SNUM(conn
))) {
420 (fsp
->fsp_name
->flags
& SMB_FILENAME_POSIX_PATH
);
422 posix_pathnames
= (smb_fname
->flags
& SMB_FILENAME_POSIX_PATH
);
425 status
= get_ea_names_from_file(talloc_tos(),
432 if (!NT_STATUS_IS_OK(status
)) {
436 if (num_names
== 0) {
440 for (i
=0; i
<num_names
; i
++) {
441 struct ea_list
*listp
;
444 if (strnequal(names
[i
], "system.", 7)
445 || samba_private_attr_name(names
[i
]))
449 * Filter out any underlying POSIX EA names
450 * that a Windows client can't handle.
452 if (!posix_pathnames
&&
453 is_invalid_windows_ea_name(names
[i
])) {
457 listp
= talloc(mem_ctx
, struct ea_list
);
459 return NT_STATUS_NO_MEMORY
;
462 status
= get_ea_value(listp
,
469 if (!NT_STATUS_IS_OK(status
)) {
474 if (listp
->ea
.value
.length
== 0) {
476 * We can never return a zero length EA.
477 * Windows reports the EA's as corrupted.
483 push_ascii_fstring(dos_ea_name
, listp
->ea
.name
);
486 4 + strlen(dos_ea_name
) + 1 + listp
->ea
.value
.length
;
488 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
489 "= %u\n", (unsigned int)*pea_total_len
, dos_ea_name
,
490 (unsigned int)listp
->ea
.value
.length
));
492 DLIST_ADD_END(ea_list_head
, listp
);
496 /* Add on 4 for total length. */
497 if (*pea_total_len
) {
501 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
502 (unsigned int)*pea_total_len
));
504 *ea_list
= ea_list_head
;
508 static NTSTATUS
get_ea_list_from_file(TALLOC_CTX
*mem_ctx
, connection_struct
*conn
, files_struct
*fsp
,
509 const struct smb_filename
*smb_fname
, size_t *pea_total_len
, struct ea_list
**ea_list
)
514 if (!lp_ea_support(SNUM(conn
))) {
518 if (is_ntfs_stream_smb_fname(smb_fname
)) {
519 return NT_STATUS_INVALID_PARAMETER
;
522 return get_ea_list_from_file_path(mem_ctx
,
530 /****************************************************************************
531 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
533 ****************************************************************************/
535 static unsigned int fill_ea_buffer(TALLOC_CTX
*mem_ctx
, char *pdata
, unsigned int total_data_size
,
536 connection_struct
*conn
, struct ea_list
*ea_list
)
538 unsigned int ret_data_size
= 4;
541 SMB_ASSERT(total_data_size
>= 4);
543 if (!lp_ea_support(SNUM(conn
))) {
548 for (p
= pdata
+ 4; ea_list
; ea_list
= ea_list
->next
) {
551 push_ascii_fstring(dos_ea_name
, ea_list
->ea
.name
);
552 dos_namelen
= strlen(dos_ea_name
);
553 if (dos_namelen
> 255 || dos_namelen
== 0) {
556 if (ea_list
->ea
.value
.length
> 65535) {
559 if (4 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
> total_data_size
) {
563 /* We know we have room. */
564 SCVAL(p
,0,ea_list
->ea
.flags
);
565 SCVAL(p
,1,dos_namelen
);
566 SSVAL(p
,2,ea_list
->ea
.value
.length
);
567 strlcpy(p
+4, dos_ea_name
, dos_namelen
+1);
568 memcpy( p
+ 4 + dos_namelen
+ 1, ea_list
->ea
.value
.data
, ea_list
->ea
.value
.length
);
570 total_data_size
-= 4 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
;
571 p
+= 4 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
;
574 ret_data_size
= PTR_DIFF(p
, pdata
);
575 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size
));
576 SIVAL(pdata
,0,ret_data_size
);
577 return ret_data_size
;
580 static NTSTATUS
fill_ea_chained_buffer(TALLOC_CTX
*mem_ctx
,
582 unsigned int total_data_size
,
583 unsigned int *ret_data_size
,
584 connection_struct
*conn
,
585 struct ea_list
*ea_list
)
587 uint8_t *p
= (uint8_t *)pdata
;
588 uint8_t *last_start
= NULL
;
589 bool do_store_data
= (pdata
!= NULL
);
593 if (!lp_ea_support(SNUM(conn
))) {
594 return NT_STATUS_NO_EAS_ON_FILE
;
597 for (; ea_list
; ea_list
= ea_list
->next
) {
603 if (last_start
!= NULL
&& do_store_data
) {
604 SIVAL(last_start
, 0, PTR_DIFF(p
, last_start
));
608 push_ascii_fstring(dos_ea_name
, ea_list
->ea
.name
);
609 dos_namelen
= strlen(dos_ea_name
);
610 if (dos_namelen
> 255 || dos_namelen
== 0) {
611 return NT_STATUS_INTERNAL_ERROR
;
613 if (ea_list
->ea
.value
.length
> 65535) {
614 return NT_STATUS_INTERNAL_ERROR
;
617 this_size
= 0x08 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
;
620 pad
= (4 - (this_size
% 4)) % 4;
625 if (this_size
> total_data_size
) {
626 return NT_STATUS_INFO_LENGTH_MISMATCH
;
629 /* We know we have room. */
630 SIVAL(p
, 0x00, 0); /* next offset */
631 SCVAL(p
, 0x04, ea_list
->ea
.flags
);
632 SCVAL(p
, 0x05, dos_namelen
);
633 SSVAL(p
, 0x06, ea_list
->ea
.value
.length
);
634 strlcpy((char *)(p
+0x08), dos_ea_name
, dos_namelen
+1);
635 memcpy(p
+ 0x08 + dos_namelen
+ 1, ea_list
->ea
.value
.data
, ea_list
->ea
.value
.length
);
637 memset(p
+ 0x08 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
,
641 total_data_size
-= this_size
;
647 *ret_data_size
= PTR_DIFF(p
, pdata
);
648 DEBUG(10,("fill_ea_chained_buffer: data_size = %u\n", *ret_data_size
));
652 static unsigned int estimate_ea_size(connection_struct
*conn
, files_struct
*fsp
, const struct smb_filename
*smb_fname
)
654 size_t total_ea_len
= 0;
656 struct ea_list
*ea_list
= NULL
;
658 if (!lp_ea_support(SNUM(conn
))) {
661 mem_ctx
= talloc_stackframe();
663 /* If this is a stream fsp, then we need to instead find the
664 * estimated ea len from the main file, not the stream
665 * (streams cannot have EAs), but the estimate isn't just 0 in
667 if (is_ntfs_stream_smb_fname(smb_fname
)) {
670 (void)get_ea_list_from_file_path(mem_ctx
,
676 if(conn
->sconn
->using_smb2
) {
678 unsigned int ret_data_size
;
680 * We're going to be using fill_ea_chained_buffer() to
681 * marshall EA's - this size is significantly larger
682 * than the SMB1 buffer. Re-calculate the size without
685 status
= fill_ea_chained_buffer(mem_ctx
,
691 if (!NT_STATUS_IS_OK(status
)) {
694 total_ea_len
= ret_data_size
;
696 TALLOC_FREE(mem_ctx
);
700 /****************************************************************************
701 Ensure the EA name is case insensitive by matching any existing EA name.
702 ****************************************************************************/
704 static void canonicalize_ea_name(connection_struct
*conn
,
706 const struct smb_filename
*smb_fname
,
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_file_path(mem_ctx
,
718 if (!NT_STATUS_IS_OK(status
)) {
722 for (; ea_list
; ea_list
= ea_list
->next
) {
723 if (strequal(&unix_ea_name
[5], ea_list
->ea
.name
)) {
724 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
725 &unix_ea_name
[5], ea_list
->ea
.name
));
726 strlcpy(&unix_ea_name
[5], ea_list
->ea
.name
, sizeof(fstring
)-5);
732 /****************************************************************************
733 Set or delete an extended attribute.
734 ****************************************************************************/
736 NTSTATUS
set_ea(connection_struct
*conn
, files_struct
*fsp
,
737 const struct smb_filename
*smb_fname
, struct ea_list
*ea_list
)
740 bool posix_pathnames
= false;
742 if (!lp_ea_support(SNUM(conn
))) {
743 return NT_STATUS_EAS_NOT_SUPPORTED
;
748 (fsp
->fsp_name
->flags
& SMB_FILENAME_POSIX_PATH
);
750 posix_pathnames
= (smb_fname
->flags
& SMB_FILENAME_POSIX_PATH
);
753 status
= refuse_symlink(conn
, fsp
, smb_fname
);
754 if (!NT_STATUS_IS_OK(status
)) {
758 status
= check_access(conn
, fsp
, smb_fname
, FILE_WRITE_EA
);
759 if (!NT_STATUS_IS_OK(status
)) {
763 /* Setting EAs on streams isn't supported. */
764 if (is_ntfs_stream_smb_fname(smb_fname
)) {
765 return NT_STATUS_INVALID_PARAMETER
;
769 * Filter out invalid Windows EA names - before
770 * we set *any* of them.
773 if (!posix_pathnames
&& ea_list_has_invalid_name(ea_list
)) {
774 return STATUS_INVALID_EA_NAME
;
777 for (;ea_list
; ea_list
= ea_list
->next
) {
779 fstring unix_ea_name
;
781 fstrcpy(unix_ea_name
, "user."); /* All EA's must start with user. */
782 fstrcat(unix_ea_name
, ea_list
->ea
.name
);
784 canonicalize_ea_name(conn
,
789 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name
, (unsigned int)ea_list
->ea
.value
.length
));
791 if (samba_private_attr_name(unix_ea_name
)) {
792 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name
));
793 return NT_STATUS_ACCESS_DENIED
;
796 if (ea_list
->ea
.value
.length
== 0) {
797 /* Remove the attribute. */
798 if (fsp
&& (fsp
->fh
->fd
!= -1)) {
799 DEBUG(10,("set_ea: deleting ea name %s on "
800 "file %s by file descriptor.\n",
801 unix_ea_name
, fsp_str_dbg(fsp
)));
802 ret
= SMB_VFS_FREMOVEXATTR(fsp
, unix_ea_name
);
804 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
805 unix_ea_name
, smb_fname
->base_name
));
806 ret
= SMB_VFS_REMOVEXATTR(conn
,
811 /* Removing a non existent attribute always succeeds. */
812 if (ret
== -1 && errno
== ENOATTR
) {
813 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
819 if (fsp
&& (fsp
->fh
->fd
!= -1)) {
820 DEBUG(10,("set_ea: setting ea name %s on file "
821 "%s by file descriptor.\n",
822 unix_ea_name
, fsp_str_dbg(fsp
)));
823 ret
= SMB_VFS_FSETXATTR(fsp
, unix_ea_name
,
824 ea_list
->ea
.value
.data
, ea_list
->ea
.value
.length
, 0);
826 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
827 unix_ea_name
, smb_fname
->base_name
));
828 ret
= SMB_VFS_SETXATTR(conn
,
831 ea_list
->ea
.value
.data
,
832 ea_list
->ea
.value
.length
,
839 if (errno
== ENOTSUP
) {
840 return NT_STATUS_EAS_NOT_SUPPORTED
;
843 return map_nt_error_from_unix(errno
);
849 /****************************************************************************
850 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
851 ****************************************************************************/
853 static struct ea_list
*read_ea_name_list(TALLOC_CTX
*ctx
, const char *pdata
, size_t data_size
)
855 struct ea_list
*ea_list_head
= NULL
;
856 size_t converted_size
, offset
= 0;
858 while (offset
+ 2 < data_size
) {
859 struct ea_list
*eal
= talloc_zero(ctx
, struct ea_list
);
860 unsigned int namelen
= CVAL(pdata
,offset
);
862 offset
++; /* Go past the namelen byte. */
864 /* integer wrap paranioa. */
865 if ((offset
+ namelen
< offset
) || (offset
+ namelen
< namelen
) ||
866 (offset
> data_size
) || (namelen
> data_size
) ||
867 (offset
+ namelen
>= data_size
)) {
870 /* Ensure the name is null terminated. */
871 if (pdata
[offset
+ namelen
] != '\0') {
874 if (!pull_ascii_talloc(ctx
, &eal
->ea
.name
, &pdata
[offset
],
876 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
877 "failed: %s", strerror(errno
)));
883 offset
+= (namelen
+ 1); /* Go past the name + terminating zero. */
884 DLIST_ADD_END(ea_list_head
, eal
);
885 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal
->ea
.name
));
891 /****************************************************************************
892 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
893 ****************************************************************************/
895 static struct ea_list
*read_ea_list(TALLOC_CTX
*ctx
, const char *pdata
, size_t data_size
)
897 struct ea_list
*ea_list_head
= NULL
;
899 size_t bytes_used
= 0;
901 while (offset
< data_size
) {
902 struct ea_list
*eal
= read_ea_list_entry(ctx
, pdata
+ offset
, data_size
- offset
, &bytes_used
);
908 DLIST_ADD_END(ea_list_head
, eal
);
909 offset
+= bytes_used
;
915 /****************************************************************************
916 Count the total EA size needed.
917 ****************************************************************************/
919 static size_t ea_list_size(struct ea_list
*ealist
)
922 struct ea_list
*listp
;
925 for (listp
= ealist
; listp
; listp
= listp
->next
) {
926 push_ascii_fstring(dos_ea_name
, listp
->ea
.name
);
927 ret
+= 4 + strlen(dos_ea_name
) + 1 + listp
->ea
.value
.length
;
929 /* Add on 4 for total length. */
937 /****************************************************************************
938 Return a union of EA's from a file list and a list of names.
939 The TALLOC context for the two lists *MUST* be identical as we steal
940 memory from one list to add to another. JRA.
941 ****************************************************************************/
943 static struct ea_list
*ea_list_union(struct ea_list
*name_list
, struct ea_list
*file_list
, size_t *total_ea_len
)
945 struct ea_list
*nlistp
, *flistp
;
947 for (nlistp
= name_list
; nlistp
; nlistp
= nlistp
->next
) {
948 for (flistp
= file_list
; flistp
; flistp
= flistp
->next
) {
949 if (strequal(nlistp
->ea
.name
, flistp
->ea
.name
)) {
955 /* Copy the data from this entry. */
956 nlistp
->ea
.flags
= flistp
->ea
.flags
;
957 nlistp
->ea
.value
= flistp
->ea
.value
;
960 nlistp
->ea
.flags
= 0;
961 ZERO_STRUCT(nlistp
->ea
.value
);
965 *total_ea_len
= ea_list_size(name_list
);
969 /****************************************************************************
970 Send the required number of replies back.
971 We assume all fields other than the data fields are
972 set correctly for the type of call.
973 HACK ! Always assumes smb_setup field is zero.
974 ****************************************************************************/
976 void send_trans2_replies(connection_struct
*conn
,
977 struct smb_request
*req
,
985 /* As we are using a protocol > LANMAN1 then the max_send
986 variable must have been set in the sessetupX call.
987 This takes precedence over the max_xmit field in the
988 global struct. These different max_xmit variables should
989 be merged as this is now too confusing */
991 int data_to_send
= datasize
;
992 int params_to_send
= paramsize
;
994 const char *pp
= params
;
995 const char *pd
= pdata
;
996 int params_sent_thistime
, data_sent_thistime
, total_sent_thistime
;
997 int alignment_offset
= 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
998 int data_alignment_offset
= 0;
999 bool overflow
= False
;
1000 struct smbXsrv_connection
*xconn
= req
->xconn
;
1001 int max_send
= xconn
->smb1
.sessions
.max_send
;
1003 /* Modify the data_to_send and datasize and set the error if
1004 we're trying to send more than max_data_bytes. We still send
1005 the part of the packet(s) that fit. Strange, but needed
1008 if (max_data_bytes
> 0 && datasize
> max_data_bytes
) {
1009 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
1010 max_data_bytes
, datasize
));
1011 datasize
= data_to_send
= max_data_bytes
;
1015 /* If there genuinely are no parameters or data to send just send the empty packet */
1017 if(params_to_send
== 0 && data_to_send
== 0) {
1018 reply_outbuf(req
, 10, 0);
1019 if (NT_STATUS_V(status
)) {
1022 ntstatus_to_dos(status
, &eclass
, &ecode
);
1023 error_packet_set((char *)req
->outbuf
,
1024 eclass
, ecode
, status
,
1027 show_msg((char *)req
->outbuf
);
1028 if (!srv_send_smb(xconn
,
1029 (char *)req
->outbuf
,
1030 true, req
->seqnum
+1,
1031 IS_CONN_ENCRYPTED(conn
),
1033 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
1035 TALLOC_FREE(req
->outbuf
);
1039 /* When sending params and data ensure that both are nicely aligned */
1040 /* Only do this alignment when there is also data to send - else
1041 can cause NT redirector problems. */
1043 if (((params_to_send
% 4) != 0) && (data_to_send
!= 0))
1044 data_alignment_offset
= 4 - (params_to_send
% 4);
1046 /* Space is bufsize minus Netbios over TCP header minus SMB header */
1047 /* The alignment_offset is to align the param bytes on an even byte
1048 boundary. NT 4.0 Beta needs this to work correctly. */
1050 useable_space
= max_send
- (smb_size
1053 + data_alignment_offset
);
1055 if (useable_space
< 0) {
1056 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
1057 "= %d!!!", useable_space
));
1058 exit_server_cleanly("send_trans2_replies: Not enough space");
1061 while (params_to_send
|| data_to_send
) {
1062 /* Calculate whether we will totally or partially fill this packet */
1064 total_sent_thistime
= params_to_send
+ data_to_send
;
1066 /* We can never send more than useable_space */
1068 * Note that 'useable_space' does not include the alignment offsets,
1069 * but we must include the alignment offsets in the calculation of
1070 * the length of the data we send over the wire, as the alignment offsets
1071 * are sent here. Fix from Marc_Jacobsen@hp.com.
1074 total_sent_thistime
= MIN(total_sent_thistime
, useable_space
);
1076 reply_outbuf(req
, 10, total_sent_thistime
+ alignment_offset
1077 + data_alignment_offset
);
1079 /* Set total params and data to be sent */
1080 SSVAL(req
->outbuf
,smb_tprcnt
,paramsize
);
1081 SSVAL(req
->outbuf
,smb_tdrcnt
,datasize
);
1083 /* Calculate how many parameters and data we can fit into
1084 * this packet. Parameters get precedence
1087 params_sent_thistime
= MIN(params_to_send
,useable_space
);
1088 data_sent_thistime
= useable_space
- params_sent_thistime
;
1089 data_sent_thistime
= MIN(data_sent_thistime
,data_to_send
);
1091 SSVAL(req
->outbuf
,smb_prcnt
, params_sent_thistime
);
1093 /* smb_proff is the offset from the start of the SMB header to the
1094 parameter bytes, however the first 4 bytes of outbuf are
1095 the Netbios over TCP header. Thus use smb_base() to subtract
1096 them from the calculation */
1098 SSVAL(req
->outbuf
,smb_proff
,
1099 ((smb_buf(req
->outbuf
)+alignment_offset
)
1100 - smb_base(req
->outbuf
)));
1102 if(params_sent_thistime
== 0)
1103 SSVAL(req
->outbuf
,smb_prdisp
,0);
1105 /* Absolute displacement of param bytes sent in this packet */
1106 SSVAL(req
->outbuf
,smb_prdisp
,pp
- params
);
1108 SSVAL(req
->outbuf
,smb_drcnt
, data_sent_thistime
);
1109 if(data_sent_thistime
== 0) {
1110 SSVAL(req
->outbuf
,smb_droff
,0);
1111 SSVAL(req
->outbuf
,smb_drdisp
, 0);
1113 /* The offset of the data bytes is the offset of the
1114 parameter bytes plus the number of parameters being sent this time */
1115 SSVAL(req
->outbuf
, smb_droff
,
1116 ((smb_buf(req
->outbuf
)+alignment_offset
)
1117 - smb_base(req
->outbuf
))
1118 + params_sent_thistime
+ data_alignment_offset
);
1119 SSVAL(req
->outbuf
,smb_drdisp
, pd
- pdata
);
1122 /* Initialize the padding for alignment */
1124 if (alignment_offset
!= 0) {
1125 memset(smb_buf(req
->outbuf
), 0, alignment_offset
);
1128 /* Copy the param bytes into the packet */
1130 if(params_sent_thistime
) {
1131 memcpy((smb_buf(req
->outbuf
)+alignment_offset
), pp
,
1132 params_sent_thistime
);
1135 /* Copy in the data bytes */
1136 if(data_sent_thistime
) {
1137 if (data_alignment_offset
!= 0) {
1138 memset((smb_buf(req
->outbuf
)+alignment_offset
+
1139 params_sent_thistime
), 0,
1140 data_alignment_offset
);
1142 memcpy(smb_buf(req
->outbuf
)+alignment_offset
1143 +params_sent_thistime
+data_alignment_offset
,
1144 pd
,data_sent_thistime
);
1147 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
1148 params_sent_thistime
, data_sent_thistime
, useable_space
));
1149 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
1150 params_to_send
, data_to_send
, paramsize
, datasize
));
1153 error_packet_set((char *)req
->outbuf
,
1154 ERRDOS
,ERRbufferoverflow
,
1155 STATUS_BUFFER_OVERFLOW
,
1157 } else if (NT_STATUS_V(status
)) {
1160 ntstatus_to_dos(status
, &eclass
, &ecode
);
1161 error_packet_set((char *)req
->outbuf
,
1162 eclass
, ecode
, status
,
1166 /* Send the packet */
1167 show_msg((char *)req
->outbuf
);
1168 if (!srv_send_smb(xconn
,
1169 (char *)req
->outbuf
,
1170 true, req
->seqnum
+1,
1171 IS_CONN_ENCRYPTED(conn
),
1173 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
1175 TALLOC_FREE(req
->outbuf
);
1177 pp
+= params_sent_thistime
;
1178 pd
+= data_sent_thistime
;
1180 params_to_send
-= params_sent_thistime
;
1181 data_to_send
-= data_sent_thistime
;
1184 if(params_to_send
< 0 || data_to_send
< 0) {
1185 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
1186 params_to_send
, data_to_send
));
1194 /****************************************************************************
1195 Reply to a TRANSACT2_OPEN.
1196 ****************************************************************************/
1198 static void call_trans2open(connection_struct
*conn
,
1199 struct smb_request
*req
,
1200 char **pparams
, int total_params
,
1201 char **ppdata
, int total_data
,
1202 unsigned int max_data_bytes
)
1204 struct smb_filename
*smb_fname
= NULL
;
1205 char *params
= *pparams
;
1206 char *pdata
= *ppdata
;
1209 bool oplock_request
;
1211 bool return_additional_info
;
1220 int fattr
=0,mtime
=0;
1221 SMB_INO_T inode
= 0;
1224 struct ea_list
*ea_list
= NULL
;
1227 uint32_t access_mask
;
1228 uint32_t share_mode
;
1229 uint32_t create_disposition
;
1230 uint32_t create_options
= 0;
1231 uint32_t private_flags
= 0;
1232 uint32_t ucf_flags
= ucf_flags_from_smb_request(req
);
1233 TALLOC_CTX
*ctx
= talloc_tos();
1236 * Ensure we have enough parameters to perform the operation.
1239 if (total_params
< 29) {
1240 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1244 flags
= SVAL(params
, 0);
1245 deny_mode
= SVAL(params
, 2);
1246 open_attr
= SVAL(params
,6);
1247 oplock_request
= (flags
& REQUEST_OPLOCK
) ? EXCLUSIVE_OPLOCK
: 0;
1248 if (oplock_request
) {
1249 oplock_request
|= (flags
& REQUEST_BATCH_OPLOCK
) ? BATCH_OPLOCK
: 0;
1253 return_additional_info
= BITSETW(params
,0);
1254 open_sattr
= SVAL(params
, 4);
1255 open_time
= make_unix_date3(params
+8);
1257 open_ofun
= SVAL(params
,12);
1258 open_size
= IVAL(params
,14);
1259 pname
= ¶ms
[28];
1262 reply_nterror(req
, NT_STATUS_NETWORK_ACCESS_DENIED
);
1266 if (req
->posix_pathnames
) {
1267 srvstr_get_path_posix(ctx
,
1276 srvstr_get_path(ctx
,
1285 if (!NT_STATUS_IS_OK(status
)) {
1286 reply_nterror(req
, status
);
1290 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
1291 fname
, (unsigned int)deny_mode
, (unsigned int)open_attr
,
1292 (unsigned int)open_ofun
, open_size
));
1294 status
= filename_convert(ctx
,
1300 if (!NT_STATUS_IS_OK(status
)) {
1301 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
1302 reply_botherror(req
,
1303 NT_STATUS_PATH_NOT_COVERED
,
1304 ERRSRV
, ERRbadpath
);
1307 reply_nterror(req
, status
);
1311 if (open_ofun
== 0) {
1312 reply_nterror(req
, NT_STATUS_OBJECT_NAME_COLLISION
);
1316 if (!map_open_params_to_ntcreate(smb_fname
->base_name
, deny_mode
,
1318 &access_mask
, &share_mode
,
1319 &create_disposition
,
1322 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
1326 /* Any data in this call is an EA list. */
1327 if (total_data
&& (total_data
!= 4)) {
1328 if (total_data
< 10) {
1329 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1333 if (IVAL(pdata
,0) > total_data
) {
1334 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
1335 IVAL(pdata
,0), (unsigned int)total_data
));
1336 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1340 ea_list
= read_ea_list(talloc_tos(), pdata
+ 4,
1343 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1347 if (!lp_ea_support(SNUM(conn
))) {
1348 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
1352 if (!req
->posix_pathnames
&&
1353 ea_list_has_invalid_name(ea_list
)) {
1355 *pparams
= (char *)SMB_REALLOC(*pparams
, param_len
);
1356 if(*pparams
== NULL
) {
1357 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1361 memset(params
, '\0', param_len
);
1362 send_trans2_replies(conn
, req
, STATUS_INVALID_EA_NAME
,
1363 params
, param_len
, NULL
, 0, max_data_bytes
);
1368 status
= SMB_VFS_CREATE_FILE(
1371 0, /* root_dir_fid */
1372 smb_fname
, /* fname */
1373 access_mask
, /* access_mask */
1374 share_mode
, /* share_access */
1375 create_disposition
, /* create_disposition*/
1376 create_options
, /* create_options */
1377 open_attr
, /* file_attributes */
1378 oplock_request
, /* oplock_request */
1380 open_size
, /* allocation_size */
1383 ea_list
, /* ea_list */
1385 &smb_action
, /* psbuf */
1386 NULL
, NULL
); /* create context */
1388 if (!NT_STATUS_IS_OK(status
)) {
1389 if (open_was_deferred(req
->xconn
, req
->mid
)) {
1390 /* We have re-scheduled this call. */
1393 reply_openerror(req
, status
);
1397 size
= get_file_size_stat(&smb_fname
->st
);
1398 fattr
= dos_mode(conn
, smb_fname
);
1399 mtime
= convert_timespec_to_time_t(smb_fname
->st
.st_ex_mtime
);
1400 inode
= smb_fname
->st
.st_ex_ino
;
1401 if (fattr
& FILE_ATTRIBUTE_DIRECTORY
) {
1402 close_file(req
, fsp
, ERROR_CLOSE
);
1403 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
1407 /* Realloc the size of parameters and data we will return */
1408 *pparams
= (char *)SMB_REALLOC(*pparams
, 30);
1409 if(*pparams
== NULL
) {
1410 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1415 SSVAL(params
,0,fsp
->fnum
);
1416 SSVAL(params
,2,fattr
);
1417 srv_put_dos_date2(params
,4, mtime
);
1418 SIVAL(params
,8, (uint32_t)size
);
1419 SSVAL(params
,12,deny_mode
);
1420 SSVAL(params
,14,0); /* open_type - file or directory. */
1421 SSVAL(params
,16,0); /* open_state - only valid for IPC device. */
1423 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
1424 smb_action
|= EXTENDED_OPLOCK_GRANTED
;
1427 SSVAL(params
,18,smb_action
);
1430 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1432 SIVAL(params
,20,inode
);
1433 SSVAL(params
,24,0); /* Padding. */
1435 uint32_t ea_size
= estimate_ea_size(conn
, fsp
,
1437 SIVAL(params
, 26, ea_size
);
1439 SIVAL(params
, 26, 0);
1442 /* Send the required number of replies */
1443 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 30, *ppdata
, 0, max_data_bytes
);
1445 TALLOC_FREE(smb_fname
);
1448 /*********************************************************
1449 Routine to check if a given string matches exactly.
1450 as a special case a mask of "." does NOT match. That
1451 is required for correct wildcard semantics
1452 Case can be significant or not.
1453 **********************************************************/
1455 static bool exact_match(bool has_wild
,
1456 bool case_sensitive
,
1460 if (mask
[0] == '.' && mask
[1] == 0) {
1468 if (case_sensitive
) {
1469 return strcmp(str
,mask
)==0;
1471 return strcasecmp_m(str
,mask
) == 0;
1475 /****************************************************************************
1476 Return the filetype for UNIX extensions.
1477 ****************************************************************************/
1479 static uint32_t unix_filetype(mode_t mode
)
1482 return UNIX_TYPE_FILE
;
1483 else if(S_ISDIR(mode
))
1484 return UNIX_TYPE_DIR
;
1486 else if(S_ISLNK(mode
))
1487 return UNIX_TYPE_SYMLINK
;
1490 else if(S_ISCHR(mode
))
1491 return UNIX_TYPE_CHARDEV
;
1494 else if(S_ISBLK(mode
))
1495 return UNIX_TYPE_BLKDEV
;
1498 else if(S_ISFIFO(mode
))
1499 return UNIX_TYPE_FIFO
;
1502 else if(S_ISSOCK(mode
))
1503 return UNIX_TYPE_SOCKET
;
1506 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode
));
1507 return UNIX_TYPE_UNKNOWN
;
1510 /****************************************************************************
1511 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1512 ****************************************************************************/
1514 enum perm_type
{ PERM_NEW_FILE
, PERM_NEW_DIR
, PERM_EXISTING_FILE
, PERM_EXISTING_DIR
};
1516 static NTSTATUS
unix_perms_from_wire( connection_struct
*conn
,
1517 const SMB_STRUCT_STAT
*psbuf
,
1519 enum perm_type ptype
,
1524 if (perms
== SMB_MODE_NO_CHANGE
) {
1525 if (!VALID_STAT(*psbuf
)) {
1526 return NT_STATUS_INVALID_PARAMETER
;
1528 *ret_perms
= psbuf
->st_ex_mode
;
1529 return NT_STATUS_OK
;
1533 ret
|= ((perms
& UNIX_X_OTH
) ? S_IXOTH
: 0);
1534 ret
|= ((perms
& UNIX_W_OTH
) ? S_IWOTH
: 0);
1535 ret
|= ((perms
& UNIX_R_OTH
) ? S_IROTH
: 0);
1536 ret
|= ((perms
& UNIX_X_GRP
) ? S_IXGRP
: 0);
1537 ret
|= ((perms
& UNIX_W_GRP
) ? S_IWGRP
: 0);
1538 ret
|= ((perms
& UNIX_R_GRP
) ? S_IRGRP
: 0);
1539 ret
|= ((perms
& UNIX_X_USR
) ? S_IXUSR
: 0);
1540 ret
|= ((perms
& UNIX_W_USR
) ? S_IWUSR
: 0);
1541 ret
|= ((perms
& UNIX_R_USR
) ? S_IRUSR
: 0);
1543 ret
|= ((perms
& UNIX_STICKY
) ? S_ISVTX
: 0);
1546 ret
|= ((perms
& UNIX_SET_GID
) ? S_ISGID
: 0);
1549 ret
|= ((perms
& UNIX_SET_UID
) ? S_ISUID
: 0);
1552 if (ptype
== PERM_NEW_FILE
) {
1554 * "create mask"/"force create mode" are
1555 * only applied to new files, not existing ones.
1557 ret
&= lp_create_mask(SNUM(conn
));
1558 /* Add in force bits */
1559 ret
|= lp_force_create_mode(SNUM(conn
));
1560 } else if (ptype
== PERM_NEW_DIR
) {
1562 * "directory mask"/"force directory mode" are
1563 * only applied to new directories, not existing ones.
1565 ret
&= lp_directory_mask(SNUM(conn
));
1566 /* Add in force bits */
1567 ret
|= lp_force_directory_mode(SNUM(conn
));
1571 return NT_STATUS_OK
;
1574 /****************************************************************************
1575 Needed to show the msdfs symlinks as directories. Modifies psbuf
1576 to be a directory if it's a msdfs link.
1577 ****************************************************************************/
1579 static bool check_msdfs_link(connection_struct
*conn
,
1580 struct smb_filename
*smb_fname
)
1582 int saved_errno
= errno
;
1583 if(lp_host_msdfs() &&
1584 lp_msdfs_root(SNUM(conn
)) &&
1585 is_msdfs_link(conn
, smb_fname
)) {
1587 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1589 smb_fname
->base_name
));
1590 smb_fname
->st
.st_ex_mode
=
1591 (smb_fname
->st
.st_ex_mode
& 0xFFF) | S_IFDIR
;
1592 errno
= saved_errno
;
1595 errno
= saved_errno
;
1600 /****************************************************************************
1601 Get a level dependent lanman2 dir entry.
1602 ****************************************************************************/
1604 struct smbd_dirptr_lanman2_state
{
1605 connection_struct
*conn
;
1606 uint32_t info_level
;
1607 bool check_mangled_names
;
1609 bool got_exact_match
;
1612 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX
*ctx
,
1618 struct smbd_dirptr_lanman2_state
*state
=
1619 (struct smbd_dirptr_lanman2_state
*)private_data
;
1621 char mangled_name
[13]; /* mangled 8.3 name. */
1625 /* Mangle fname if it's an illegal name. */
1626 if (mangle_must_mangle(dname
, state
->conn
->params
)) {
1628 * Slow path - ensure we can push the original name as UCS2. If
1629 * not, then just don't return this name.
1633 size_t len
= (strlen(dname
) + 2) * 4; /* Allow enough space. */
1634 uint8_t *tmp
= talloc_array(talloc_tos(),
1638 status
= srvstr_push(NULL
,
1639 FLAGS2_UNICODE_STRINGS
,
1648 if (!NT_STATUS_IS_OK(status
)) {
1652 ok
= name_to_8_3(dname
, mangled_name
,
1653 true, state
->conn
->params
);
1657 fname
= mangled_name
;
1662 got_match
= exact_match(state
->has_wild
,
1663 state
->conn
->case_sensitive
,
1665 state
->got_exact_match
= got_match
;
1667 got_match
= mask_match(fname
, mask
,
1668 state
->conn
->case_sensitive
);
1671 if(!got_match
&& state
->check_mangled_names
&&
1672 !mangle_is_8_3(fname
, false, state
->conn
->params
)) {
1674 * It turns out that NT matches wildcards against
1675 * both long *and* short names. This may explain some
1676 * of the wildcard wierdness from old DOS clients
1677 * that some people have been seeing.... JRA.
1679 /* Force the mangling into 8.3. */
1680 ok
= name_to_8_3(fname
, mangled_name
,
1681 false, state
->conn
->params
);
1686 got_match
= exact_match(state
->has_wild
,
1687 state
->conn
->case_sensitive
,
1688 mangled_name
, mask
);
1689 state
->got_exact_match
= got_match
;
1691 got_match
= mask_match(mangled_name
, mask
,
1692 state
->conn
->case_sensitive
);
1700 *_fname
= talloc_strdup(ctx
, fname
);
1701 if (*_fname
== NULL
) {
1708 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX
*ctx
,
1710 struct smb_filename
*smb_fname
,
1713 struct smbd_dirptr_lanman2_state
*state
=
1714 (struct smbd_dirptr_lanman2_state
*)private_data
;
1715 bool ms_dfs_link
= false;
1718 if (INFO_LEVEL_IS_UNIX(state
->info_level
)) {
1719 if (SMB_VFS_LSTAT(state
->conn
, smb_fname
) != 0) {
1720 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1721 "Couldn't lstat [%s] (%s)\n",
1722 smb_fname_str_dbg(smb_fname
),
1726 } else if (!VALID_STAT(smb_fname
->st
) &&
1727 SMB_VFS_STAT(state
->conn
, smb_fname
) != 0) {
1728 /* Needed to show the msdfs symlinks as
1731 ms_dfs_link
= check_msdfs_link(state
->conn
,
1734 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1735 "Couldn't stat [%s] (%s)\n",
1736 smb_fname_str_dbg(smb_fname
),
1743 mode
= dos_mode_msdfs(state
->conn
, smb_fname
);
1745 mode
= dos_mode(state
->conn
, smb_fname
);
1752 static NTSTATUS
smbd_marshall_dir_entry(TALLOC_CTX
*ctx
,
1753 connection_struct
*conn
,
1755 uint32_t info_level
,
1756 struct ea_list
*name_list
,
1757 bool check_mangled_names
,
1758 bool requires_resume_key
,
1761 const struct smb_filename
*smb_fname
,
1762 int space_remaining
,
1768 uint64_t *last_entry_off
)
1770 char *p
, *q
, *pdata
= *ppdata
;
1772 uint64_t file_size
= 0;
1773 uint64_t allocation_size
= 0;
1774 uint64_t file_index
= 0;
1776 struct timespec mdate_ts
= {0};
1777 struct timespec adate_ts
= {0};
1778 struct timespec cdate_ts
= {0};
1779 struct timespec create_date_ts
= {0};
1780 time_t mdate
= (time_t)0, adate
= (time_t)0, create_date
= (time_t)0;
1782 char *last_entry_ptr
;
1787 struct readdir_attr_data
*readdir_attr_data
= NULL
;
1789 if (!(mode
& FILE_ATTRIBUTE_DIRECTORY
)) {
1790 file_size
= get_file_size_stat(&smb_fname
->st
);
1792 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
, NULL
, &smb_fname
->st
);
1794 status
= SMB_VFS_READDIR_ATTR(conn
, smb_fname
, ctx
, &readdir_attr_data
);
1795 if (!NT_STATUS_IS_OK(status
)) {
1796 if (!NT_STATUS_EQUAL(NT_STATUS_NOT_SUPPORTED
, status
)) {
1801 file_index
= get_FileIndex(conn
, &smb_fname
->st
);
1803 mdate_ts
= smb_fname
->st
.st_ex_mtime
;
1804 adate_ts
= smb_fname
->st
.st_ex_atime
;
1805 create_date_ts
= get_create_timespec(conn
, NULL
, smb_fname
);
1806 cdate_ts
= get_change_timespec(conn
, NULL
, smb_fname
);
1808 if (lp_dos_filetime_resolution(SNUM(conn
))) {
1809 dos_filetime_timespec(&create_date_ts
);
1810 dos_filetime_timespec(&mdate_ts
);
1811 dos_filetime_timespec(&adate_ts
);
1812 dos_filetime_timespec(&cdate_ts
);
1815 create_date
= convert_timespec_to_time_t(create_date_ts
);
1816 mdate
= convert_timespec_to_time_t(mdate_ts
);
1817 adate
= convert_timespec_to_time_t(adate_ts
);
1819 /* align the record */
1820 SMB_ASSERT(align
>= 1);
1822 off
= (int)PTR_DIFF(pdata
, base_data
);
1823 pad
= (off
+ (align
-1)) & ~(align
-1);
1826 if (pad
&& pad
> space_remaining
) {
1827 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1828 "for padding (wanted %u, had %d)\n",
1831 return STATUS_MORE_ENTRIES
; /* Not finished - just out of space */
1835 /* initialize padding to 0 */
1837 memset(pdata
, 0, pad
);
1839 space_remaining
-= pad
;
1841 DEBUG(10,("smbd_marshall_dir_entry: space_remaining = %d\n",
1851 switch (info_level
) {
1852 case SMB_FIND_INFO_STANDARD
:
1853 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1854 if(requires_resume_key
) {
1858 srv_put_dos_date2(p
,0,create_date
);
1859 srv_put_dos_date2(p
,4,adate
);
1860 srv_put_dos_date2(p
,8,mdate
);
1861 SIVAL(p
,12,(uint32_t)file_size
);
1862 SIVAL(p
,16,(uint32_t)allocation_size
);
1866 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1867 p
+= ucs2_align(base_data
, p
, 0);
1869 status
= srvstr_push(base_data
, flags2
, p
,
1870 fname
, PTR_DIFF(end_data
, p
),
1871 STR_TERMINATE
, &len
);
1872 if (!NT_STATUS_IS_OK(status
)) {
1875 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1877 SCVAL(nameptr
, -1, len
- 2);
1879 SCVAL(nameptr
, -1, 0);
1883 SCVAL(nameptr
, -1, len
- 1);
1885 SCVAL(nameptr
, -1, 0);
1891 case SMB_FIND_EA_SIZE
:
1892 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
1893 if (requires_resume_key
) {
1897 srv_put_dos_date2(p
,0,create_date
);
1898 srv_put_dos_date2(p
,4,adate
);
1899 srv_put_dos_date2(p
,8,mdate
);
1900 SIVAL(p
,12,(uint32_t)file_size
);
1901 SIVAL(p
,16,(uint32_t)allocation_size
);
1904 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
1906 SIVAL(p
,22,ea_size
); /* Extended attributes */
1910 status
= srvstr_push(base_data
, flags2
,
1911 p
, fname
, PTR_DIFF(end_data
, p
),
1912 STR_TERMINATE
| STR_NOALIGN
, &len
);
1913 if (!NT_STATUS_IS_OK(status
)) {
1916 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1929 SCVAL(nameptr
,0,len
);
1931 SCVAL(p
,0,0); p
+= 1; /* Extra zero byte ? - why.. */
1934 case SMB_FIND_EA_LIST
:
1936 struct ea_list
*file_list
= NULL
;
1939 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
1941 return NT_STATUS_INVALID_PARAMETER
;
1943 if (requires_resume_key
) {
1947 srv_put_dos_date2(p
,0,create_date
);
1948 srv_put_dos_date2(p
,4,adate
);
1949 srv_put_dos_date2(p
,8,mdate
);
1950 SIVAL(p
,12,(uint32_t)file_size
);
1951 SIVAL(p
,16,(uint32_t)allocation_size
);
1953 p
+= 22; /* p now points to the EA area. */
1955 status
= get_ea_list_from_file(ctx
, conn
, NULL
,
1957 &ea_len
, &file_list
);
1958 if (!NT_STATUS_IS_OK(status
)) {
1961 name_list
= ea_list_union(name_list
, file_list
, &ea_len
);
1963 /* We need to determine if this entry will fit in the space available. */
1964 /* Max string size is 255 bytes. */
1965 if (PTR_DIFF(p
+ 255 + ea_len
,pdata
) > space_remaining
) {
1966 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1967 "(wanted %u, had %d)\n",
1968 (unsigned int)PTR_DIFF(p
+ 255 + ea_len
,pdata
),
1970 return STATUS_MORE_ENTRIES
; /* Not finished - just out of space */
1973 /* Push the ea_data followed by the name. */
1974 p
+= fill_ea_buffer(ctx
, p
, space_remaining
, conn
, name_list
);
1976 status
= srvstr_push(base_data
, flags2
,
1977 p
+ 1, fname
, PTR_DIFF(end_data
, p
+1),
1978 STR_TERMINATE
| STR_NOALIGN
, &len
);
1979 if (!NT_STATUS_IS_OK(status
)) {
1982 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1995 SCVAL(nameptr
,0,len
);
1997 SCVAL(p
,0,0); p
+= 1; /* Extra zero byte ? - why.. */
2001 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
2002 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
2003 was_8_3
= mangle_is_8_3(fname
, True
, conn
->params
);
2005 SIVAL(p
,0,reskey
); p
+= 4;
2006 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
2007 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
2008 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
2009 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
2010 SOFF_T(p
,0,file_size
); p
+= 8;
2011 SOFF_T(p
,0,allocation_size
); p
+= 8;
2012 SIVAL(p
,0,mode
); p
+= 4;
2013 q
= p
; p
+= 4; /* q is placeholder for name length. */
2014 if (mode
& FILE_ATTRIBUTE_REPARSE_POINT
) {
2015 SIVAL(p
, 0, IO_REPARSE_TAG_DFS
);
2017 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
2019 SIVAL(p
,0,ea_size
); /* Extended attributes */
2022 /* Clear the short name buffer. This is
2023 * IMPORTANT as not doing so will trigger
2024 * a Win2k client bug. JRA.
2026 if (!was_8_3
&& check_mangled_names
) {
2027 char mangled_name
[13]; /* mangled 8.3 name. */
2028 if (!name_to_8_3(fname
,mangled_name
,True
,
2030 /* Error - mangle failed ! */
2031 memset(mangled_name
,'\0',12);
2033 mangled_name
[12] = 0;
2034 status
= srvstr_push(base_data
, flags2
,
2035 p
+2, mangled_name
, 24,
2036 STR_UPPER
|STR_UNICODE
, &len
);
2037 if (!NT_STATUS_IS_OK(status
)) {
2041 memset(p
+ 2 + len
,'\0',24 - len
);
2048 status
= srvstr_push(base_data
, flags2
, p
,
2049 fname
, PTR_DIFF(end_data
, p
),
2050 STR_TERMINATE_ASCII
, &len
);
2051 if (!NT_STATUS_IS_OK(status
)) {
2057 len
= PTR_DIFF(p
, pdata
);
2058 pad
= (len
+ (align
-1)) & ~(align
-1);
2060 * offset to the next entry, the caller
2061 * will overwrite it for the last entry
2062 * that's why we always include the padding
2066 * set padding to zero
2069 memset(p
, 0, pad
- len
);
2076 case SMB_FIND_FILE_DIRECTORY_INFO
:
2077 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
2079 SIVAL(p
,0,reskey
); p
+= 4;
2080 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
2081 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
2082 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
2083 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
2084 SOFF_T(p
,0,file_size
); p
+= 8;
2085 SOFF_T(p
,0,allocation_size
); p
+= 8;
2086 SIVAL(p
,0,mode
); p
+= 4;
2087 status
= srvstr_push(base_data
, flags2
,
2088 p
+ 4, fname
, PTR_DIFF(end_data
, p
+4),
2089 STR_TERMINATE_ASCII
, &len
);
2090 if (!NT_STATUS_IS_OK(status
)) {
2096 len
= PTR_DIFF(p
, pdata
);
2097 pad
= (len
+ (align
-1)) & ~(align
-1);
2099 * offset to the next entry, the caller
2100 * will overwrite it for the last entry
2101 * that's why we always include the padding
2105 * set padding to zero
2108 memset(p
, 0, pad
- len
);
2115 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
2116 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
2118 SIVAL(p
,0,reskey
); p
+= 4;
2119 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
2120 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
2121 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
2122 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
2123 SOFF_T(p
,0,file_size
); p
+= 8;
2124 SOFF_T(p
,0,allocation_size
); p
+= 8;
2125 SIVAL(p
,0,mode
); p
+= 4;
2126 q
= p
; p
+= 4; /* q is placeholder for name length. */
2128 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
2130 SIVAL(p
,0,ea_size
); /* Extended attributes */
2133 status
= srvstr_push(base_data
, flags2
, p
,
2134 fname
, PTR_DIFF(end_data
, p
),
2135 STR_TERMINATE_ASCII
, &len
);
2136 if (!NT_STATUS_IS_OK(status
)) {
2142 len
= PTR_DIFF(p
, pdata
);
2143 pad
= (len
+ (align
-1)) & ~(align
-1);
2145 * offset to the next entry, the caller
2146 * will overwrite it for the last entry
2147 * that's why we always include the padding
2151 * set padding to zero
2154 memset(p
, 0, pad
- len
);
2161 case SMB_FIND_FILE_NAMES_INFO
:
2162 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
2164 SIVAL(p
,0,reskey
); p
+= 4;
2166 /* this must *not* be null terminated or w2k gets in a loop trying to set an
2167 acl on a dir (tridge) */
2168 status
= srvstr_push(base_data
, flags2
, p
,
2169 fname
, PTR_DIFF(end_data
, p
),
2170 STR_TERMINATE_ASCII
, &len
);
2171 if (!NT_STATUS_IS_OK(status
)) {
2177 len
= PTR_DIFF(p
, pdata
);
2178 pad
= (len
+ (align
-1)) & ~(align
-1);
2180 * offset to the next entry, the caller
2181 * will overwrite it for the last entry
2182 * that's why we always include the padding
2186 * set padding to zero
2189 memset(p
, 0, pad
- len
);
2196 case SMB_FIND_ID_FULL_DIRECTORY_INFO
:
2197 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
2199 SIVAL(p
,0,reskey
); p
+= 4;
2200 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
2201 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
2202 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
2203 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
2204 SOFF_T(p
,0,file_size
); p
+= 8;
2205 SOFF_T(p
,0,allocation_size
); p
+= 8;
2206 SIVAL(p
,0,mode
); p
+= 4;
2207 q
= p
; p
+= 4; /* q is placeholder for name length. */
2208 if (mode
& FILE_ATTRIBUTE_REPARSE_POINT
) {
2209 SIVAL(p
, 0, IO_REPARSE_TAG_DFS
);
2211 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
2213 SIVAL(p
,0,ea_size
); /* Extended attributes */
2216 SIVAL(p
,0,0); p
+= 4; /* Unknown - reserved ? */
2217 SBVAL(p
,0,file_index
); p
+= 8;
2218 status
= srvstr_push(base_data
, flags2
, p
,
2219 fname
, PTR_DIFF(end_data
, p
),
2220 STR_TERMINATE_ASCII
, &len
);
2221 if (!NT_STATUS_IS_OK(status
)) {
2227 len
= PTR_DIFF(p
, pdata
);
2228 pad
= (len
+ (align
-1)) & ~(align
-1);
2230 * offset to the next entry, the caller
2231 * will overwrite it for the last entry
2232 * that's why we always include the padding
2236 * set padding to zero
2239 memset(p
, 0, pad
- len
);
2246 case SMB_FIND_ID_BOTH_DIRECTORY_INFO
:
2247 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
2248 was_8_3
= mangle_is_8_3(fname
, True
, conn
->params
);
2250 SIVAL(p
,0,reskey
); p
+= 4;
2251 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
2252 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
2253 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
2254 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
2255 SOFF_T(p
,0,file_size
); p
+= 8;
2256 SOFF_T(p
,0,allocation_size
); p
+= 8;
2257 SIVAL(p
,0,mode
); p
+= 4;
2258 q
= p
; p
+= 4; /* q is placeholder for name length */
2259 if (mode
& FILE_ATTRIBUTE_REPARSE_POINT
) {
2260 SIVAL(p
, 0, IO_REPARSE_TAG_DFS
);
2261 } else if (readdir_attr_data
&&
2262 readdir_attr_data
->type
== RDATTR_AAPL
) {
2264 * OS X specific SMB2 extension negotiated via
2265 * AAPL create context: return max_access in
2268 SIVAL(p
, 0, readdir_attr_data
->attr_data
.aapl
.max_access
);
2270 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
2272 SIVAL(p
,0,ea_size
); /* Extended attributes */
2276 if (readdir_attr_data
&&
2277 readdir_attr_data
->type
== RDATTR_AAPL
) {
2279 * OS X specific SMB2 extension negotiated via
2280 * AAPL create context: return resource fork
2281 * length and compressed FinderInfo in
2284 * According to documentation short_name_len
2285 * should be 0, but on the wire behaviour
2286 * shows its set to 24 by clients.
2290 /* Resourefork length */
2291 SBVAL(p
, 2, readdir_attr_data
->attr_data
.aapl
.rfork_size
);
2293 /* Compressed FinderInfo */
2294 memcpy(p
+ 10, &readdir_attr_data
->attr_data
.aapl
.finder_info
, 16);
2295 } else if (!was_8_3
&& check_mangled_names
) {
2296 char mangled_name
[13]; /* mangled 8.3 name. */
2297 if (!name_to_8_3(fname
,mangled_name
,True
,
2299 /* Error - mangle failed ! */
2300 memset(mangled_name
,'\0',12);
2302 mangled_name
[12] = 0;
2303 status
= srvstr_push(base_data
, flags2
,
2304 p
+2, mangled_name
, 24,
2305 STR_UPPER
|STR_UNICODE
, &len
);
2306 if (!NT_STATUS_IS_OK(status
)) {
2311 memset(p
+ 2 + len
,'\0',24 - len
);
2315 /* Clear the short name buffer. This is
2316 * IMPORTANT as not doing so will trigger
2317 * a Win2k client bug. JRA.
2324 if (readdir_attr_data
&&
2325 readdir_attr_data
->type
== RDATTR_AAPL
) {
2327 * OS X specific SMB2 extension negotiated via
2328 * AAPL create context: return UNIX mode in
2331 uint16_t aapl_mode
= (uint16_t)readdir_attr_data
->attr_data
.aapl
.unix_mode
;
2332 SSVAL(p
, 0, aapl_mode
);
2338 SBVAL(p
,0,file_index
); p
+= 8;
2339 status
= srvstr_push(base_data
, flags2
, p
,
2340 fname
, PTR_DIFF(end_data
, p
),
2341 STR_TERMINATE_ASCII
, &len
);
2342 if (!NT_STATUS_IS_OK(status
)) {
2348 len
= PTR_DIFF(p
, pdata
);
2349 pad
= (len
+ (align
-1)) & ~(align
-1);
2351 * offset to the next entry, the caller
2352 * will overwrite it for the last entry
2353 * that's why we always include the padding
2357 * set padding to zero
2360 memset(p
, 0, pad
- len
);
2367 /* CIFS UNIX Extension. */
2369 case SMB_FIND_FILE_UNIX
:
2370 case SMB_FIND_FILE_UNIX_INFO2
:
2372 SIVAL(p
,0,reskey
); p
+= 4; /* Used for continuing search. */
2374 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
2376 if (info_level
== SMB_FIND_FILE_UNIX
) {
2377 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
2378 p
= store_file_unix_basic(conn
, p
,
2379 NULL
, &smb_fname
->st
);
2380 status
= srvstr_push(base_data
, flags2
, p
,
2381 fname
, PTR_DIFF(end_data
, p
),
2382 STR_TERMINATE
, &len
);
2383 if (!NT_STATUS_IS_OK(status
)) {
2387 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
2388 p
= store_file_unix_basic_info2(conn
, p
,
2389 NULL
, &smb_fname
->st
);
2392 status
= srvstr_push(base_data
, flags2
, p
, fname
,
2393 PTR_DIFF(end_data
, p
), 0, &len
);
2394 if (!NT_STATUS_IS_OK(status
)) {
2397 SIVAL(nameptr
, 0, len
);
2402 len
= PTR_DIFF(p
, pdata
);
2403 pad
= (len
+ (align
-1)) & ~(align
-1);
2405 * offset to the next entry, the caller
2406 * will overwrite it for the last entry
2407 * that's why we always include the padding
2411 * set padding to zero
2414 memset(p
, 0, pad
- len
);
2419 /* End of SMB_QUERY_FILE_UNIX_BASIC */
2424 return NT_STATUS_INVALID_LEVEL
;
2427 if (PTR_DIFF(p
,pdata
) > space_remaining
) {
2428 DEBUG(9,("smbd_marshall_dir_entry: out of space "
2429 "(wanted %u, had %d)\n",
2430 (unsigned int)PTR_DIFF(p
,pdata
),
2432 return STATUS_MORE_ENTRIES
; /* Not finished - just out of space */
2435 /* Setup the last entry pointer, as an offset from base_data */
2436 *last_entry_off
= PTR_DIFF(last_entry_ptr
,base_data
);
2437 /* Advance the data pointer to the next slot */
2440 return NT_STATUS_OK
;
2443 NTSTATUS
smbd_dirptr_lanman2_entry(TALLOC_CTX
*ctx
,
2444 connection_struct
*conn
,
2445 struct dptr_struct
*dirptr
,
2447 const char *path_mask
,
2450 int requires_resume_key
,
2458 int space_remaining
,
2459 bool *got_exact_match
,
2460 int *_last_entry_off
,
2461 struct ea_list
*name_list
,
2462 struct file_id
*file_id
)
2465 const char *mask
= NULL
;
2466 long prev_dirpos
= 0;
2469 struct smb_filename
*smb_fname
= NULL
;
2470 struct smbd_dirptr_lanman2_state state
;
2472 uint64_t last_entry_off
= 0;
2474 enum mangled_names_options mangled_names
;
2475 bool marshall_with_83_names
;
2477 mangled_names
= lp_mangled_names(conn
->params
);
2481 state
.info_level
= info_level
;
2482 if (mangled_names
!= MANGLED_NAMES_NO
) {
2483 state
.check_mangled_names
= true;
2485 state
.has_wild
= dptr_has_wild(dirptr
);
2486 state
.got_exact_match
= false;
2488 *got_exact_match
= false;
2490 p
= strrchr_m(path_mask
,'/');
2501 ok
= smbd_dirptr_get_entry(ctx
,
2507 smbd_dirptr_lanman2_match_fn
,
2508 smbd_dirptr_lanman2_mode_fn
,
2515 return NT_STATUS_END_OF_FILE
;
2518 *got_exact_match
= state
.got_exact_match
;
2520 marshall_with_83_names
= (mangled_names
== MANGLED_NAMES_YES
);
2522 status
= smbd_marshall_dir_entry(ctx
,
2527 marshall_with_83_names
,
2528 requires_resume_key
,
2539 if (NT_STATUS_EQUAL(status
, NT_STATUS_ILLEGAL_CHARACTER
)) {
2540 DEBUG(1,("Conversion error: illegal character: %s\n",
2541 smb_fname_str_dbg(smb_fname
)));
2544 if (file_id
!= NULL
) {
2545 *file_id
= vfs_file_id_from_sbuf(conn
, &smb_fname
->st
);
2549 TALLOC_FREE(smb_fname
);
2550 if (NT_STATUS_EQUAL(status
, STATUS_MORE_ENTRIES
)) {
2551 dptr_SeekDir(dirptr
, prev_dirpos
);
2554 if (!NT_STATUS_IS_OK(status
)) {
2558 *_last_entry_off
= last_entry_off
;
2559 return NT_STATUS_OK
;
2562 static NTSTATUS
get_lanman2_dir_entry(TALLOC_CTX
*ctx
,
2563 connection_struct
*conn
,
2564 struct dptr_struct
*dirptr
,
2566 const char *path_mask
,
2569 bool requires_resume_key
,
2575 int space_remaining
,
2576 bool *got_exact_match
,
2577 int *last_entry_off
,
2578 struct ea_list
*name_list
)
2581 const bool do_pad
= true;
2583 if (info_level
>= 1 && info_level
<= 3) {
2584 /* No alignment on earlier info levels. */
2588 return smbd_dirptr_lanman2_entry(ctx
, conn
, dirptr
, flags2
,
2589 path_mask
, dirtype
, info_level
,
2590 requires_resume_key
, dont_descend
, ask_sharemode
,
2592 ppdata
, base_data
, end_data
,
2595 last_entry_off
, name_list
, NULL
);
2598 /****************************************************************************
2599 Reply to a TRANS2_FINDFIRST.
2600 ****************************************************************************/
2602 static void call_trans2findfirst(connection_struct
*conn
,
2603 struct smb_request
*req
,
2604 char **pparams
, int total_params
,
2605 char **ppdata
, int total_data
,
2606 unsigned int max_data_bytes
)
2608 /* We must be careful here that we don't return more than the
2609 allowed number of data bytes. If this means returning fewer than
2610 maxentries then so be it. We assume that the redirector has
2611 enough room for the fixed number of parameter bytes it has
2613 struct smb_filename
*smb_dname
= NULL
;
2614 char *params
= *pparams
;
2615 char *pdata
= *ppdata
;
2619 uint16_t findfirst_flags
;
2620 bool close_after_first
;
2622 bool requires_resume_key
;
2624 char *directory
= NULL
;
2627 int last_entry_off
=0;
2631 bool finished
= False
;
2632 bool dont_descend
= False
;
2633 bool out_of_space
= False
;
2634 int space_remaining
;
2635 bool mask_contains_wcard
= False
;
2636 struct ea_list
*ea_list
= NULL
;
2637 NTSTATUS ntstatus
= NT_STATUS_OK
;
2638 bool ask_sharemode
= lp_parm_bool(SNUM(conn
), "smbd", "search ask sharemode", true);
2639 struct dptr_struct
*dirptr
= NULL
;
2640 struct smbd_server_connection
*sconn
= req
->sconn
;
2641 uint32_t ucf_flags
= UCF_SAVE_LCOMP
| UCF_ALWAYS_ALLOW_WCARD_LCOMP
|
2642 ucf_flags_from_smb_request(req
);
2643 bool backup_priv
= false;
2644 bool as_root
= false;
2646 if (total_params
< 13) {
2647 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2651 dirtype
= SVAL(params
,0);
2652 maxentries
= SVAL(params
,2);
2653 findfirst_flags
= SVAL(params
,4);
2654 close_after_first
= (findfirst_flags
& FLAG_TRANS2_FIND_CLOSE
);
2655 close_if_end
= (findfirst_flags
& FLAG_TRANS2_FIND_CLOSE_IF_END
);
2656 requires_resume_key
= (findfirst_flags
& FLAG_TRANS2_FIND_REQUIRE_RESUME
);
2657 backup_priv
= ((findfirst_flags
& FLAG_TRANS2_FIND_BACKUP_INTENT
) &&
2658 security_token_has_privilege(get_current_nttok(conn
),
2661 info_level
= SVAL(params
,6);
2663 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2664 close_if_end = %d requires_resume_key = %d backup_priv = %d level = 0x%x, max_data_bytes = %d\n",
2665 (unsigned int)dirtype
, maxentries
, close_after_first
, close_if_end
, requires_resume_key
,
2667 info_level
, max_data_bytes
));
2670 /* W2K3 seems to treat zero as 1. */
2674 switch (info_level
) {
2675 case SMB_FIND_INFO_STANDARD
:
2676 case SMB_FIND_EA_SIZE
:
2677 case SMB_FIND_EA_LIST
:
2678 case SMB_FIND_FILE_DIRECTORY_INFO
:
2679 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
2680 case SMB_FIND_FILE_NAMES_INFO
:
2681 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
2682 case SMB_FIND_ID_FULL_DIRECTORY_INFO
:
2683 case SMB_FIND_ID_BOTH_DIRECTORY_INFO
:
2685 case SMB_FIND_FILE_UNIX
:
2686 case SMB_FIND_FILE_UNIX_INFO2
:
2687 /* Always use filesystem for UNIX mtime query. */
2688 ask_sharemode
= false;
2689 if (!lp_unix_extensions()) {
2690 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2693 ucf_flags
|= UCF_UNIX_NAME_LOOKUP
;
2696 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2700 if (req
->posix_pathnames
) {
2701 srvstr_get_path_wcard_posix(talloc_tos(),
2709 &mask_contains_wcard
);
2711 srvstr_get_path_wcard(talloc_tos(),
2719 &mask_contains_wcard
);
2721 if (!NT_STATUS_IS_OK(ntstatus
)) {
2722 reply_nterror(req
, ntstatus
);
2729 ntstatus
= filename_convert_with_privilege(talloc_tos(),
2734 &mask_contains_wcard
,
2737 ntstatus
= filename_convert(talloc_tos(), conn
,
2740 &mask_contains_wcard
,
2744 if (!NT_STATUS_IS_OK(ntstatus
)) {
2745 if (NT_STATUS_EQUAL(ntstatus
,NT_STATUS_PATH_NOT_COVERED
)) {
2746 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
2747 ERRSRV
, ERRbadpath
);
2750 reply_nterror(req
, ntstatus
);
2754 mask
= smb_dname
->original_lcomp
;
2756 directory
= smb_dname
->base_name
;
2758 p
= strrchr_m(directory
,'/');
2760 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2761 if((directory
[0] == '.') && (directory
[1] == '\0')) {
2762 mask
= talloc_strdup(talloc_tos(),"*");
2764 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2767 mask_contains_wcard
= True
;
2773 if (p
== NULL
|| p
== directory
) {
2774 /* Ensure we don't have a directory name of "". */
2775 directory
= talloc_strdup(talloc_tos(), ".");
2777 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2780 /* Ensure smb_dname->base_name matches. */
2781 smb_dname
->base_name
= directory
;
2784 DEBUG(5,("dir=%s, mask = %s\n",directory
, mask
));
2786 if (info_level
== SMB_FIND_EA_LIST
) {
2789 if (total_data
< 4) {
2790 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2794 ea_size
= IVAL(pdata
,0);
2795 if (ea_size
!= total_data
) {
2796 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2797 total_data=%u (should be %u)\n", (unsigned int)total_data
, (unsigned int)IVAL(pdata
,0) ));
2798 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2802 if (!lp_ea_support(SNUM(conn
))) {
2803 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
2807 /* Pull out the list of names. */
2808 ea_list
= read_ea_name_list(talloc_tos(), pdata
+ 4, ea_size
- 4);
2810 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2815 if (max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
< max_data_bytes
) {
2816 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2820 *ppdata
= (char *)SMB_REALLOC(
2821 *ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
2822 if(*ppdata
== NULL
) {
2823 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2827 data_end
= pdata
+ max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
- 1;
2829 * squash valgrind "writev(vector[...]) points to uninitialised byte(s)"
2832 memset(pdata
+ total_data
, 0, ((max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
) - total_data
));
2833 /* Realloc the params space */
2834 *pparams
= (char *)SMB_REALLOC(*pparams
, 10);
2835 if (*pparams
== NULL
) {
2836 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2841 /* Save the wildcard match and attribs we are using on this directory -
2842 needed as lanman2 assumes these are being saved between calls */
2844 ntstatus
= dptr_create(conn
,
2852 mask_contains_wcard
,
2856 if (!NT_STATUS_IS_OK(ntstatus
)) {
2857 reply_nterror(req
, ntstatus
);
2862 /* Remember this in case we have
2863 to do a findnext. */
2864 dptr_set_priv(dirptr
);
2867 dptr_num
= dptr_dnum(dirptr
);
2868 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num
, mask
, dirtype
));
2870 /* We don't need to check for VOL here as this is returned by
2871 a different TRANS2 call. */
2873 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2874 directory
,lp_dont_descend(talloc_tos(), SNUM(conn
))));
2875 if (in_list(directory
,
2876 lp_dont_descend(talloc_tos(), SNUM(conn
)),
2877 conn
->case_sensitive
)) {
2878 dont_descend
= True
;
2882 space_remaining
= max_data_bytes
;
2883 out_of_space
= False
;
2885 for (i
=0;(i
<maxentries
) && !finished
&& !out_of_space
;i
++) {
2886 bool got_exact_match
= False
;
2888 /* this is a heuristic to avoid seeking the dirptr except when
2889 absolutely necessary. It allows for a filename of about 40 chars */
2890 if (space_remaining
< DIRLEN_GUESS
&& numentries
> 0) {
2891 out_of_space
= True
;
2894 ntstatus
= get_lanman2_dir_entry(talloc_tos(),
2898 mask
,dirtype
,info_level
,
2899 requires_resume_key
,dont_descend
,
2904 &last_entry_off
, ea_list
);
2905 if (NT_STATUS_EQUAL(ntstatus
,
2906 NT_STATUS_ILLEGAL_CHARACTER
)) {
2908 * Bad character conversion on name. Ignore this
2913 if (NT_STATUS_EQUAL(ntstatus
, STATUS_MORE_ENTRIES
)) {
2914 out_of_space
= true;
2916 finished
= !NT_STATUS_IS_OK(ntstatus
);
2920 if (!finished
&& !out_of_space
)
2924 * As an optimisation if we know we aren't looking
2925 * for a wildcard name (ie. the name matches the wildcard exactly)
2926 * then we can finish on any (first) match.
2927 * This speeds up large directory searches. JRA.
2933 /* Ensure space_remaining never goes -ve. */
2934 if (PTR_DIFF(p
,pdata
) > max_data_bytes
) {
2935 space_remaining
= 0;
2936 out_of_space
= true;
2938 space_remaining
= max_data_bytes
- PTR_DIFF(p
,pdata
);
2942 /* Check if we can close the dirptr */
2943 if(close_after_first
|| (finished
&& close_if_end
)) {
2944 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num
));
2945 dptr_close(sconn
, &dptr_num
);
2949 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2950 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2951 * the protocol level is less than NT1. Tested with smbclient. JRA.
2952 * This should fix the OS/2 client bug #2335.
2955 if(numentries
== 0) {
2956 dptr_close(sconn
, &dptr_num
);
2957 if (get_Protocol() < PROTOCOL_NT1
) {
2958 reply_force_doserror(req
, ERRDOS
, ERRnofiles
);
2961 reply_botherror(req
, NT_STATUS_NO_SUCH_FILE
,
2962 ERRDOS
, ERRbadfile
);
2967 /* At this point pdata points to numentries directory entries. */
2969 /* Set up the return parameter block */
2970 SSVAL(params
,0,dptr_num
);
2971 SSVAL(params
,2,numentries
);
2972 SSVAL(params
,4,finished
);
2973 SSVAL(params
,6,0); /* Never an EA error */
2974 SSVAL(params
,8,last_entry_off
);
2976 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 10, pdata
, PTR_DIFF(p
,pdata
),
2979 if ((! *directory
) && dptr_path(sconn
, dptr_num
)) {
2980 directory
= talloc_strdup(talloc_tos(),dptr_path(sconn
, dptr_num
));
2982 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2986 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2987 smb_fn_name(req
->cmd
),
2988 mask
, directory
, dirtype
, numentries
) );
2991 * Force a name mangle here to ensure that the
2992 * mask as an 8.3 name is top of the mangled cache.
2993 * The reasons for this are subtle. Don't remove
2994 * this code unless you know what you are doing
2995 * (see PR#13758). JRA.
2998 if(!mangle_is_8_3_wildcards( mask
, False
, conn
->params
)) {
2999 char mangled_name
[13];
3000 name_to_8_3(mask
, mangled_name
, True
, conn
->params
);
3008 TALLOC_FREE(smb_dname
);
3012 /****************************************************************************
3013 Reply to a TRANS2_FINDNEXT.
3014 ****************************************************************************/
3016 static void call_trans2findnext(connection_struct
*conn
,
3017 struct smb_request
*req
,
3018 char **pparams
, int total_params
,
3019 char **ppdata
, int total_data
,
3020 unsigned int max_data_bytes
)
3022 /* We must be careful here that we don't return more than the
3023 allowed number of data bytes. If this means returning fewer than
3024 maxentries then so be it. We assume that the redirector has
3025 enough room for the fixed number of parameter bytes it has
3027 char *params
= *pparams
;
3028 char *pdata
= *ppdata
;
3032 uint16_t info_level
;
3033 uint32_t resume_key
;
3034 uint16_t findnext_flags
;
3035 bool close_after_request
;
3037 bool requires_resume_key
;
3039 bool mask_contains_wcard
= False
;
3040 char *resume_name
= NULL
;
3041 const char *mask
= NULL
;
3042 const char *directory
= NULL
;
3046 int i
, last_entry_off
=0;
3047 bool finished
= False
;
3048 bool dont_descend
= False
;
3049 bool out_of_space
= False
;
3050 int space_remaining
;
3051 struct ea_list
*ea_list
= NULL
;
3052 NTSTATUS ntstatus
= NT_STATUS_OK
;
3053 bool ask_sharemode
= lp_parm_bool(SNUM(conn
), "smbd", "search ask sharemode", true);
3054 TALLOC_CTX
*ctx
= talloc_tos();
3055 struct dptr_struct
*dirptr
;
3056 struct smbd_server_connection
*sconn
= req
->sconn
;
3057 bool backup_priv
= false;
3058 bool as_root
= false;
3060 if (total_params
< 13) {
3061 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3065 dptr_num
= SVAL(params
,0);
3066 maxentries
= SVAL(params
,2);
3067 info_level
= SVAL(params
,4);
3068 resume_key
= IVAL(params
,6);
3069 findnext_flags
= SVAL(params
,10);
3070 close_after_request
= (findnext_flags
& FLAG_TRANS2_FIND_CLOSE
);
3071 close_if_end
= (findnext_flags
& FLAG_TRANS2_FIND_CLOSE_IF_END
);
3072 requires_resume_key
= (findnext_flags
& FLAG_TRANS2_FIND_REQUIRE_RESUME
);
3073 continue_bit
= (findnext_flags
& FLAG_TRANS2_FIND_CONTINUE
);
3075 if (!continue_bit
) {
3076 /* We only need resume_name if continue_bit is zero. */
3077 if (req
->posix_pathnames
) {
3078 srvstr_get_path_wcard_posix(ctx
,
3086 &mask_contains_wcard
);
3088 srvstr_get_path_wcard(ctx
,
3096 &mask_contains_wcard
);
3098 if (!NT_STATUS_IS_OK(ntstatus
)) {
3099 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
3100 complain (it thinks we're asking for the directory above the shared
3101 path or an invalid name). Catch this as the resume name is only compared, never used in
3102 a file access. JRA. */
3103 srvstr_pull_talloc(ctx
, params
, req
->flags2
,
3104 &resume_name
, params
+12,
3108 if (!resume_name
|| !(ISDOT(resume_name
) || ISDOTDOT(resume_name
))) {
3109 reply_nterror(req
, ntstatus
);
3115 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
3116 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
3117 resume_key = %d resume name = %s continue=%d level = %d\n",
3118 dptr_num
, max_data_bytes
, maxentries
, close_after_request
, close_if_end
,
3119 requires_resume_key
, resume_key
,
3120 resume_name
? resume_name
: "(NULL)", continue_bit
, info_level
));
3123 /* W2K3 seems to treat zero as 1. */
3127 switch (info_level
) {
3128 case SMB_FIND_INFO_STANDARD
:
3129 case SMB_FIND_EA_SIZE
:
3130 case SMB_FIND_EA_LIST
:
3131 case SMB_FIND_FILE_DIRECTORY_INFO
:
3132 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
3133 case SMB_FIND_FILE_NAMES_INFO
:
3134 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
3135 case SMB_FIND_ID_FULL_DIRECTORY_INFO
:
3136 case SMB_FIND_ID_BOTH_DIRECTORY_INFO
:
3138 case SMB_FIND_FILE_UNIX
:
3139 case SMB_FIND_FILE_UNIX_INFO2
:
3140 /* Always use filesystem for UNIX mtime query. */
3141 ask_sharemode
= false;
3142 if (!lp_unix_extensions()) {
3143 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
3148 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
3152 if (info_level
== SMB_FIND_EA_LIST
) {
3155 if (total_data
< 4) {
3156 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3160 ea_size
= IVAL(pdata
,0);
3161 if (ea_size
!= total_data
) {
3162 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
3163 total_data=%u (should be %u)\n", (unsigned int)total_data
, (unsigned int)IVAL(pdata
,0) ));
3164 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3168 if (!lp_ea_support(SNUM(conn
))) {
3169 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
3173 /* Pull out the list of names. */
3174 ea_list
= read_ea_name_list(ctx
, pdata
+ 4, ea_size
- 4);
3176 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3181 if (max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
< max_data_bytes
) {
3182 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3186 *ppdata
= (char *)SMB_REALLOC(
3187 *ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
3188 if(*ppdata
== NULL
) {
3189 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
3194 data_end
= pdata
+ max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
- 1;
3197 * squash valgrind "writev(vector[...]) points to uninitialised byte(s)"
3200 memset(pdata
+ total_data
, 0, (max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
) - total_data
);
3201 /* Realloc the params space */
3202 *pparams
= (char *)SMB_REALLOC(*pparams
, 6*SIZEOFWORD
);
3203 if(*pparams
== NULL
) {
3204 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
3210 /* Check that the dptr is valid */
3211 if(!(dirptr
= dptr_fetch_lanman2(sconn
, dptr_num
))) {
3212 reply_nterror(req
, STATUS_NO_MORE_FILES
);
3216 directory
= dptr_path(sconn
, dptr_num
);
3218 /* Get the wildcard mask from the dptr */
3219 if((mask
= dptr_wcard(sconn
, dptr_num
))== NULL
) {
3220 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num
));
3221 reply_nterror(req
, STATUS_NO_MORE_FILES
);
3225 /* Get the attr mask from the dptr */
3226 dirtype
= dptr_attr(sconn
, dptr_num
);
3228 backup_priv
= dptr_get_priv(dirptr
);
3230 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld) "
3231 "backup_priv = %d\n",
3232 dptr_num
, mask
, dirtype
,
3234 dptr_TellDir(dirptr
),
3237 /* We don't need to check for VOL here as this is returned by
3238 a different TRANS2 call. */
3240 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
3241 directory
,lp_dont_descend(ctx
, SNUM(conn
))));
3242 if (in_list(directory
,lp_dont_descend(ctx
, SNUM(conn
)),conn
->case_sensitive
))
3243 dont_descend
= True
;
3246 space_remaining
= max_data_bytes
;
3247 out_of_space
= False
;
3255 * Seek to the correct position. We no longer use the resume key but
3256 * depend on the last file name instead.
3259 if(!continue_bit
&& resume_name
&& *resume_name
) {
3262 long current_pos
= 0;
3264 * Remember, name_to_8_3 is called by
3265 * get_lanman2_dir_entry(), so the resume name
3266 * could be mangled. Ensure we check the unmangled name.
3269 if (mangle_is_mangled(resume_name
, conn
->params
)) {
3270 char *new_resume_name
= NULL
;
3271 mangle_lookup_name_from_8_3(ctx
,
3275 if (new_resume_name
) {
3276 resume_name
= new_resume_name
;
3281 * Fix for NT redirector problem triggered by resume key indexes
3282 * changing between directory scans. We now return a resume key of 0
3283 * and instead look for the filename to continue from (also given
3284 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
3285 * findfirst/findnext (as is usual) then the directory pointer
3286 * should already be at the correct place.
3289 finished
= !dptr_SearchDir(dirptr
, resume_name
, ¤t_pos
, &st
);
3290 } /* end if resume_name && !continue_bit */
3292 for (i
=0;(i
<(int)maxentries
) && !finished
&& !out_of_space
;i
++) {
3293 bool got_exact_match
= False
;
3295 /* this is a heuristic to avoid seeking the dirptr except when
3296 absolutely necessary. It allows for a filename of about 40 chars */
3297 if (space_remaining
< DIRLEN_GUESS
&& numentries
> 0) {
3298 out_of_space
= True
;
3301 ntstatus
= get_lanman2_dir_entry(ctx
,
3305 mask
,dirtype
,info_level
,
3306 requires_resume_key
,dont_descend
,
3311 &last_entry_off
, ea_list
);
3312 if (NT_STATUS_EQUAL(ntstatus
,
3313 NT_STATUS_ILLEGAL_CHARACTER
)) {
3315 * Bad character conversion on name. Ignore this
3320 if (NT_STATUS_EQUAL(ntstatus
, STATUS_MORE_ENTRIES
)) {
3321 out_of_space
= true;
3323 finished
= !NT_STATUS_IS_OK(ntstatus
);
3327 if (!finished
&& !out_of_space
)
3331 * As an optimisation if we know we aren't looking
3332 * for a wildcard name (ie. the name matches the wildcard exactly)
3333 * then we can finish on any (first) match.
3334 * This speeds up large directory searches. JRA.
3340 space_remaining
= max_data_bytes
- PTR_DIFF(p
,pdata
);
3343 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
3344 smb_fn_name(req
->cmd
),
3345 mask
, directory
, dirtype
, numentries
) );
3347 /* Check if we can close the dirptr */
3348 if(close_after_request
|| (finished
&& close_if_end
)) {
3349 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num
));
3350 dptr_close(sconn
, &dptr_num
); /* This frees up the saved mask */
3357 /* Set up the return parameter block */
3358 SSVAL(params
,0,numentries
);
3359 SSVAL(params
,2,finished
);
3360 SSVAL(params
,4,0); /* Never an EA error */
3361 SSVAL(params
,6,last_entry_off
);
3363 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 8, pdata
, PTR_DIFF(p
,pdata
),
3369 unsigned char *create_volume_objectid(connection_struct
*conn
, unsigned char objid
[16])
3371 E_md4hash(lp_servicename(talloc_tos(), SNUM(conn
)),objid
);
3375 static void samba_extended_info_version(struct smb_extended_info
*extended_info
)
3377 SMB_ASSERT(extended_info
!= NULL
);
3379 extended_info
->samba_magic
= SAMBA_EXTENDED_INFO_MAGIC
;
3380 extended_info
->samba_version
= ((SAMBA_VERSION_MAJOR
& 0xff) << 24)
3381 | ((SAMBA_VERSION_MINOR
& 0xff) << 16)
3382 | ((SAMBA_VERSION_RELEASE
& 0xff) << 8);
3383 #ifdef SAMBA_VERSION_REVISION
3384 extended_info
->samba_version
|= (tolower(*SAMBA_VERSION_REVISION
) - 'a' + 1) & 0xff;
3386 extended_info
->samba_subversion
= 0;
3387 #ifdef SAMBA_VERSION_RC_RELEASE
3388 extended_info
->samba_subversion
|= (SAMBA_VERSION_RC_RELEASE
& 0xff) << 24;
3390 #ifdef SAMBA_VERSION_PRE_RELEASE
3391 extended_info
->samba_subversion
|= (SAMBA_VERSION_PRE_RELEASE
& 0xff) << 16;
3394 #ifdef SAMBA_VERSION_VENDOR_PATCH
3395 extended_info
->samba_subversion
|= (SAMBA_VERSION_VENDOR_PATCH
& 0xffff);
3397 extended_info
->samba_gitcommitdate
= 0;
3398 #ifdef SAMBA_VERSION_COMMIT_TIME
3399 unix_to_nt_time(&extended_info
->samba_gitcommitdate
, SAMBA_VERSION_COMMIT_TIME
);
3402 memset(extended_info
->samba_version_string
, 0,
3403 sizeof(extended_info
->samba_version_string
));
3405 snprintf (extended_info
->samba_version_string
,
3406 sizeof(extended_info
->samba_version_string
),
3407 "%s", samba_version_string());
3410 NTSTATUS
smbd_do_qfsinfo(struct smbXsrv_connection
*xconn
,
3411 connection_struct
*conn
,
3412 TALLOC_CTX
*mem_ctx
,
3413 uint16_t info_level
,
3415 unsigned int max_data_bytes
,
3416 size_t *fixed_portion
,
3417 struct smb_filename
*fname
,
3421 char *pdata
, *end_data
;
3424 const char *vname
= volume_label(talloc_tos(), SNUM(conn
));
3425 int snum
= SNUM(conn
);
3426 const char *fstype
= lp_fstype(SNUM(conn
));
3427 const char *filename
= NULL
;
3428 const uint64_t bytes_per_sector
= 512;
3429 uint32_t additional_flags
= 0;
3430 struct smb_filename smb_fname
;
3432 NTSTATUS status
= NT_STATUS_OK
;
3435 if (fname
== NULL
|| fname
->base_name
== NULL
) {
3438 filename
= fname
->base_name
;
3442 if (info_level
!= SMB_QUERY_CIFS_UNIX_INFO
) {
3443 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
3444 "info level (0x%x) on IPC$.\n",
3445 (unsigned int)info_level
));
3446 return NT_STATUS_ACCESS_DENIED
;
3450 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level
));
3452 ZERO_STRUCT(smb_fname
);
3453 smb_fname
.base_name
= discard_const_p(char, filename
);
3455 if(SMB_VFS_STAT(conn
, &smb_fname
) != 0) {
3456 DEBUG(2,("stat of . failed (%s)\n", strerror(errno
)));
3457 return map_nt_error_from_unix(errno
);
3462 if (max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
< max_data_bytes
) {
3463 return NT_STATUS_INVALID_PARAMETER
;
3466 *ppdata
= (char *)SMB_REALLOC(
3467 *ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
3468 if (*ppdata
== NULL
) {
3469 return NT_STATUS_NO_MEMORY
;
3473 memset((char *)pdata
,'\0',max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
3474 end_data
= pdata
+ max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
- 1;
3478 switch (info_level
) {
3479 case SMB_INFO_ALLOCATION
:
3481 uint64_t dfree
,dsize
,bsize
,block_size
,sectors_per_unit
;
3483 df_ret
= get_dfree_info(conn
, &smb_fname
, &bsize
,
3485 if (df_ret
== (uint64_t)-1) {
3486 return map_nt_error_from_unix(errno
);
3489 block_size
= lp_block_size(snum
);
3490 if (bsize
< block_size
) {
3491 uint64_t factor
= block_size
/bsize
;
3496 if (bsize
> block_size
) {
3497 uint64_t factor
= bsize
/block_size
;
3502 sectors_per_unit
= bsize
/bytes_per_sector
;
3504 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
3505 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st
.st_ex_dev
, (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
3506 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
3509 * For large drives, return max values and not modulo.
3511 dsize
= MIN(dsize
, UINT32_MAX
);
3512 dfree
= MIN(dfree
, UINT32_MAX
);
3514 SIVAL(pdata
,l1_idFileSystem
,st
.st_ex_dev
);
3515 SIVAL(pdata
,l1_cSectorUnit
,sectors_per_unit
);
3516 SIVAL(pdata
,l1_cUnit
,dsize
);
3517 SIVAL(pdata
,l1_cUnitAvail
,dfree
);
3518 SSVAL(pdata
,l1_cbSector
,bytes_per_sector
);
3522 case SMB_INFO_VOLUME
:
3523 /* Return volume name */
3525 * Add volume serial number - hash of a combination of
3526 * the called hostname and the service name.
3528 SIVAL(pdata
,0,str_checksum(lp_servicename(talloc_tos(), snum
)) ^ (str_checksum(get_local_machine_name())<<16) );
3530 * Win2k3 and previous mess this up by sending a name length
3531 * one byte short. I believe only older clients (OS/2 Win9x) use
3532 * this call so try fixing this by adding a terminating null to
3533 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
3535 status
= srvstr_push(
3537 pdata
+l2_vol_szVolLabel
, vname
,
3538 PTR_DIFF(end_data
, pdata
+l2_vol_szVolLabel
),
3539 STR_NOALIGN
|STR_TERMINATE
, &len
);
3540 if (!NT_STATUS_IS_OK(status
)) {
3543 SCVAL(pdata
,l2_vol_cch
,len
);
3544 data_len
= l2_vol_szVolLabel
+ len
;
3545 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %u, name = %s\n",
3546 (unsigned)convert_timespec_to_time_t(st
.st_ex_ctime
),
3547 (unsigned)len
, vname
));
3550 case SMB_QUERY_FS_ATTRIBUTE_INFO
:
3551 case SMB_FS_ATTRIBUTE_INFORMATION
:
3553 additional_flags
= 0;
3554 #if defined(HAVE_SYS_QUOTAS)
3555 additional_flags
|= FILE_VOLUME_QUOTAS
;
3558 if(lp_nt_acl_support(SNUM(conn
))) {
3559 additional_flags
|= FILE_PERSISTENT_ACLS
;
3562 /* Capabilities are filled in at connection time through STATVFS call */
3563 additional_flags
|= conn
->fs_capabilities
;
3564 additional_flags
|= lp_parm_int(conn
->params
->service
,
3565 "share", "fake_fscaps",
3568 SIVAL(pdata
,0,FILE_CASE_PRESERVED_NAMES
|FILE_CASE_SENSITIVE_SEARCH
|
3569 FILE_SUPPORTS_OBJECT_IDS
|FILE_UNICODE_ON_DISK
|
3570 additional_flags
); /* FS ATTRIBUTES */
3572 SIVAL(pdata
,4,255); /* Max filename component length */
3573 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
3574 and will think we can't do long filenames */
3575 status
= srvstr_push(pdata
, flags2
, pdata
+12, fstype
,
3576 PTR_DIFF(end_data
, pdata
+12),
3578 if (!NT_STATUS_IS_OK(status
)) {
3582 data_len
= 12 + len
;
3583 if (max_data_bytes
>= 16 && data_len
> max_data_bytes
) {
3584 /* the client only requested a portion of the
3586 data_len
= max_data_bytes
;
3587 status
= STATUS_BUFFER_OVERFLOW
;
3589 *fixed_portion
= 16;
3592 case SMB_QUERY_FS_LABEL_INFO
:
3593 case SMB_FS_LABEL_INFORMATION
:
3594 status
= srvstr_push(pdata
, flags2
, pdata
+4, vname
,
3595 PTR_DIFF(end_data
, pdata
+4), 0, &len
);
3596 if (!NT_STATUS_IS_OK(status
)) {
3603 case SMB_QUERY_FS_VOLUME_INFO
:
3604 case SMB_FS_VOLUME_INFORMATION
:
3607 * Add volume serial number - hash of a combination of
3608 * the called hostname and the service name.
3610 SIVAL(pdata
,8,str_checksum(lp_servicename(talloc_tos(), snum
)) ^
3611 (str_checksum(get_local_machine_name())<<16));
3613 /* Max label len is 32 characters. */
3614 status
= srvstr_push(pdata
, flags2
, pdata
+18, vname
,
3615 PTR_DIFF(end_data
, pdata
+18),
3617 if (!NT_STATUS_IS_OK(status
)) {
3620 SIVAL(pdata
,12,len
);
3623 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3624 (int)strlen(vname
),vname
,
3625 lp_servicename(talloc_tos(), snum
)));
3626 if (max_data_bytes
>= 24 && data_len
> max_data_bytes
) {
3627 /* the client only requested a portion of the
3629 data_len
= max_data_bytes
;
3630 status
= STATUS_BUFFER_OVERFLOW
;
3632 *fixed_portion
= 24;
3635 case SMB_QUERY_FS_SIZE_INFO
:
3636 case SMB_FS_SIZE_INFORMATION
:
3638 uint64_t dfree
,dsize
,bsize
,block_size
,sectors_per_unit
;
3640 df_ret
= get_dfree_info(conn
, &smb_fname
, &bsize
,
3642 if (df_ret
== (uint64_t)-1) {
3643 return map_nt_error_from_unix(errno
);
3645 block_size
= lp_block_size(snum
);
3646 if (bsize
< block_size
) {
3647 uint64_t factor
= block_size
/bsize
;
3652 if (bsize
> block_size
) {
3653 uint64_t factor
= bsize
/block_size
;
3658 sectors_per_unit
= bsize
/bytes_per_sector
;
3659 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3660 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
3661 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
3662 SBIG_UINT(pdata
,0,dsize
);
3663 SBIG_UINT(pdata
,8,dfree
);
3664 SIVAL(pdata
,16,sectors_per_unit
);
3665 SIVAL(pdata
,20,bytes_per_sector
);
3666 *fixed_portion
= 24;
3670 case SMB_FS_FULL_SIZE_INFORMATION
:
3672 uint64_t dfree
,dsize
,bsize
,block_size
,sectors_per_unit
;
3674 df_ret
= get_dfree_info(conn
, &smb_fname
, &bsize
,
3676 if (df_ret
== (uint64_t)-1) {
3677 return map_nt_error_from_unix(errno
);
3679 block_size
= lp_block_size(snum
);
3680 if (bsize
< block_size
) {
3681 uint64_t factor
= block_size
/bsize
;
3686 if (bsize
> block_size
) {
3687 uint64_t factor
= bsize
/block_size
;
3692 sectors_per_unit
= bsize
/bytes_per_sector
;
3693 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3694 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
3695 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
3696 SBIG_UINT(pdata
,0,dsize
); /* Total Allocation units. */
3697 SBIG_UINT(pdata
,8,dfree
); /* Caller available allocation units. */
3698 SBIG_UINT(pdata
,16,dfree
); /* Actual available allocation units. */
3699 SIVAL(pdata
,24,sectors_per_unit
); /* Sectors per allocation unit. */
3700 SIVAL(pdata
,28,bytes_per_sector
); /* Bytes per sector. */
3701 *fixed_portion
= 32;
3705 case SMB_QUERY_FS_DEVICE_INFO
:
3706 case SMB_FS_DEVICE_INFORMATION
:
3708 uint32_t characteristics
= FILE_DEVICE_IS_MOUNTED
;
3710 if (!CAN_WRITE(conn
)) {
3711 characteristics
|= FILE_READ_ONLY_DEVICE
;
3714 SIVAL(pdata
,0,FILE_DEVICE_DISK
); /* dev type */
3715 SIVAL(pdata
,4,characteristics
);
3720 #ifdef HAVE_SYS_QUOTAS
3721 case SMB_FS_QUOTA_INFORMATION
:
3723 * what we have to send --metze:
3725 * Unknown1: 24 NULL bytes
3726 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3727 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3728 * Quota Flags: 2 byte :
3729 * Unknown3: 6 NULL bytes
3733 * details for Quota Flags:
3735 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3736 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3737 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3738 * 0x0001 Enable Quotas: enable quota for this fs
3742 /* we need to fake up a fsp here,
3743 * because its not send in this call
3746 SMB_NTQUOTA_STRUCT quotas
;
3749 ZERO_STRUCT(quotas
);
3752 fsp
.fnum
= FNUM_FIELD_INVALID
;
3755 if (get_current_uid(conn
) != 0) {
3756 DEBUG(0,("get_user_quota: access_denied "
3757 "service [%s] user [%s]\n",
3758 lp_servicename(talloc_tos(), SNUM(conn
)),
3759 conn
->session_info
->unix_info
->unix_name
));
3760 return NT_STATUS_ACCESS_DENIED
;
3763 status
= vfs_get_ntquota(&fsp
, SMB_USER_FS_QUOTA_TYPE
,
3765 if (!NT_STATUS_IS_OK(status
)) {
3766 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn
))));
3772 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3773 lp_servicename(talloc_tos(), SNUM(conn
))));
3775 /* Unknown1 24 NULL bytes*/
3776 SBIG_UINT(pdata
,0,(uint64_t)0);
3777 SBIG_UINT(pdata
,8,(uint64_t)0);
3778 SBIG_UINT(pdata
,16,(uint64_t)0);
3780 /* Default Soft Quota 8 bytes */
3781 SBIG_UINT(pdata
,24,quotas
.softlim
);
3783 /* Default Hard Quota 8 bytes */
3784 SBIG_UINT(pdata
,32,quotas
.hardlim
);
3786 /* Quota flag 2 bytes */
3787 SSVAL(pdata
,40,quotas
.qflags
);
3789 /* Unknown3 6 NULL bytes */
3795 #endif /* HAVE_SYS_QUOTAS */
3796 case SMB_FS_OBJECTID_INFORMATION
:
3798 unsigned char objid
[16];
3799 struct smb_extended_info extended_info
;
3800 memcpy(pdata
,create_volume_objectid(conn
, objid
),16);
3801 samba_extended_info_version (&extended_info
);
3802 SIVAL(pdata
,16,extended_info
.samba_magic
);
3803 SIVAL(pdata
,20,extended_info
.samba_version
);
3804 SIVAL(pdata
,24,extended_info
.samba_subversion
);
3805 SBIG_UINT(pdata
,28,extended_info
.samba_gitcommitdate
);
3806 memcpy(pdata
+36,extended_info
.samba_version_string
,28);
3811 case SMB_FS_SECTOR_SIZE_INFORMATION
:
3815 * These values match a physical Windows Server 2012
3816 * share backed by NTFS atop spinning rust.
3818 DEBUG(5, ("SMB_FS_SECTOR_SIZE_INFORMATION:"));
3819 /* logical_bytes_per_sector */
3820 SIVAL(pdata
, 0, bytes_per_sector
);
3821 /* phys_bytes_per_sector_atomic */
3822 SIVAL(pdata
, 4, bytes_per_sector
);
3823 /* phys_bytes_per_sector_perf */
3824 SIVAL(pdata
, 8, bytes_per_sector
);
3825 /* fs_effective_phys_bytes_per_sector_atomic */
3826 SIVAL(pdata
, 12, bytes_per_sector
);
3828 SIVAL(pdata
, 16, SSINFO_FLAGS_ALIGNED_DEVICE
3829 | SSINFO_FLAGS_PARTITION_ALIGNED_ON_DEVICE
);
3830 /* byte_off_sector_align */
3831 SIVAL(pdata
, 20, 0);
3832 /* byte_off_partition_align */
3833 SIVAL(pdata
, 24, 0);
3834 *fixed_portion
= 28;
3840 * Query the version and capabilities of the CIFS UNIX extensions
3844 case SMB_QUERY_CIFS_UNIX_INFO
:
3846 bool large_write
= lp_min_receive_file_size() &&
3847 !srv_is_signing_active(xconn
);
3848 bool large_read
= !srv_is_signing_active(xconn
);
3849 int encrypt_caps
= 0;
3851 if (!lp_unix_extensions()) {
3852 return NT_STATUS_INVALID_LEVEL
;
3855 switch (conn
->encrypt_level
) {
3856 case SMB_SIGNING_OFF
:
3859 case SMB_SIGNING_DESIRED
:
3860 case SMB_SIGNING_IF_REQUIRED
:
3861 case SMB_SIGNING_DEFAULT
:
3862 encrypt_caps
= CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP
;
3864 case SMB_SIGNING_REQUIRED
:
3865 encrypt_caps
= CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP
|
3866 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP
;
3867 large_write
= false;
3873 SSVAL(pdata
,0,CIFS_UNIX_MAJOR_VERSION
);
3874 SSVAL(pdata
,2,CIFS_UNIX_MINOR_VERSION
);
3876 /* We have POSIX ACLs, pathname, encryption,
3877 * large read/write, and locking capability. */
3879 SBIG_UINT(pdata
,4,((uint64_t)(
3880 CIFS_UNIX_POSIX_ACLS_CAP
|
3881 CIFS_UNIX_POSIX_PATHNAMES_CAP
|
3882 CIFS_UNIX_FCNTL_LOCKS_CAP
|
3883 CIFS_UNIX_EXTATTR_CAP
|
3884 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP
|
3886 (large_read
? CIFS_UNIX_LARGE_READ_CAP
: 0) |
3888 CIFS_UNIX_LARGE_WRITE_CAP
: 0))));
3892 case SMB_QUERY_POSIX_FS_INFO
:
3895 vfs_statvfs_struct svfs
;
3897 if (!lp_unix_extensions()) {
3898 return NT_STATUS_INVALID_LEVEL
;
3901 rc
= SMB_VFS_STATVFS(conn
, &smb_fname
, &svfs
);
3905 SIVAL(pdata
,0,svfs
.OptimalTransferSize
);
3906 SIVAL(pdata
,4,svfs
.BlockSize
);
3907 SBIG_UINT(pdata
,8,svfs
.TotalBlocks
);
3908 SBIG_UINT(pdata
,16,svfs
.BlocksAvail
);
3909 SBIG_UINT(pdata
,24,svfs
.UserBlocksAvail
);
3910 SBIG_UINT(pdata
,32,svfs
.TotalFileNodes
);
3911 SBIG_UINT(pdata
,40,svfs
.FreeFileNodes
);
3912 SBIG_UINT(pdata
,48,svfs
.FsIdentifier
);
3913 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3915 } else if (rc
== EOPNOTSUPP
) {
3916 return NT_STATUS_INVALID_LEVEL
;
3917 #endif /* EOPNOTSUPP */
3919 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn
))));
3920 return NT_STATUS_DOS(ERRSRV
, ERRerror
);
3925 case SMB_QUERY_POSIX_WHOAMI
:
3931 if (!lp_unix_extensions()) {
3932 return NT_STATUS_INVALID_LEVEL
;
3935 if (max_data_bytes
< 40) {
3936 return NT_STATUS_BUFFER_TOO_SMALL
;
3939 if (security_session_user_level(conn
->session_info
, NULL
) < SECURITY_USER
) {
3940 flags
|= SMB_WHOAMI_GUEST
;
3943 /* NOTE: 8 bytes for UID/GID, irrespective of native
3944 * platform size. This matches
3945 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3947 data_len
= 4 /* flags */
3954 + 4 /* pad/reserved */
3955 + (conn
->session_info
->unix_token
->ngroups
* 8)
3957 + (conn
->session_info
->security_token
->num_sids
*
3961 SIVAL(pdata
, 0, flags
);
3962 SIVAL(pdata
, 4, SMB_WHOAMI_MASK
);
3964 (uint64_t)conn
->session_info
->unix_token
->uid
);
3965 SBIG_UINT(pdata
, 16,
3966 (uint64_t)conn
->session_info
->unix_token
->gid
);
3969 if (data_len
>= max_data_bytes
) {
3970 /* Potential overflow, skip the GIDs and SIDs. */
3972 SIVAL(pdata
, 24, 0); /* num_groups */
3973 SIVAL(pdata
, 28, 0); /* num_sids */
3974 SIVAL(pdata
, 32, 0); /* num_sid_bytes */
3975 SIVAL(pdata
, 36, 0); /* reserved */
3981 SIVAL(pdata
, 24, conn
->session_info
->unix_token
->ngroups
);
3982 SIVAL(pdata
, 28, conn
->session_info
->security_token
->num_sids
);
3984 /* We walk the SID list twice, but this call is fairly
3985 * infrequent, and I don't expect that it's performance
3986 * sensitive -- jpeach
3988 for (i
= 0, sid_bytes
= 0;
3989 i
< conn
->session_info
->security_token
->num_sids
; ++i
) {
3990 sid_bytes
+= ndr_size_dom_sid(
3991 &conn
->session_info
->security_token
->sids
[i
],
3995 /* SID list byte count */
3996 SIVAL(pdata
, 32, sid_bytes
);
3998 /* 4 bytes pad/reserved - must be zero */
3999 SIVAL(pdata
, 36, 0);
4003 for (i
= 0; i
< conn
->session_info
->unix_token
->ngroups
; ++i
) {
4004 SBIG_UINT(pdata
, data_len
,
4005 (uint64_t)conn
->session_info
->unix_token
->groups
[i
]);
4011 i
< conn
->session_info
->security_token
->num_sids
; ++i
) {
4012 int sid_len
= ndr_size_dom_sid(
4013 &conn
->session_info
->security_token
->sids
[i
],
4016 sid_linearize((uint8_t *)(pdata
+ data_len
),
4018 &conn
->session_info
->security_token
->sids
[i
]);
4019 data_len
+= sid_len
;
4025 case SMB_MAC_QUERY_FS_INFO
:
4027 * Thursby MAC extension... ONLY on NTFS filesystems
4028 * once we do streams then we don't need this
4030 if (strequal(lp_fstype(SNUM(conn
)),"NTFS")) {
4032 SIVAL(pdata
,84,0x100); /* Don't support mac... */
4037 return NT_STATUS_INVALID_LEVEL
;
4040 *ret_data_len
= data_len
;
4044 static NTSTATUS
smb_set_fsquota(connection_struct
*conn
,
4045 struct smb_request
*req
,
4047 const DATA_BLOB
*qdata
)
4050 SMB_NTQUOTA_STRUCT quotas
;
4052 ZERO_STRUCT(quotas
);
4055 if ((get_current_uid(conn
) != 0) || !CAN_WRITE(conn
)) {
4056 DEBUG(3, ("set_fsquota: access_denied service [%s] user [%s]\n",
4057 lp_servicename(talloc_tos(), SNUM(conn
)),
4058 conn
->session_info
->unix_info
->unix_name
));
4059 return NT_STATUS_ACCESS_DENIED
;
4062 if (!check_fsp_ntquota_handle(conn
, req
,
4064 DEBUG(1, ("set_fsquota: no valid QUOTA HANDLE\n"));
4065 return NT_STATUS_INVALID_HANDLE
;
4068 /* note: normally there're 48 bytes,
4069 * but we didn't use the last 6 bytes for now
4072 if (qdata
->length
< 42) {
4073 DEBUG(0,("set_fsquota: requires total_data(%u) >= 42 bytes!\n",
4074 (unsigned int)qdata
->length
));
4075 return NT_STATUS_INVALID_PARAMETER
;
4078 /* unknown_1 24 NULL bytes in pdata*/
4080 /* the soft quotas 8 bytes (uint64_t)*/
4081 quotas
.softlim
= BVAL(qdata
->data
,24);
4083 /* the hard quotas 8 bytes (uint64_t)*/
4084 quotas
.hardlim
= BVAL(qdata
->data
,32);
4086 /* quota_flags 2 bytes **/
4087 quotas
.qflags
= SVAL(qdata
->data
,40);
4089 /* unknown_2 6 NULL bytes follow*/
4091 /* now set the quotas */
4092 if (vfs_set_ntquota(fsp
, SMB_USER_FS_QUOTA_TYPE
, NULL
, "as
)!=0) {
4093 DEBUG(1, ("vfs_set_ntquota() failed for service [%s]\n",
4094 lp_servicename(talloc_tos(), SNUM(conn
))));
4095 status
= map_nt_error_from_unix(errno
);
4097 status
= NT_STATUS_OK
;
4102 NTSTATUS
smbd_do_setfsinfo(connection_struct
*conn
,
4103 struct smb_request
*req
,
4104 TALLOC_CTX
*mem_ctx
,
4105 uint16_t info_level
,
4107 const DATA_BLOB
*pdata
)
4109 switch (info_level
) {
4110 case SMB_FS_QUOTA_INFORMATION
:
4112 return smb_set_fsquota(conn
,
4121 return NT_STATUS_INVALID_LEVEL
;
4124 /****************************************************************************
4125 Reply to a TRANS2_QFSINFO (query filesystem info).
4126 ****************************************************************************/
4128 static void call_trans2qfsinfo(connection_struct
*conn
,
4129 struct smb_request
*req
,
4130 char **pparams
, int total_params
,
4131 char **ppdata
, int total_data
,
4132 unsigned int max_data_bytes
)
4134 char *params
= *pparams
;
4135 uint16_t info_level
;
4137 size_t fixed_portion
;
4140 if (total_params
< 2) {
4141 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4145 info_level
= SVAL(params
,0);
4147 if (ENCRYPTION_REQUIRED(conn
) && !req
->encrypted
) {
4148 if (info_level
!= SMB_QUERY_CIFS_UNIX_INFO
) {
4149 DEBUG(0,("call_trans2qfsinfo: encryption required "
4150 "and info level 0x%x sent.\n",
4151 (unsigned int)info_level
));
4152 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
4157 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level
));
4159 status
= smbd_do_qfsinfo(req
->xconn
, conn
, req
,
4166 if (!NT_STATUS_IS_OK(status
)) {
4167 reply_nterror(req
, status
);
4171 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 0, *ppdata
, data_len
,
4174 DEBUG( 4, ( "%s info_level = %d\n",
4175 smb_fn_name(req
->cmd
), info_level
) );
4180 /****************************************************************************
4181 Reply to a TRANS2_SETFSINFO (set filesystem info).
4182 ****************************************************************************/
4184 static void call_trans2setfsinfo(connection_struct
*conn
,
4185 struct smb_request
*req
,
4186 char **pparams
, int total_params
,
4187 char **ppdata
, int total_data
,
4188 unsigned int max_data_bytes
)
4190 struct smbXsrv_connection
*xconn
= req
->xconn
;
4191 char *pdata
= *ppdata
;
4192 char *params
= *pparams
;
4193 uint16_t info_level
;
4195 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",
4196 lp_servicename(talloc_tos(), SNUM(conn
))));
4199 if (total_params
< 4) {
4200 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
4202 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4206 info_level
= SVAL(params
,2);
4209 if (info_level
!= SMB_REQUEST_TRANSPORT_ENCRYPTION
&&
4210 info_level
!= SMB_SET_CIFS_UNIX_INFO
) {
4211 DEBUG(0,("call_trans2setfsinfo: not an allowed "
4212 "info level (0x%x) on IPC$.\n",
4213 (unsigned int)info_level
));
4214 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
4219 if (ENCRYPTION_REQUIRED(conn
) && !req
->encrypted
) {
4220 if (info_level
!= SMB_REQUEST_TRANSPORT_ENCRYPTION
) {
4221 DEBUG(0,("call_trans2setfsinfo: encryption required "
4222 "and info level 0x%x sent.\n",
4223 (unsigned int)info_level
));
4224 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
4229 switch(info_level
) {
4230 case SMB_SET_CIFS_UNIX_INFO
:
4231 if (!lp_unix_extensions()) {
4232 DEBUG(2,("call_trans2setfsinfo: "
4233 "SMB_SET_CIFS_UNIX_INFO is invalid with "
4234 "unix extensions off\n"));
4236 NT_STATUS_INVALID_LEVEL
);
4240 /* There should be 12 bytes of capabilities set. */
4241 if (total_data
< 12) {
4244 NT_STATUS_INVALID_PARAMETER
);
4247 xconn
->smb1
.unix_info
.client_major
= SVAL(pdata
,0);
4248 xconn
->smb1
.unix_info
.client_minor
= SVAL(pdata
,2);
4249 xconn
->smb1
.unix_info
.client_cap_low
= IVAL(pdata
,4);
4250 xconn
->smb1
.unix_info
.client_cap_high
= IVAL(pdata
,8);
4251 /* Just print these values for now. */
4252 DEBUG(10, ("call_trans2setfsinfo: set unix_info info. "
4253 "major = %u, minor = %u cap_low = 0x%x, "
4255 (unsigned int)xconn
->
4256 smb1
.unix_info
.client_major
,
4257 (unsigned int)xconn
->
4258 smb1
.unix_info
.client_minor
,
4259 (unsigned int)xconn
->
4260 smb1
.unix_info
.client_cap_low
,
4261 (unsigned int)xconn
->
4262 smb1
.unix_info
.client_cap_high
));
4264 /* Here is where we must switch to posix pathname processing... */
4265 if (xconn
->smb1
.unix_info
.client_cap_low
& CIFS_UNIX_POSIX_PATHNAMES_CAP
) {
4266 lp_set_posix_pathnames();
4267 mangle_change_to_posix();
4270 if ((xconn
->smb1
.unix_info
.client_cap_low
& CIFS_UNIX_FCNTL_LOCKS_CAP
) &&
4271 !(xconn
->smb1
.unix_info
.client_cap_low
& CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP
)) {
4272 /* Client that knows how to do posix locks,
4273 * but not posix open/mkdir operations. Set a
4274 * default type for read/write checks. */
4276 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK
);
4281 case SMB_REQUEST_TRANSPORT_ENCRYPTION
:
4284 size_t param_len
= 0;
4285 size_t data_len
= total_data
;
4287 if (!lp_unix_extensions()) {
4290 NT_STATUS_INVALID_LEVEL
);
4294 if (lp_smb_encrypt(SNUM(conn
)) == SMB_SIGNING_OFF
) {
4297 NT_STATUS_NOT_SUPPORTED
);
4301 if (xconn
->smb1
.echo_handler
.trusted_fde
) {
4302 DEBUG( 2,("call_trans2setfsinfo: "
4303 "request transport encryption disabled"
4304 "with 'fork echo handler = yes'\n"));
4307 NT_STATUS_NOT_SUPPORTED
);
4311 DEBUG( 4,("call_trans2setfsinfo: "
4312 "request transport encryption.\n"));
4314 status
= srv_request_encryption_setup(conn
,
4315 (unsigned char **)ppdata
,
4317 (unsigned char **)pparams
,
4320 if (!NT_STATUS_EQUAL(status
, NT_STATUS_MORE_PROCESSING_REQUIRED
) &&
4321 !NT_STATUS_IS_OK(status
)) {
4322 reply_nterror(req
, status
);
4326 send_trans2_replies(conn
, req
,
4334 if (NT_STATUS_IS_OK(status
)) {
4335 /* Server-side transport
4336 * encryption is now *on*. */
4337 status
= srv_encryption_start(conn
);
4338 if (!NT_STATUS_IS_OK(status
)) {
4339 char *reason
= talloc_asprintf(talloc_tos(),
4340 "Failure in setting "
4341 "up encrypted transport: %s",
4343 exit_server_cleanly(reason
);
4349 case SMB_FS_QUOTA_INFORMATION
:
4353 .data
= (uint8_t *)pdata
,
4354 .length
= total_data
4356 files_struct
*fsp
= NULL
;
4357 fsp
= file_fsp(req
, SVAL(params
,0));
4359 status
= smb_set_fsquota(conn
,
4363 if (!NT_STATUS_IS_OK(status
)) {
4364 reply_nterror(req
, status
);
4370 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
4372 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
4378 * sending this reply works fine,
4379 * but I'm not sure it's the same
4380 * like windows do...
4383 reply_outbuf(req
, 10, 0);
4386 #if defined(HAVE_POSIX_ACLS)
4387 /****************************************************************************
4388 Utility function to count the number of entries in a POSIX acl.
4389 ****************************************************************************/
4391 static unsigned int count_acl_entries(connection_struct
*conn
, SMB_ACL_T posix_acl
)
4393 unsigned int ace_count
= 0;
4394 int entry_id
= SMB_ACL_FIRST_ENTRY
;
4395 SMB_ACL_ENTRY_T entry
;
4397 while ( posix_acl
&& (sys_acl_get_entry(posix_acl
, entry_id
, &entry
) == 1)) {
4399 if (entry_id
== SMB_ACL_FIRST_ENTRY
) {
4400 entry_id
= SMB_ACL_NEXT_ENTRY
;
4407 /****************************************************************************
4408 Utility function to marshall a POSIX acl into wire format.
4409 ****************************************************************************/
4411 static bool marshall_posix_acl(connection_struct
*conn
, char *pdata
, SMB_STRUCT_STAT
*pst
, SMB_ACL_T posix_acl
)
4413 int entry_id
= SMB_ACL_FIRST_ENTRY
;
4414 SMB_ACL_ENTRY_T entry
;
4416 while ( posix_acl
&& (sys_acl_get_entry(posix_acl
, entry_id
, &entry
) == 1)) {
4417 SMB_ACL_TAG_T tagtype
;
4418 SMB_ACL_PERMSET_T permset
;
4419 unsigned char perms
= 0;
4420 unsigned int own_grp
;
4423 if (entry_id
== SMB_ACL_FIRST_ENTRY
) {
4424 entry_id
= SMB_ACL_NEXT_ENTRY
;
4427 if (sys_acl_get_tag_type(entry
, &tagtype
) == -1) {
4428 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
4432 if (sys_acl_get_permset(entry
, &permset
) == -1) {
4433 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
4437 perms
|= (sys_acl_get_perm(permset
, SMB_ACL_READ
) ? SMB_POSIX_ACL_READ
: 0);
4438 perms
|= (sys_acl_get_perm(permset
, SMB_ACL_WRITE
) ? SMB_POSIX_ACL_WRITE
: 0);
4439 perms
|= (sys_acl_get_perm(permset
, SMB_ACL_EXECUTE
) ? SMB_POSIX_ACL_EXECUTE
: 0);
4441 SCVAL(pdata
,1,perms
);
4444 case SMB_ACL_USER_OBJ
:
4445 SCVAL(pdata
,0,SMB_POSIX_ACL_USER_OBJ
);
4446 own_grp
= (unsigned int)pst
->st_ex_uid
;
4447 SIVAL(pdata
,2,own_grp
);
4452 uid_t
*puid
= (uid_t
*)sys_acl_get_qualifier(entry
);
4454 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
4457 own_grp
= (unsigned int)*puid
;
4458 SCVAL(pdata
,0,SMB_POSIX_ACL_USER
);
4459 SIVAL(pdata
,2,own_grp
);
4463 case SMB_ACL_GROUP_OBJ
:
4464 SCVAL(pdata
,0,SMB_POSIX_ACL_GROUP_OBJ
);
4465 own_grp
= (unsigned int)pst
->st_ex_gid
;
4466 SIVAL(pdata
,2,own_grp
);
4471 gid_t
*pgid
= (gid_t
*)sys_acl_get_qualifier(entry
);
4473 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
4476 own_grp
= (unsigned int)*pgid
;
4477 SCVAL(pdata
,0,SMB_POSIX_ACL_GROUP
);
4478 SIVAL(pdata
,2,own_grp
);
4483 SCVAL(pdata
,0,SMB_POSIX_ACL_MASK
);
4484 SIVAL(pdata
,2,0xFFFFFFFF);
4485 SIVAL(pdata
,6,0xFFFFFFFF);
4488 SCVAL(pdata
,0,SMB_POSIX_ACL_OTHER
);
4489 SIVAL(pdata
,2,0xFFFFFFFF);
4490 SIVAL(pdata
,6,0xFFFFFFFF);
4493 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
4496 pdata
+= SMB_POSIX_ACL_ENTRY_SIZE
;
4503 /****************************************************************************
4504 Store the FILE_UNIX_BASIC info.
4505 ****************************************************************************/
4507 static char *store_file_unix_basic(connection_struct
*conn
,
4510 const SMB_STRUCT_STAT
*psbuf
)
4512 uint64_t file_index
= get_FileIndex(conn
, psbuf
);
4515 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
4516 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf
->st_ex_mode
));
4518 SOFF_T(pdata
,0,get_file_size_stat(psbuf
)); /* File size 64 Bit */
4521 SOFF_T(pdata
,0,SMB_VFS_GET_ALLOC_SIZE(conn
,fsp
,psbuf
)); /* Number of bytes used on disk - 64 Bit */
4524 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER
, pdata
, psbuf
->st_ex_ctime
); /* Change Time 64 Bit */
4525 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER
,pdata
+8, psbuf
->st_ex_atime
); /* Last access time 64 Bit */
4526 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER
, pdata
+16, psbuf
->st_ex_mtime
); /* Last modification time 64 Bit */
4529 SIVAL(pdata
,0,psbuf
->st_ex_uid
); /* user id for the owner */
4533 SIVAL(pdata
,0,psbuf
->st_ex_gid
); /* group id of owner */
4537 SIVAL(pdata
,0,unix_filetype(psbuf
->st_ex_mode
));
4540 if (S_ISBLK(psbuf
->st_ex_mode
) || S_ISCHR(psbuf
->st_ex_mode
)) {
4541 devno
= psbuf
->st_ex_rdev
;
4543 devno
= psbuf
->st_ex_dev
;
4546 SIVAL(pdata
,0,unix_dev_major(devno
)); /* Major device number if type is device */
4550 SIVAL(pdata
,0,unix_dev_minor(devno
)); /* Minor device number if type is device */
4554 SINO_T_VAL(pdata
,0,(SMB_INO_T
)file_index
); /* inode number */
4557 SIVAL(pdata
,0, unix_perms_to_wire(psbuf
->st_ex_mode
)); /* Standard UNIX file permissions */
4561 SIVAL(pdata
,0,psbuf
->st_ex_nlink
); /* number of hard links */
4568 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
4569 * the chflags(2) (or equivalent) flags.
4571 * XXX: this really should be behind the VFS interface. To do this, we would
4572 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
4573 * Each VFS module could then implement its own mapping as appropriate for the
4574 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
4576 static const struct {unsigned stat_fflag
; unsigned smb_fflag
;}
4580 { UF_NODUMP
, EXT_DO_NOT_BACKUP
},
4584 { UF_IMMUTABLE
, EXT_IMMUTABLE
},
4588 { UF_APPEND
, EXT_OPEN_APPEND_ONLY
},
4592 { UF_HIDDEN
, EXT_HIDDEN
},
4595 /* Do not remove. We need to guarantee that this array has at least one
4596 * entry to build on HP-UX.
4602 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT
*psbuf
,
4603 uint32_t *smb_fflags
, uint32_t *smb_fmask
)
4607 for (i
= 0; i
< ARRAY_SIZE(info2_flags_map
); ++i
) {
4608 *smb_fmask
|= info2_flags_map
[i
].smb_fflag
;
4609 if (psbuf
->st_ex_flags
& info2_flags_map
[i
].stat_fflag
) {
4610 *smb_fflags
|= info2_flags_map
[i
].smb_fflag
;
4615 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT
*psbuf
,
4616 const uint32_t smb_fflags
,
4617 const uint32_t smb_fmask
,
4620 uint32_t max_fmask
= 0;
4623 *stat_fflags
= psbuf
->st_ex_flags
;
4625 /* For each flags requested in smb_fmask, check the state of the
4626 * corresponding flag in smb_fflags and set or clear the matching
4630 for (i
= 0; i
< ARRAY_SIZE(info2_flags_map
); ++i
) {
4631 max_fmask
|= info2_flags_map
[i
].smb_fflag
;
4632 if (smb_fmask
& info2_flags_map
[i
].smb_fflag
) {
4633 if (smb_fflags
& info2_flags_map
[i
].smb_fflag
) {
4634 *stat_fflags
|= info2_flags_map
[i
].stat_fflag
;
4636 *stat_fflags
&= ~info2_flags_map
[i
].stat_fflag
;
4641 /* If smb_fmask is asking to set any bits that are not supported by
4642 * our flag mappings, we should fail.
4644 if ((smb_fmask
& max_fmask
) != smb_fmask
) {
4652 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
4653 * of file flags and birth (create) time.
4655 static char *store_file_unix_basic_info2(connection_struct
*conn
,
4658 const SMB_STRUCT_STAT
*psbuf
)
4660 uint32_t file_flags
= 0;
4661 uint32_t flags_mask
= 0;
4663 pdata
= store_file_unix_basic(conn
, pdata
, fsp
, psbuf
);
4665 /* Create (birth) time 64 bit */
4666 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER
,pdata
, psbuf
->st_ex_btime
);
4669 map_info2_flags_from_sbuf(psbuf
, &file_flags
, &flags_mask
);
4670 SIVAL(pdata
, 0, file_flags
); /* flags */
4671 SIVAL(pdata
, 4, flags_mask
); /* mask */
4677 static NTSTATUS
marshall_stream_info(unsigned int num_streams
,
4678 const struct stream_struct
*streams
,
4680 unsigned int max_data_bytes
,
4681 unsigned int *data_size
)
4684 unsigned int ofs
= 0;
4686 if (max_data_bytes
< 32) {
4687 return NT_STATUS_INFO_LENGTH_MISMATCH
;
4690 for (i
= 0; i
< num_streams
; i
++) {
4691 unsigned int next_offset
;
4693 smb_ucs2_t
*namebuf
;
4695 if (!push_ucs2_talloc(talloc_tos(), &namebuf
,
4696 streams
[i
].name
, &namelen
) ||
4699 return NT_STATUS_INVALID_PARAMETER
;
4703 * name_buf is now null-terminated, we need to marshall as not
4710 * We cannot overflow ...
4712 if ((ofs
+ 24 + namelen
) > max_data_bytes
) {
4713 DEBUG(10, ("refusing to overflow reply at stream %u\n",
4715 TALLOC_FREE(namebuf
);
4716 return STATUS_BUFFER_OVERFLOW
;
4719 SIVAL(data
, ofs
+4, namelen
);
4720 SOFF_T(data
, ofs
+8, streams
[i
].size
);
4721 SOFF_T(data
, ofs
+16, streams
[i
].alloc_size
);
4722 memcpy(data
+ofs
+24, namebuf
, namelen
);
4723 TALLOC_FREE(namebuf
);
4725 next_offset
= ofs
+ 24 + namelen
;
4727 if (i
== num_streams
-1) {
4728 SIVAL(data
, ofs
, 0);
4731 unsigned int align
= ndr_align_size(next_offset
, 8);
4733 if ((next_offset
+ align
) > max_data_bytes
) {
4734 DEBUG(10, ("refusing to overflow align "
4735 "reply at stream %u\n",
4737 TALLOC_FREE(namebuf
);
4738 return STATUS_BUFFER_OVERFLOW
;
4741 memset(data
+next_offset
, 0, align
);
4742 next_offset
+= align
;
4744 SIVAL(data
, ofs
, next_offset
- ofs
);
4751 DEBUG(10, ("max_data: %u, data_size: %u\n", max_data_bytes
, ofs
));
4755 return NT_STATUS_OK
;
4758 /****************************************************************************
4759 Reply to a TRANSACT2_QFILEINFO on a PIPE !
4760 ****************************************************************************/
4762 static void call_trans2qpipeinfo(connection_struct
*conn
,
4763 struct smb_request
*req
,
4764 unsigned int tran_call
,
4765 char **pparams
, int total_params
,
4766 char **ppdata
, int total_data
,
4767 unsigned int max_data_bytes
)
4769 char *params
= *pparams
;
4770 char *pdata
= *ppdata
;
4771 unsigned int data_size
= 0;
4772 unsigned int param_size
= 2;
4773 uint16_t info_level
;
4777 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4781 if (total_params
< 4) {
4782 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4786 fsp
= file_fsp(req
, SVAL(params
,0));
4787 if (!fsp_is_np(fsp
)) {
4788 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
4792 info_level
= SVAL(params
,2);
4794 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
4795 if (*pparams
== NULL
) {
4796 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
4801 if (max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
< max_data_bytes
) {
4802 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4805 data_size
= max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
;
4806 *ppdata
= (char *)SMB_REALLOC(*ppdata
, data_size
);
4807 if (*ppdata
== NULL
) {
4808 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
4813 switch (info_level
) {
4814 case SMB_FILE_STANDARD_INFORMATION
:
4816 SOFF_T(pdata
,0,4096LL);
4823 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
4827 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, param_size
, *ppdata
, data_size
,
4833 NTSTATUS
smbd_do_qfilepathinfo(connection_struct
*conn
,
4834 TALLOC_CTX
*mem_ctx
,
4835 uint16_t info_level
,
4837 struct smb_filename
*smb_fname
,
4838 bool delete_pending
,
4839 struct timespec write_time_ts
,
4840 struct ea_list
*ea_list
,
4841 int lock_data_count
,
4844 unsigned int max_data_bytes
,
4845 size_t *fixed_portion
,
4847 unsigned int *pdata_size
)
4849 char *pdata
= *ppdata
;
4850 char *dstart
, *dend
;
4851 unsigned int data_size
;
4852 struct timespec create_time_ts
, mtime_ts
, atime_ts
, ctime_ts
;
4853 time_t create_time
, mtime
, atime
, c_time
;
4854 SMB_STRUCT_STAT
*psbuf
= &smb_fname
->st
;
4861 uint64_t file_size
= 0;
4863 uint64_t allocation_size
= 0;
4864 uint64_t file_index
= 0;
4865 uint32_t access_mask
= 0;
4868 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
4869 return NT_STATUS_INVALID_LEVEL
;
4872 DEBUG(5,("smbd_do_qfilepathinfo: %s (%s) level=%d max_data=%u\n",
4873 smb_fname_str_dbg(smb_fname
),
4875 info_level
, max_data_bytes
));
4877 mode
= dos_mode(conn
, smb_fname
);
4878 nlink
= psbuf
->st_ex_nlink
;
4880 if (nlink
&& (mode
&FILE_ATTRIBUTE_DIRECTORY
)) {
4884 if ((nlink
> 0) && delete_pending
) {
4888 if (max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
< max_data_bytes
) {
4889 return NT_STATUS_INVALID_PARAMETER
;
4892 data_size
= max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
;
4893 *ppdata
= (char *)SMB_REALLOC(*ppdata
, data_size
);
4894 if (*ppdata
== NULL
) {
4895 return NT_STATUS_NO_MEMORY
;
4899 dend
= dstart
+ data_size
- 1;
4901 if (!null_timespec(write_time_ts
) && !INFO_LEVEL_IS_UNIX(info_level
)) {
4902 update_stat_ex_mtime(psbuf
, write_time_ts
);
4905 create_time_ts
= get_create_timespec(conn
, fsp
, smb_fname
);
4906 mtime_ts
= psbuf
->st_ex_mtime
;
4907 atime_ts
= psbuf
->st_ex_atime
;
4908 ctime_ts
= get_change_timespec(conn
, fsp
, smb_fname
);
4910 if (lp_dos_filetime_resolution(SNUM(conn
))) {
4911 dos_filetime_timespec(&create_time_ts
);
4912 dos_filetime_timespec(&mtime_ts
);
4913 dos_filetime_timespec(&atime_ts
);
4914 dos_filetime_timespec(&ctime_ts
);
4917 create_time
= convert_timespec_to_time_t(create_time_ts
);
4918 mtime
= convert_timespec_to_time_t(mtime_ts
);
4919 atime
= convert_timespec_to_time_t(atime_ts
);
4920 c_time
= convert_timespec_to_time_t(ctime_ts
);
4922 p
= strrchr_m(smb_fname
->base_name
,'/');
4924 base_name
= smb_fname
->base_name
;
4928 /* NT expects the name to be in an exact form of the *full*
4929 filename. See the trans2 torture test */
4930 if (ISDOT(base_name
)) {
4931 dos_fname
= talloc_strdup(mem_ctx
, "\\");
4933 return NT_STATUS_NO_MEMORY
;
4936 dos_fname
= talloc_asprintf(mem_ctx
,
4938 smb_fname
->base_name
);
4940 return NT_STATUS_NO_MEMORY
;
4942 if (is_ntfs_stream_smb_fname(smb_fname
)) {
4943 dos_fname
= talloc_asprintf(dos_fname
, "%s",
4944 smb_fname
->stream_name
);
4946 return NT_STATUS_NO_MEMORY
;
4950 string_replace(dos_fname
, '/', '\\');
4953 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
, fsp
, psbuf
);
4956 /* Do we have this path open ? */
4958 struct file_id fileid
= vfs_file_id_from_sbuf(conn
, psbuf
);
4959 fsp1
= file_find_di_first(conn
->sconn
, fileid
);
4960 if (fsp1
&& fsp1
->initial_allocation_size
) {
4961 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
, fsp1
, psbuf
);
4965 if (!(mode
& FILE_ATTRIBUTE_DIRECTORY
)) {
4966 file_size
= get_file_size_stat(psbuf
);
4970 pos
= fsp
->fh
->position_information
;
4974 access_mask
= fsp
->access_mask
;
4976 /* GENERIC_EXECUTE mapping from Windows */
4977 access_mask
= 0x12019F;
4980 /* This should be an index number - looks like
4983 I think this causes us to fail the IFSKIT
4984 BasicFileInformationTest. -tpot */
4985 file_index
= get_FileIndex(conn
, psbuf
);
4989 switch (info_level
) {
4990 case SMB_INFO_STANDARD
:
4991 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4993 srv_put_dos_date2(pdata
,l1_fdateCreation
,create_time
);
4994 srv_put_dos_date2(pdata
,l1_fdateLastAccess
,atime
);
4995 srv_put_dos_date2(pdata
,l1_fdateLastWrite
,mtime
); /* write time */
4996 SIVAL(pdata
,l1_cbFile
,(uint32_t)file_size
);
4997 SIVAL(pdata
,l1_cbFileAlloc
,(uint32_t)allocation_size
);
4998 SSVAL(pdata
,l1_attrFile
,mode
);
5001 case SMB_INFO_QUERY_EA_SIZE
:
5003 unsigned int ea_size
=
5004 estimate_ea_size(conn
, fsp
,
5006 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
5008 srv_put_dos_date2(pdata
,0,create_time
);
5009 srv_put_dos_date2(pdata
,4,atime
);
5010 srv_put_dos_date2(pdata
,8,mtime
); /* write time */
5011 SIVAL(pdata
,12,(uint32_t)file_size
);
5012 SIVAL(pdata
,16,(uint32_t)allocation_size
);
5013 SSVAL(pdata
,20,mode
);
5014 SIVAL(pdata
,22,ea_size
);
5018 case SMB_INFO_IS_NAME_VALID
:
5019 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
5021 /* os/2 needs this ? really ?*/
5022 return NT_STATUS_DOS(ERRDOS
, ERRbadfunc
);
5024 /* This is only reached for qpathinfo */
5028 case SMB_INFO_QUERY_EAS_FROM_LIST
:
5030 size_t total_ea_len
= 0;
5031 struct ea_list
*ea_file_list
= NULL
;
5032 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
5035 get_ea_list_from_file(mem_ctx
, conn
, fsp
,
5037 &total_ea_len
, &ea_file_list
);
5038 if (!NT_STATUS_IS_OK(status
)) {
5042 ea_list
= ea_list_union(ea_list
, ea_file_list
, &total_ea_len
);
5044 if (!ea_list
|| (total_ea_len
> data_size
)) {
5046 SIVAL(pdata
,0,4); /* EA List Length must be set to 4 if no EA's. */
5050 data_size
= fill_ea_buffer(mem_ctx
, pdata
, data_size
, conn
, ea_list
);
5054 case SMB_INFO_QUERY_ALL_EAS
:
5056 /* We have data_size bytes to put EA's into. */
5057 size_t total_ea_len
= 0;
5058 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
5060 status
= get_ea_list_from_file(mem_ctx
, conn
, fsp
,
5062 &total_ea_len
, &ea_list
);
5063 if (!NT_STATUS_IS_OK(status
)) {
5067 if (!ea_list
|| (total_ea_len
> data_size
)) {
5069 SIVAL(pdata
,0,4); /* EA List Length must be set to 4 if no EA's. */
5073 data_size
= fill_ea_buffer(mem_ctx
, pdata
, data_size
, conn
, ea_list
);
5077 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
5079 /* This is FileFullEaInformation - 0xF which maps to
5080 * 1015 (decimal) in smbd_do_setfilepathinfo. */
5082 /* We have data_size bytes to put EA's into. */
5083 size_t total_ea_len
= 0;
5084 struct ea_list
*ea_file_list
= NULL
;
5086 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
5088 /*TODO: add filtering and index handling */
5091 get_ea_list_from_file(mem_ctx
, conn
, fsp
,
5093 &total_ea_len
, &ea_file_list
);
5094 if (!NT_STATUS_IS_OK(status
)) {
5097 if (!ea_file_list
) {
5098 return NT_STATUS_NO_EAS_ON_FILE
;
5101 status
= fill_ea_chained_buffer(mem_ctx
,
5105 conn
, ea_file_list
);
5106 if (!NT_STATUS_IS_OK(status
)) {
5112 case SMB_FILE_BASIC_INFORMATION
:
5113 case SMB_QUERY_FILE_BASIC_INFO
:
5115 if (info_level
== SMB_QUERY_FILE_BASIC_INFO
) {
5116 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
5117 data_size
= 36; /* w95 returns 40 bytes not 36 - why ?. */
5119 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
5123 put_long_date_timespec(conn
->ts_res
,pdata
,create_time_ts
);
5124 put_long_date_timespec(conn
->ts_res
,pdata
+8,atime_ts
);
5125 put_long_date_timespec(conn
->ts_res
,pdata
+16,mtime_ts
); /* write time */
5126 put_long_date_timespec(conn
->ts_res
,pdata
+24,ctime_ts
); /* change time */
5127 SIVAL(pdata
,32,mode
);
5129 DEBUG(5,("SMB_QFBI - "));
5130 DEBUG(5,("create: %s ", ctime(&create_time
)));
5131 DEBUG(5,("access: %s ", ctime(&atime
)));
5132 DEBUG(5,("write: %s ", ctime(&mtime
)));
5133 DEBUG(5,("change: %s ", ctime(&c_time
)));
5134 DEBUG(5,("mode: %x\n", mode
));
5135 *fixed_portion
= data_size
;
5138 case SMB_FILE_STANDARD_INFORMATION
:
5139 case SMB_QUERY_FILE_STANDARD_INFO
:
5141 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
5143 SOFF_T(pdata
,0,allocation_size
);
5144 SOFF_T(pdata
,8,file_size
);
5145 SIVAL(pdata
,16,nlink
);
5146 SCVAL(pdata
,20,delete_pending
?1:0);
5147 SCVAL(pdata
,21,(mode
&FILE_ATTRIBUTE_DIRECTORY
)?1:0);
5148 SSVAL(pdata
,22,0); /* Padding. */
5149 *fixed_portion
= 24;
5152 case SMB_FILE_EA_INFORMATION
:
5153 case SMB_QUERY_FILE_EA_INFO
:
5155 unsigned int ea_size
=
5156 estimate_ea_size(conn
, fsp
, smb_fname
);
5157 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
5160 SIVAL(pdata
,0,ea_size
);
5164 /* Get the 8.3 name - used if NT SMB was negotiated. */
5165 case SMB_QUERY_FILE_ALT_NAME_INFO
:
5166 case SMB_FILE_ALTERNATE_NAME_INFORMATION
:
5168 char mangled_name
[13];
5169 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
5170 if (!name_to_8_3(base_name
,mangled_name
,
5171 True
,conn
->params
)) {
5172 return NT_STATUS_NO_MEMORY
;
5174 status
= srvstr_push(dstart
, flags2
,
5175 pdata
+4, mangled_name
,
5176 PTR_DIFF(dend
, pdata
+4),
5178 if (!NT_STATUS_IS_OK(status
)) {
5181 data_size
= 4 + len
;
5187 case SMB_QUERY_FILE_NAME_INFO
:
5190 this must be *exactly* right for ACLs on mapped drives to work
5192 status
= srvstr_push(dstart
, flags2
,
5194 PTR_DIFF(dend
, pdata
+4),
5196 if (!NT_STATUS_IS_OK(status
)) {
5199 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
5200 data_size
= 4 + len
;
5205 case SMB_FILE_ALLOCATION_INFORMATION
:
5206 case SMB_QUERY_FILE_ALLOCATION_INFO
:
5207 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
5209 SOFF_T(pdata
,0,allocation_size
);
5212 case SMB_FILE_END_OF_FILE_INFORMATION
:
5213 case SMB_QUERY_FILE_END_OF_FILEINFO
:
5214 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
5216 SOFF_T(pdata
,0,file_size
);
5219 case SMB_QUERY_FILE_ALL_INFO
:
5220 case SMB_FILE_ALL_INFORMATION
:
5222 unsigned int ea_size
=
5223 estimate_ea_size(conn
, fsp
, smb_fname
);
5224 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
5225 put_long_date_timespec(conn
->ts_res
,pdata
,create_time_ts
);
5226 put_long_date_timespec(conn
->ts_res
,pdata
+8,atime_ts
);
5227 put_long_date_timespec(conn
->ts_res
,pdata
+16,mtime_ts
); /* write time */
5228 put_long_date_timespec(conn
->ts_res
,pdata
+24,ctime_ts
); /* change time */
5229 SIVAL(pdata
,32,mode
);
5230 SIVAL(pdata
,36,0); /* padding. */
5232 SOFF_T(pdata
,0,allocation_size
);
5233 SOFF_T(pdata
,8,file_size
);
5234 SIVAL(pdata
,16,nlink
);
5235 SCVAL(pdata
,20,delete_pending
);
5236 SCVAL(pdata
,21,(mode
&FILE_ATTRIBUTE_DIRECTORY
)?1:0);
5239 SIVAL(pdata
,0,ea_size
);
5240 pdata
+= 4; /* EA info */
5241 status
= srvstr_push(dstart
, flags2
,
5243 PTR_DIFF(dend
, pdata
+4),
5245 if (!NT_STATUS_IS_OK(status
)) {
5250 data_size
= PTR_DIFF(pdata
,(*ppdata
));
5251 *fixed_portion
= 10;
5255 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
5257 unsigned int ea_size
=
5258 estimate_ea_size(conn
, fsp
, smb_fname
);
5259 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
5260 put_long_date_timespec(conn
->ts_res
,pdata
+0x00,create_time_ts
);
5261 put_long_date_timespec(conn
->ts_res
,pdata
+0x08,atime_ts
);
5262 put_long_date_timespec(conn
->ts_res
,pdata
+0x10,mtime_ts
); /* write time */
5263 put_long_date_timespec(conn
->ts_res
,pdata
+0x18,ctime_ts
); /* change time */
5264 SIVAL(pdata
, 0x20, mode
);
5265 SIVAL(pdata
, 0x24, 0); /* padding. */
5266 SBVAL(pdata
, 0x28, allocation_size
);
5267 SBVAL(pdata
, 0x30, file_size
);
5268 SIVAL(pdata
, 0x38, nlink
);
5269 SCVAL(pdata
, 0x3C, delete_pending
);
5270 SCVAL(pdata
, 0x3D, (mode
&FILE_ATTRIBUTE_DIRECTORY
)?1:0);
5271 SSVAL(pdata
, 0x3E, 0); /* padding */
5272 SBVAL(pdata
, 0x40, file_index
);
5273 SIVAL(pdata
, 0x48, ea_size
);
5274 SIVAL(pdata
, 0x4C, access_mask
);
5275 SBVAL(pdata
, 0x50, pos
);
5276 SIVAL(pdata
, 0x58, mode
); /*TODO: mode != mode fix this!!! */
5277 SIVAL(pdata
, 0x5C, 0); /* No alignment needed. */
5281 status
= srvstr_push(dstart
, flags2
,
5283 PTR_DIFF(dend
, pdata
+4),
5285 if (!NT_STATUS_IS_OK(status
)) {
5290 data_size
= PTR_DIFF(pdata
,(*ppdata
));
5291 *fixed_portion
= 104;
5294 case SMB_FILE_INTERNAL_INFORMATION
:
5296 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
5297 SBVAL(pdata
, 0, file_index
);
5302 case SMB_FILE_ACCESS_INFORMATION
:
5303 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
5304 SIVAL(pdata
, 0, access_mask
);
5309 case SMB_FILE_NAME_INFORMATION
:
5310 /* Pathname with leading '\'. */
5313 byte_len
= dos_PutUniCode(pdata
+4,dos_fname
,(size_t)max_data_bytes
,False
);
5314 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
5315 SIVAL(pdata
,0,byte_len
);
5316 data_size
= 4 + byte_len
;
5320 case SMB_FILE_DISPOSITION_INFORMATION
:
5321 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
5323 SCVAL(pdata
,0,delete_pending
);
5327 case SMB_FILE_POSITION_INFORMATION
:
5328 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
5330 SOFF_T(pdata
,0,pos
);
5334 case SMB_FILE_MODE_INFORMATION
:
5335 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
5336 SIVAL(pdata
,0,mode
);
5341 case SMB_FILE_ALIGNMENT_INFORMATION
:
5342 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
5343 SIVAL(pdata
,0,0); /* No alignment needed. */
5349 * NT4 server just returns "invalid query" to this - if we try
5350 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
5353 /* The first statement above is false - verified using Thursby
5354 * client against NT4 -- gcolley.
5356 case SMB_QUERY_FILE_STREAM_INFO
:
5357 case SMB_FILE_STREAM_INFORMATION
: {
5358 unsigned int num_streams
= 0;
5359 struct stream_struct
*streams
= NULL
;
5361 DEBUG(10,("smbd_do_qfilepathinfo: "
5362 "SMB_FILE_STREAM_INFORMATION\n"));
5364 if (is_ntfs_stream_smb_fname(smb_fname
)) {
5365 return NT_STATUS_INVALID_PARAMETER
;
5368 status
= vfs_streaminfo(conn
,
5375 if (!NT_STATUS_IS_OK(status
)) {
5376 DEBUG(10, ("could not get stream info: %s\n",
5377 nt_errstr(status
)));
5381 status
= marshall_stream_info(num_streams
, streams
,
5382 pdata
, max_data_bytes
,
5385 if (!NT_STATUS_IS_OK(status
)) {
5386 DEBUG(10, ("marshall_stream_info failed: %s\n",
5387 nt_errstr(status
)));
5388 TALLOC_FREE(streams
);
5392 TALLOC_FREE(streams
);
5394 *fixed_portion
= 32;
5398 case SMB_QUERY_COMPRESSION_INFO
:
5399 case SMB_FILE_COMPRESSION_INFORMATION
:
5400 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
5401 SOFF_T(pdata
,0,file_size
);
5402 SIVAL(pdata
,8,0); /* ??? */
5403 SIVAL(pdata
,12,0); /* ??? */
5405 *fixed_portion
= 16;
5408 case SMB_FILE_NETWORK_OPEN_INFORMATION
:
5409 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
5410 put_long_date_timespec(conn
->ts_res
,pdata
,create_time_ts
);
5411 put_long_date_timespec(conn
->ts_res
,pdata
+8,atime_ts
);
5412 put_long_date_timespec(conn
->ts_res
,pdata
+16,mtime_ts
); /* write time */
5413 put_long_date_timespec(conn
->ts_res
,pdata
+24,ctime_ts
); /* change time */
5414 SOFF_T(pdata
,32,allocation_size
);
5415 SOFF_T(pdata
,40,file_size
);
5416 SIVAL(pdata
,48,mode
);
5417 SIVAL(pdata
,52,0); /* ??? */
5419 *fixed_portion
= 56;
5422 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION
:
5423 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
5424 SIVAL(pdata
,0,mode
);
5431 * CIFS UNIX Extensions.
5434 case SMB_QUERY_FILE_UNIX_BASIC
:
5436 pdata
= store_file_unix_basic(conn
, pdata
, fsp
, psbuf
);
5437 data_size
= PTR_DIFF(pdata
,(*ppdata
));
5439 DEBUG(4,("smbd_do_qfilepathinfo: "
5440 "SMB_QUERY_FILE_UNIX_BASIC\n"));
5441 dump_data(4, (uint8_t *)(*ppdata
), data_size
);
5445 case SMB_QUERY_FILE_UNIX_INFO2
:
5447 pdata
= store_file_unix_basic_info2(conn
, pdata
, fsp
, psbuf
);
5448 data_size
= PTR_DIFF(pdata
,(*ppdata
));
5452 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
5454 for (i
=0; i
<100; i
++)
5455 DEBUG(4,("%d=%x, ",i
, (*ppdata
)[i
]));
5461 case SMB_QUERY_FILE_UNIX_LINK
:
5464 char *buffer
= talloc_array(mem_ctx
, char, PATH_MAX
+1);
5467 return NT_STATUS_NO_MEMORY
;
5470 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
5472 if(!S_ISLNK(psbuf
->st_ex_mode
)) {
5473 return NT_STATUS_DOS(ERRSRV
, ERRbadlink
);
5476 return NT_STATUS_DOS(ERRDOS
, ERRbadlink
);
5478 link_len
= SMB_VFS_READLINK(conn
,
5481 if (link_len
== -1) {
5482 return map_nt_error_from_unix(errno
);
5484 buffer
[link_len
] = 0;
5485 status
= srvstr_push(dstart
, flags2
,
5487 PTR_DIFF(dend
, pdata
),
5488 STR_TERMINATE
, &len
);
5489 if (!NT_STATUS_IS_OK(status
)) {
5493 data_size
= PTR_DIFF(pdata
,(*ppdata
));
5498 #if defined(HAVE_POSIX_ACLS)
5499 case SMB_QUERY_POSIX_ACL
:
5501 SMB_ACL_T file_acl
= NULL
;
5502 SMB_ACL_T def_acl
= NULL
;
5503 uint16_t num_file_acls
= 0;
5504 uint16_t num_def_acls
= 0;
5506 status
= refuse_symlink(conn
,
5509 if (!NT_STATUS_IS_OK(status
)) {
5513 if (fsp
&& fsp
->fh
->fd
!= -1) {
5514 file_acl
= SMB_VFS_SYS_ACL_GET_FD(fsp
,
5518 SMB_VFS_SYS_ACL_GET_FILE(conn
,
5520 SMB_ACL_TYPE_ACCESS
,
5524 if (file_acl
== NULL
&& no_acl_syscall_error(errno
)) {
5525 DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
5526 "not implemented on "
5527 "filesystem containing %s\n",
5528 smb_fname
->base_name
));
5529 return NT_STATUS_NOT_IMPLEMENTED
;
5532 if (S_ISDIR(psbuf
->st_ex_mode
)) {
5533 if (fsp
&& fsp
->is_directory
) {
5535 SMB_VFS_SYS_ACL_GET_FILE(
5538 SMB_ACL_TYPE_DEFAULT
,
5542 SMB_VFS_SYS_ACL_GET_FILE(
5545 SMB_ACL_TYPE_DEFAULT
,
5548 def_acl
= free_empty_sys_acl(conn
, def_acl
);
5551 num_file_acls
= count_acl_entries(conn
, file_acl
);
5552 num_def_acls
= count_acl_entries(conn
, def_acl
);
5554 if ( data_size
< (num_file_acls
+ num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
+ SMB_POSIX_ACL_HEADER_SIZE
) {
5555 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
5557 (unsigned int)((num_file_acls
+ num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
+
5558 SMB_POSIX_ACL_HEADER_SIZE
) ));
5560 TALLOC_FREE(file_acl
);
5563 TALLOC_FREE(def_acl
);
5565 return NT_STATUS_BUFFER_TOO_SMALL
;
5568 SSVAL(pdata
,0,SMB_POSIX_ACL_VERSION
);
5569 SSVAL(pdata
,2,num_file_acls
);
5570 SSVAL(pdata
,4,num_def_acls
);
5571 if (!marshall_posix_acl(conn
, pdata
+ SMB_POSIX_ACL_HEADER_SIZE
, psbuf
, file_acl
)) {
5573 TALLOC_FREE(file_acl
);
5576 TALLOC_FREE(def_acl
);
5578 return NT_STATUS_INTERNAL_ERROR
;
5580 if (!marshall_posix_acl(conn
, pdata
+ SMB_POSIX_ACL_HEADER_SIZE
+ (num_file_acls
*SMB_POSIX_ACL_ENTRY_SIZE
), psbuf
, def_acl
)) {
5582 TALLOC_FREE(file_acl
);
5585 TALLOC_FREE(def_acl
);
5587 return NT_STATUS_INTERNAL_ERROR
;
5591 TALLOC_FREE(file_acl
);
5594 TALLOC_FREE(def_acl
);
5596 data_size
= (num_file_acls
+ num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
+ SMB_POSIX_ACL_HEADER_SIZE
;
5602 case SMB_QUERY_POSIX_LOCK
:
5607 enum brl_type lock_type
;
5609 /* We need an open file with a real fd for this. */
5610 if (!fsp
|| fsp
->fh
->fd
== -1) {
5611 return NT_STATUS_INVALID_LEVEL
;
5614 if (lock_data_count
!= POSIX_LOCK_DATA_SIZE
) {
5615 return NT_STATUS_INVALID_PARAMETER
;
5618 switch (SVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
)) {
5619 case POSIX_LOCK_TYPE_READ
:
5620 lock_type
= READ_LOCK
;
5622 case POSIX_LOCK_TYPE_WRITE
:
5623 lock_type
= WRITE_LOCK
;
5625 case POSIX_LOCK_TYPE_UNLOCK
:
5627 /* There's no point in asking for an unlock... */
5628 return NT_STATUS_INVALID_PARAMETER
;
5631 smblctx
= (uint64_t)IVAL(pdata
, POSIX_LOCK_PID_OFFSET
);
5632 offset
= BVAL(pdata
,POSIX_LOCK_START_OFFSET
);
5633 count
= BVAL(pdata
,POSIX_LOCK_LEN_OFFSET
);
5635 status
= query_lock(fsp
,
5642 if (ERROR_WAS_LOCK_DENIED(status
)) {
5643 /* Here we need to report who has it locked... */
5644 data_size
= POSIX_LOCK_DATA_SIZE
;
5646 SSVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
, lock_type
);
5647 SSVAL(pdata
, POSIX_LOCK_FLAGS_OFFSET
, 0);
5648 SIVAL(pdata
, POSIX_LOCK_PID_OFFSET
, (uint32_t)smblctx
);
5649 SBVAL(pdata
, POSIX_LOCK_START_OFFSET
, offset
);
5650 SBVAL(pdata
, POSIX_LOCK_LEN_OFFSET
, count
);
5652 } else if (NT_STATUS_IS_OK(status
)) {
5653 /* For success we just return a copy of what we sent
5654 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
5655 data_size
= POSIX_LOCK_DATA_SIZE
;
5656 memcpy(pdata
, lock_data
, POSIX_LOCK_DATA_SIZE
);
5657 SSVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
, POSIX_LOCK_TYPE_UNLOCK
);
5665 return NT_STATUS_INVALID_LEVEL
;
5668 *pdata_size
= data_size
;
5669 return NT_STATUS_OK
;
5672 /****************************************************************************
5673 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
5674 file name or file id).
5675 ****************************************************************************/
5677 static void call_trans2qfilepathinfo(connection_struct
*conn
,
5678 struct smb_request
*req
,
5679 unsigned int tran_call
,
5680 char **pparams
, int total_params
,
5681 char **ppdata
, int total_data
,
5682 unsigned int max_data_bytes
)
5684 char *params
= *pparams
;
5685 char *pdata
= *ppdata
;
5686 uint16_t info_level
;
5687 unsigned int data_size
= 0;
5688 unsigned int param_size
= 2;
5689 struct smb_filename
*smb_fname
= NULL
;
5690 bool delete_pending
= False
;
5691 struct timespec write_time_ts
;
5692 files_struct
*fsp
= NULL
;
5693 struct file_id fileid
;
5694 struct ea_list
*ea_list
= NULL
;
5695 int lock_data_count
= 0;
5696 char *lock_data
= NULL
;
5697 size_t fixed_portion
;
5698 NTSTATUS status
= NT_STATUS_OK
;
5701 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5705 ZERO_STRUCT(write_time_ts
);
5707 if (tran_call
== TRANSACT2_QFILEINFO
) {
5708 if (total_params
< 4) {
5709 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5714 call_trans2qpipeinfo(conn
, req
, tran_call
,
5715 pparams
, total_params
,
5721 fsp
= file_fsp(req
, SVAL(params
,0));
5722 info_level
= SVAL(params
,2);
5724 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level
));
5726 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
5727 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
5731 /* Initial check for valid fsp ptr. */
5732 if (!check_fsp_open(conn
, req
, fsp
)) {
5736 smb_fname
= cp_smb_filename(talloc_tos(), fsp
->fsp_name
);
5737 if (smb_fname
== NULL
) {
5738 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5742 if(fsp
->fake_file_handle
) {
5744 * This is actually for the QUOTA_FAKE_FILE --metze
5747 /* We know this name is ok, it's already passed the checks. */
5749 } else if(fsp
->fh
->fd
== -1) {
5751 * This is actually a QFILEINFO on a directory
5752 * handle (returned from an NT SMB). NT5.0 seems
5753 * to do this call. JRA.
5756 if (INFO_LEVEL_IS_UNIX(info_level
)) {
5757 /* Always do lstat for UNIX calls. */
5758 if (SMB_VFS_LSTAT(conn
, smb_fname
)) {
5759 DEBUG(3,("call_trans2qfilepathinfo: "
5760 "SMB_VFS_LSTAT of %s failed "
5762 smb_fname_str_dbg(smb_fname
),
5765 map_nt_error_from_unix(errno
));
5768 } else if (SMB_VFS_STAT(conn
, smb_fname
)) {
5769 DEBUG(3,("call_trans2qfilepathinfo: "
5770 "SMB_VFS_STAT of %s failed (%s)\n",
5771 smb_fname_str_dbg(smb_fname
),
5774 map_nt_error_from_unix(errno
));
5778 fileid
= vfs_file_id_from_sbuf(conn
, &smb_fname
->st
);
5779 get_file_infos(fileid
, fsp
->name_hash
, &delete_pending
, &write_time_ts
);
5782 * Original code - this is an open file.
5784 if (SMB_VFS_FSTAT(fsp
, &smb_fname
->st
) != 0) {
5785 DEBUG(3, ("fstat of %s failed (%s)\n",
5786 fsp_fnum_dbg(fsp
), strerror(errno
)));
5788 map_nt_error_from_unix(errno
));
5791 fileid
= vfs_file_id_from_sbuf(conn
, &smb_fname
->st
);
5792 get_file_infos(fileid
, fsp
->name_hash
, &delete_pending
, &write_time_ts
);
5798 uint32_t ucf_flags
= ucf_flags_from_smb_request(req
);
5801 if (total_params
< 7) {
5802 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5806 info_level
= SVAL(params
,0);
5808 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level
));
5810 if (INFO_LEVEL_IS_UNIX(info_level
)) {
5811 if (!lp_unix_extensions()) {
5812 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
5815 if (info_level
== SMB_QUERY_FILE_UNIX_BASIC
||
5816 info_level
== SMB_QUERY_FILE_UNIX_INFO2
||
5817 info_level
== SMB_QUERY_FILE_UNIX_LINK
||
5818 req
->posix_pathnames
) {
5819 ucf_flags
|= UCF_UNIX_NAME_LOOKUP
;
5823 if (req
->posix_pathnames
) {
5824 srvstr_get_path_posix(req
,
5833 srvstr_get_path(req
,
5842 if (!NT_STATUS_IS_OK(status
)) {
5843 reply_nterror(req
, status
);
5847 status
= filename_convert(req
,
5853 if (!NT_STATUS_IS_OK(status
)) {
5854 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
5855 reply_botherror(req
,
5856 NT_STATUS_PATH_NOT_COVERED
,
5857 ERRSRV
, ERRbadpath
);
5860 reply_nterror(req
, status
);
5864 /* If this is a stream, check if there is a delete_pending. */
5865 if ((conn
->fs_capabilities
& FILE_NAMED_STREAMS
)
5866 && is_ntfs_stream_smb_fname(smb_fname
)) {
5867 struct smb_filename
*smb_fname_base
;
5869 /* Create an smb_filename with stream_name == NULL. */
5870 smb_fname_base
= synthetic_smb_fname(
5872 smb_fname
->base_name
,
5876 if (smb_fname_base
== NULL
) {
5877 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5881 if (INFO_LEVEL_IS_UNIX(info_level
) || req
->posix_pathnames
) {
5882 /* Always do lstat for UNIX calls. */
5883 if (SMB_VFS_LSTAT(conn
, smb_fname_base
) != 0) {
5884 DEBUG(3,("call_trans2qfilepathinfo: "
5885 "SMB_VFS_LSTAT of %s failed "
5887 smb_fname_str_dbg(smb_fname_base
),
5889 TALLOC_FREE(smb_fname_base
);
5891 map_nt_error_from_unix(errno
));
5895 if (SMB_VFS_STAT(conn
, smb_fname_base
) != 0) {
5896 DEBUG(3,("call_trans2qfilepathinfo: "
5897 "fileinfo of %s failed "
5899 smb_fname_str_dbg(smb_fname_base
),
5901 TALLOC_FREE(smb_fname_base
);
5903 map_nt_error_from_unix(errno
));
5908 status
= file_name_hash(conn
,
5909 smb_fname_str_dbg(smb_fname_base
),
5911 if (!NT_STATUS_IS_OK(status
)) {
5912 TALLOC_FREE(smb_fname_base
);
5913 reply_nterror(req
, status
);
5917 fileid
= vfs_file_id_from_sbuf(conn
,
5918 &smb_fname_base
->st
);
5919 TALLOC_FREE(smb_fname_base
);
5920 get_file_infos(fileid
, name_hash
, &delete_pending
, NULL
);
5921 if (delete_pending
) {
5922 reply_nterror(req
, NT_STATUS_DELETE_PENDING
);
5927 if (INFO_LEVEL_IS_UNIX(info_level
) || req
->posix_pathnames
) {
5928 /* Always do lstat for UNIX calls. */
5929 if (SMB_VFS_LSTAT(conn
, smb_fname
)) {
5930 DEBUG(3,("call_trans2qfilepathinfo: "
5931 "SMB_VFS_LSTAT of %s failed (%s)\n",
5932 smb_fname_str_dbg(smb_fname
),
5935 map_nt_error_from_unix(errno
));
5940 if (SMB_VFS_STAT(conn
, smb_fname
) != 0) {
5941 DEBUG(3,("call_trans2qfilepathinfo: "
5942 "SMB_VFS_STAT of %s failed (%s)\n",
5943 smb_fname_str_dbg(smb_fname
),
5946 map_nt_error_from_unix(errno
));
5951 status
= file_name_hash(conn
,
5952 smb_fname_str_dbg(smb_fname
),
5954 if (!NT_STATUS_IS_OK(status
)) {
5955 reply_nterror(req
, status
);
5959 fileid
= vfs_file_id_from_sbuf(conn
, &smb_fname
->st
);
5960 get_file_infos(fileid
, name_hash
, &delete_pending
, &write_time_ts
);
5961 if (delete_pending
) {
5962 reply_nterror(req
, NT_STATUS_DELETE_PENDING
);
5967 DEBUG(3,("call_trans2qfilepathinfo %s (%s) level=%d call=%d "
5968 "total_data=%d\n", smb_fname_str_dbg(smb_fname
),
5970 info_level
,tran_call
,total_data
));
5972 /* Pull out any data sent here before we realloc. */
5973 switch (info_level
) {
5974 case SMB_INFO_QUERY_EAS_FROM_LIST
:
5976 /* Pull any EA list from the data portion. */
5979 if (total_data
< 4) {
5981 req
, NT_STATUS_INVALID_PARAMETER
);
5984 ea_size
= IVAL(pdata
,0);
5986 if (total_data
> 0 && ea_size
!= total_data
) {
5987 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5988 total_data=%u (should be %u)\n", (unsigned int)total_data
, (unsigned int)IVAL(pdata
,0) ));
5990 req
, NT_STATUS_INVALID_PARAMETER
);
5994 if (!lp_ea_support(SNUM(conn
))) {
5995 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
5999 /* Pull out the list of names. */
6000 ea_list
= read_ea_name_list(req
, pdata
+ 4, ea_size
- 4);
6003 req
, NT_STATUS_INVALID_PARAMETER
);
6009 case SMB_QUERY_POSIX_LOCK
:
6011 if (fsp
== NULL
|| fsp
->fh
->fd
== -1) {
6012 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
6016 if (total_data
!= POSIX_LOCK_DATA_SIZE
) {
6018 req
, NT_STATUS_INVALID_PARAMETER
);
6022 /* Copy the lock range data. */
6023 lock_data
= (char *)talloc_memdup(
6024 req
, pdata
, total_data
);
6026 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
6029 lock_data_count
= total_data
;
6035 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
6036 if (*pparams
== NULL
) {
6037 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
6044 * draft-leach-cifs-v1-spec-02.txt
6045 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
6048 * The requested information is placed in the Data portion of the
6049 * transaction response. For the information levels greater than 0x100,
6050 * the transaction response has 1 parameter word which should be
6051 * ignored by the client.
6053 * However Windows only follows this rule for the IS_NAME_VALID call.
6055 switch (info_level
) {
6056 case SMB_INFO_IS_NAME_VALID
:
6061 if ((info_level
& 0xFF00) == 0xFF00) {
6063 * We use levels that start with 0xFF00
6064 * internally to represent SMB2 specific levels
6066 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
6070 status
= smbd_do_qfilepathinfo(conn
, req
, info_level
,
6072 delete_pending
, write_time_ts
,
6074 lock_data_count
, lock_data
,
6075 req
->flags2
, max_data_bytes
,
6077 ppdata
, &data_size
);
6078 if (!NT_STATUS_IS_OK(status
)) {
6079 reply_nterror(req
, status
);
6082 if (fixed_portion
> max_data_bytes
) {
6083 reply_nterror(req
, NT_STATUS_INFO_LENGTH_MISMATCH
);
6087 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, param_size
, *ppdata
, data_size
,
6093 /****************************************************************************
6094 Set a hard link (called by UNIX extensions and by NT rename with HARD link
6096 ****************************************************************************/
6098 NTSTATUS
hardlink_internals(TALLOC_CTX
*ctx
,
6099 connection_struct
*conn
,
6100 struct smb_request
*req
,
6101 bool overwrite_if_exists
,
6102 const struct smb_filename
*smb_fname_old
,
6103 struct smb_filename
*smb_fname_new
)
6105 NTSTATUS status
= NT_STATUS_OK
;
6107 /* source must already exist. */
6108 if (!VALID_STAT(smb_fname_old
->st
)) {
6109 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
6112 if (VALID_STAT(smb_fname_new
->st
)) {
6113 if (overwrite_if_exists
) {
6114 if (S_ISDIR(smb_fname_new
->st
.st_ex_mode
)) {
6115 return NT_STATUS_FILE_IS_A_DIRECTORY
;
6117 status
= unlink_internals(conn
,
6119 FILE_ATTRIBUTE_NORMAL
,
6122 if (!NT_STATUS_IS_OK(status
)) {
6126 /* Disallow if newname already exists. */
6127 return NT_STATUS_OBJECT_NAME_COLLISION
;
6131 /* No links from a directory. */
6132 if (S_ISDIR(smb_fname_old
->st
.st_ex_mode
)) {
6133 return NT_STATUS_FILE_IS_A_DIRECTORY
;
6136 /* Setting a hardlink to/from a stream isn't currently supported. */
6137 if (is_ntfs_stream_smb_fname(smb_fname_old
) ||
6138 is_ntfs_stream_smb_fname(smb_fname_new
)) {
6139 return NT_STATUS_INVALID_PARAMETER
;
6142 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
6143 smb_fname_old
->base_name
, smb_fname_new
->base_name
));
6145 if (SMB_VFS_LINK(conn
, smb_fname_old
, smb_fname_new
) != 0) {
6146 status
= map_nt_error_from_unix(errno
);
6147 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
6148 nt_errstr(status
), smb_fname_old
->base_name
,
6149 smb_fname_new
->base_name
));
6154 /****************************************************************************
6155 Deal with setting the time from any of the setfilepathinfo functions.
6156 NOTE !!!! The check for FILE_WRITE_ATTRIBUTES access must be done *before*
6157 calling this function.
6158 ****************************************************************************/
6160 NTSTATUS
smb_set_file_time(connection_struct
*conn
,
6162 const struct smb_filename
*smb_fname
,
6163 struct smb_file_time
*ft
,
6164 bool setting_write_time
)
6166 struct smb_filename smb_fname_base
;
6168 FILE_NOTIFY_CHANGE_LAST_ACCESS
6169 |FILE_NOTIFY_CHANGE_LAST_WRITE
6170 |FILE_NOTIFY_CHANGE_CREATION
;
6172 if (!VALID_STAT(smb_fname
->st
)) {
6173 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
6176 /* get some defaults (no modifications) if any info is zero or -1. */
6177 if (null_timespec(ft
->create_time
)) {
6178 action
&= ~FILE_NOTIFY_CHANGE_CREATION
;
6181 if (null_timespec(ft
->atime
)) {
6182 action
&= ~FILE_NOTIFY_CHANGE_LAST_ACCESS
;
6185 if (null_timespec(ft
->mtime
)) {
6186 action
&= ~FILE_NOTIFY_CHANGE_LAST_WRITE
;
6189 if (!setting_write_time
) {
6190 /* ft->mtime comes from change time, not write time. */
6191 action
&= ~FILE_NOTIFY_CHANGE_LAST_WRITE
;
6194 /* Ensure the resolution is the correct for
6195 * what we can store on this filesystem. */
6197 round_timespec(conn
->ts_res
, &ft
->create_time
);
6198 round_timespec(conn
->ts_res
, &ft
->ctime
);
6199 round_timespec(conn
->ts_res
, &ft
->atime
);
6200 round_timespec(conn
->ts_res
, &ft
->mtime
);
6202 DEBUG(5,("smb_set_filetime: actime: %s\n ",
6203 time_to_asc(convert_timespec_to_time_t(ft
->atime
))));
6204 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
6205 time_to_asc(convert_timespec_to_time_t(ft
->mtime
))));
6206 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
6207 time_to_asc(convert_timespec_to_time_t(ft
->ctime
))));
6208 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
6209 time_to_asc(convert_timespec_to_time_t(ft
->create_time
))));
6211 if (setting_write_time
) {
6213 * This was a Windows setfileinfo on an open file.
6214 * NT does this a lot. We also need to
6215 * set the time here, as it can be read by
6216 * FindFirst/FindNext and with the patch for bug #2045
6217 * in smbd/fileio.c it ensures that this timestamp is
6218 * kept sticky even after a write. We save the request
6219 * away and will set it on file close and after a write. JRA.
6222 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
6223 time_to_asc(convert_timespec_to_time_t(ft
->mtime
))));
6226 if (fsp
->base_fsp
) {
6227 set_sticky_write_time_fsp(fsp
->base_fsp
,
6230 set_sticky_write_time_fsp(fsp
, ft
->mtime
);
6233 set_sticky_write_time_path(
6234 vfs_file_id_from_sbuf(conn
, &smb_fname
->st
),
6239 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
6241 /* Always call ntimes on the base, even if a stream was passed in. */
6242 smb_fname_base
= *smb_fname
;
6243 smb_fname_base
.stream_name
= NULL
;
6245 if(file_ntimes(conn
, &smb_fname_base
, ft
)!=0) {
6246 return map_nt_error_from_unix(errno
);
6249 notify_fname(conn
, NOTIFY_ACTION_MODIFIED
, action
,
6250 smb_fname
->base_name
);
6251 return NT_STATUS_OK
;
6254 /****************************************************************************
6255 Deal with setting the dosmode from any of the setfilepathinfo functions.
6256 NB. The check for FILE_WRITE_ATTRIBUTES access on this path must have been
6257 done before calling this function.
6258 ****************************************************************************/
6260 static NTSTATUS
smb_set_file_dosmode(connection_struct
*conn
,
6261 const struct smb_filename
*smb_fname
,
6264 struct smb_filename
*smb_fname_base
;
6267 if (!VALID_STAT(smb_fname
->st
)) {
6268 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
6271 /* Always operate on the base_name, even if a stream was passed in. */
6272 smb_fname_base
= synthetic_smb_fname(talloc_tos(),
6273 smb_fname
->base_name
,
6277 if (smb_fname_base
== NULL
) {
6278 return NT_STATUS_NO_MEMORY
;
6282 if (S_ISDIR(smb_fname_base
->st
.st_ex_mode
)) {
6283 dosmode
|= FILE_ATTRIBUTE_DIRECTORY
;
6285 dosmode
&= ~FILE_ATTRIBUTE_DIRECTORY
;
6289 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode
));
6291 /* check the mode isn't different, before changing it */
6292 if ((dosmode
!= 0) && (dosmode
!= dos_mode(conn
, smb_fname_base
))) {
6293 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
6294 "0x%x\n", smb_fname_str_dbg(smb_fname_base
),
6295 (unsigned int)dosmode
));
6297 if(file_set_dosmode(conn
, smb_fname_base
, dosmode
, NULL
,
6299 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
6301 smb_fname_str_dbg(smb_fname_base
),
6303 status
= map_nt_error_from_unix(errno
);
6307 status
= NT_STATUS_OK
;
6309 TALLOC_FREE(smb_fname_base
);
6313 /****************************************************************************
6314 Deal with setting the size from any of the setfilepathinfo functions.
6315 ****************************************************************************/
6317 static NTSTATUS
smb_set_file_size(connection_struct
*conn
,
6318 struct smb_request
*req
,
6320 const struct smb_filename
*smb_fname
,
6321 const SMB_STRUCT_STAT
*psbuf
,
6323 bool fail_after_createfile
)
6325 NTSTATUS status
= NT_STATUS_OK
;
6326 struct smb_filename
*smb_fname_tmp
= NULL
;
6327 files_struct
*new_fsp
= NULL
;
6329 if (!VALID_STAT(*psbuf
)) {
6330 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
6333 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size
));
6335 if (size
== get_file_size_stat(psbuf
)) {
6336 return NT_STATUS_OK
;
6339 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
6340 smb_fname_str_dbg(smb_fname
), (double)size
));
6342 if (fsp
&& fsp
->fh
->fd
!= -1) {
6343 /* Handle based call. */
6344 if (!(fsp
->access_mask
& FILE_WRITE_DATA
)) {
6345 return NT_STATUS_ACCESS_DENIED
;
6348 if (vfs_set_filelen(fsp
, size
) == -1) {
6349 return map_nt_error_from_unix(errno
);
6351 trigger_write_time_update_immediate(fsp
);
6352 return NT_STATUS_OK
;
6355 smb_fname_tmp
= cp_smb_filename(talloc_tos(), smb_fname
);
6356 if (smb_fname_tmp
== NULL
) {
6357 return NT_STATUS_NO_MEMORY
;
6360 smb_fname_tmp
->st
= *psbuf
;
6362 status
= SMB_VFS_CREATE_FILE(
6365 0, /* root_dir_fid */
6366 smb_fname_tmp
, /* fname */
6367 FILE_WRITE_DATA
, /* access_mask */
6368 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
6370 FILE_OPEN
, /* create_disposition*/
6371 0, /* create_options */
6372 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
6373 0, /* oplock_request */
6375 0, /* allocation_size */
6376 0, /* private_flags */
6379 &new_fsp
, /* result */
6381 NULL
, NULL
); /* create context */
6383 TALLOC_FREE(smb_fname_tmp
);
6385 if (!NT_STATUS_IS_OK(status
)) {
6386 /* NB. We check for open_was_deferred in the caller. */
6390 /* See RAW-SFILEINFO-END-OF-FILE */
6391 if (fail_after_createfile
) {
6392 close_file(req
, new_fsp
,NORMAL_CLOSE
);
6393 return NT_STATUS_INVALID_LEVEL
;
6396 if (vfs_set_filelen(new_fsp
, size
) == -1) {
6397 status
= map_nt_error_from_unix(errno
);
6398 close_file(req
, new_fsp
,NORMAL_CLOSE
);
6402 trigger_write_time_update_immediate(new_fsp
);
6403 close_file(req
, new_fsp
,NORMAL_CLOSE
);
6404 return NT_STATUS_OK
;
6407 /****************************************************************************
6408 Deal with SMB_INFO_SET_EA.
6409 ****************************************************************************/
6411 static NTSTATUS
smb_info_set_ea(connection_struct
*conn
,
6415 const struct smb_filename
*smb_fname
)
6417 struct ea_list
*ea_list
= NULL
;
6418 TALLOC_CTX
*ctx
= NULL
;
6419 NTSTATUS status
= NT_STATUS_OK
;
6421 if (total_data
< 10) {
6423 /* OS/2 workplace shell seems to send SET_EA requests of "null"
6424 length. They seem to have no effect. Bug #3212. JRA */
6426 if ((total_data
== 4) && (IVAL(pdata
,0) == 4)) {
6427 /* We're done. We only get EA info in this call. */
6428 return NT_STATUS_OK
;
6431 return NT_STATUS_INVALID_PARAMETER
;
6434 if (IVAL(pdata
,0) > total_data
) {
6435 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
6436 IVAL(pdata
,0), (unsigned int)total_data
));
6437 return NT_STATUS_INVALID_PARAMETER
;
6441 ea_list
= read_ea_list(ctx
, pdata
+ 4, total_data
- 4);
6443 return NT_STATUS_INVALID_PARAMETER
;
6446 status
= set_ea(conn
, fsp
, smb_fname
, ea_list
);
6451 /****************************************************************************
6452 Deal with SMB_FILE_FULL_EA_INFORMATION set.
6453 ****************************************************************************/
6455 static NTSTATUS
smb_set_file_full_ea_info(connection_struct
*conn
,
6460 struct ea_list
*ea_list
= NULL
;
6464 return NT_STATUS_INVALID_HANDLE
;
6467 if (!lp_ea_support(SNUM(conn
))) {
6468 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
6469 "EA's not supported.\n",
6470 (unsigned int)total_data
));
6471 return NT_STATUS_EAS_NOT_SUPPORTED
;
6474 if (total_data
< 10) {
6475 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
6477 (unsigned int)total_data
));
6478 return NT_STATUS_INVALID_PARAMETER
;
6481 ea_list
= read_nttrans_ea_list(talloc_tos(),
6486 return NT_STATUS_INVALID_PARAMETER
;
6489 status
= set_ea(conn
, fsp
, fsp
->fsp_name
, ea_list
);
6491 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
6492 smb_fname_str_dbg(fsp
->fsp_name
),
6493 nt_errstr(status
) ));
6499 /****************************************************************************
6500 Deal with SMB_SET_FILE_DISPOSITION_INFO.
6501 ****************************************************************************/
6503 static NTSTATUS
smb_set_file_disposition_info(connection_struct
*conn
,
6507 struct smb_filename
*smb_fname
)
6509 NTSTATUS status
= NT_STATUS_OK
;
6510 bool delete_on_close
;
6511 uint32_t dosmode
= 0;
6513 if (total_data
< 1) {
6514 return NT_STATUS_INVALID_PARAMETER
;
6518 return NT_STATUS_INVALID_HANDLE
;
6521 delete_on_close
= (CVAL(pdata
,0) ? True
: False
);
6522 dosmode
= dos_mode(conn
, smb_fname
);
6524 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
6525 "delete_on_close = %u\n",
6526 smb_fname_str_dbg(smb_fname
),
6527 (unsigned int)dosmode
,
6528 (unsigned int)delete_on_close
));
6530 if (delete_on_close
) {
6531 status
= can_set_delete_on_close(fsp
, dosmode
);
6532 if (!NT_STATUS_IS_OK(status
)) {
6537 /* The set is across all open files on this dev/inode pair. */
6538 if (!set_delete_on_close(fsp
, delete_on_close
,
6539 conn
->session_info
->security_token
,
6540 conn
->session_info
->unix_token
)) {
6541 return NT_STATUS_ACCESS_DENIED
;
6543 return NT_STATUS_OK
;
6546 /****************************************************************************
6547 Deal with SMB_FILE_POSITION_INFORMATION.
6548 ****************************************************************************/
6550 static NTSTATUS
smb_file_position_information(connection_struct
*conn
,
6555 uint64_t position_information
;
6557 if (total_data
< 8) {
6558 return NT_STATUS_INVALID_PARAMETER
;
6562 /* Ignore on pathname based set. */
6563 return NT_STATUS_OK
;
6566 position_information
= (uint64_t)IVAL(pdata
,0);
6567 position_information
|= (((uint64_t)IVAL(pdata
,4)) << 32);
6569 DEBUG(10,("smb_file_position_information: Set file position "
6570 "information for file %s to %.0f\n", fsp_str_dbg(fsp
),
6571 (double)position_information
));
6572 fsp
->fh
->position_information
= position_information
;
6573 return NT_STATUS_OK
;
6576 /****************************************************************************
6577 Deal with SMB_FILE_MODE_INFORMATION.
6578 ****************************************************************************/
6580 static NTSTATUS
smb_file_mode_information(connection_struct
*conn
,
6586 if (total_data
< 4) {
6587 return NT_STATUS_INVALID_PARAMETER
;
6589 mode
= IVAL(pdata
,0);
6590 if (mode
!= 0 && mode
!= 2 && mode
!= 4 && mode
!= 6) {
6591 return NT_STATUS_INVALID_PARAMETER
;
6593 return NT_STATUS_OK
;
6596 /****************************************************************************
6597 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
6598 ****************************************************************************/
6600 static NTSTATUS
smb_set_file_unix_link(connection_struct
*conn
,
6601 struct smb_request
*req
,
6604 const struct smb_filename
*new_smb_fname
)
6606 char *link_target
= NULL
;
6607 TALLOC_CTX
*ctx
= talloc_tos();
6609 /* Set a symbolic link. */
6610 /* Don't allow this if follow links is false. */
6612 if (total_data
== 0) {
6613 return NT_STATUS_INVALID_PARAMETER
;
6616 if (!lp_follow_symlinks(SNUM(conn
))) {
6617 return NT_STATUS_ACCESS_DENIED
;
6620 srvstr_pull_talloc(ctx
, pdata
, req
->flags2
, &link_target
, pdata
,
6621 total_data
, STR_TERMINATE
);
6624 return NT_STATUS_INVALID_PARAMETER
;
6627 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
6628 new_smb_fname
->base_name
, link_target
));
6630 if (SMB_VFS_SYMLINK(conn
,link_target
,new_smb_fname
) != 0) {
6631 return map_nt_error_from_unix(errno
);
6634 return NT_STATUS_OK
;
6637 /****************************************************************************
6638 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
6639 ****************************************************************************/
6641 static NTSTATUS
smb_set_file_unix_hlink(connection_struct
*conn
,
6642 struct smb_request
*req
,
6643 const char *pdata
, int total_data
,
6644 struct smb_filename
*smb_fname_new
)
6646 char *oldname
= NULL
;
6647 struct smb_filename
*smb_fname_old
= NULL
;
6648 uint32_t ucf_flags
= ucf_flags_from_smb_request(req
);
6649 TALLOC_CTX
*ctx
= talloc_tos();
6650 NTSTATUS status
= NT_STATUS_OK
;
6652 /* Set a hard link. */
6653 if (total_data
== 0) {
6654 return NT_STATUS_INVALID_PARAMETER
;
6657 if (req
->posix_pathnames
) {
6658 srvstr_get_path_posix(ctx
,
6667 srvstr_get_path(ctx
,
6676 if (!NT_STATUS_IS_OK(status
)) {
6680 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
6681 smb_fname_str_dbg(smb_fname_new
), oldname
));
6683 status
= filename_convert(ctx
,
6689 if (!NT_STATUS_IS_OK(status
)) {
6693 return hardlink_internals(ctx
, conn
, req
, false,
6694 smb_fname_old
, smb_fname_new
);
6697 /****************************************************************************
6698 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
6699 ****************************************************************************/
6701 static NTSTATUS
smb2_file_rename_information(connection_struct
*conn
,
6702 struct smb_request
*req
,
6706 struct smb_filename
*smb_fname_src
)
6710 char *newname
= NULL
;
6711 struct smb_filename
*smb_fname_dst
= NULL
;
6712 uint32_t ucf_flags
= UCF_SAVE_LCOMP
|
6713 ucf_flags_from_smb_request(req
);
6714 NTSTATUS status
= NT_STATUS_OK
;
6715 TALLOC_CTX
*ctx
= talloc_tos();
6718 return NT_STATUS_INVALID_HANDLE
;
6721 if (total_data
< 20) {
6722 return NT_STATUS_INVALID_PARAMETER
;
6725 overwrite
= (CVAL(pdata
,0) ? True
: False
);
6726 len
= IVAL(pdata
,16);
6728 if (len
> (total_data
- 20) || (len
== 0)) {
6729 return NT_STATUS_INVALID_PARAMETER
;
6732 if (req
->posix_pathnames
) {
6733 srvstr_get_path_posix(ctx
,
6742 srvstr_get_path(ctx
,
6751 if (!NT_STATUS_IS_OK(status
)) {
6755 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
6758 status
= filename_convert(ctx
,
6764 if (!NT_STATUS_IS_OK(status
)) {
6768 if (fsp
->base_fsp
) {
6769 /* newname must be a stream name. */
6770 if (newname
[0] != ':') {
6771 return NT_STATUS_NOT_SUPPORTED
;
6774 /* Create an smb_fname to call rename_internals_fsp() with. */
6775 smb_fname_dst
= synthetic_smb_fname(talloc_tos(),
6776 fsp
->base_fsp
->fsp_name
->base_name
,
6779 fsp
->base_fsp
->fsp_name
->flags
);
6780 if (smb_fname_dst
== NULL
) {
6781 status
= NT_STATUS_NO_MEMORY
;
6786 * Set the original last component, since
6787 * rename_internals_fsp() requires it.
6789 smb_fname_dst
->original_lcomp
= talloc_strdup(smb_fname_dst
,
6791 if (smb_fname_dst
->original_lcomp
== NULL
) {
6792 status
= NT_STATUS_NO_MEMORY
;
6798 DEBUG(10,("smb2_file_rename_information: "
6799 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
6800 fsp_fnum_dbg(fsp
), fsp_str_dbg(fsp
),
6801 smb_fname_str_dbg(smb_fname_dst
)));
6802 status
= rename_internals_fsp(conn
, fsp
, smb_fname_dst
,
6803 (FILE_ATTRIBUTE_HIDDEN
|FILE_ATTRIBUTE_SYSTEM
),
6807 TALLOC_FREE(smb_fname_dst
);
6811 static NTSTATUS
smb_file_link_information(connection_struct
*conn
,
6812 struct smb_request
*req
,
6816 struct smb_filename
*smb_fname_src
)
6820 char *newname
= NULL
;
6821 struct smb_filename
*smb_fname_dst
= NULL
;
6822 NTSTATUS status
= NT_STATUS_OK
;
6823 uint32_t ucf_flags
= UCF_SAVE_LCOMP
|
6824 ucf_flags_from_smb_request(req
);
6825 TALLOC_CTX
*ctx
= talloc_tos();
6828 return NT_STATUS_INVALID_HANDLE
;
6831 if (total_data
< 20) {
6832 return NT_STATUS_INVALID_PARAMETER
;
6835 overwrite
= (CVAL(pdata
,0) ? true : false);
6836 len
= IVAL(pdata
,16);
6838 if (len
> (total_data
- 20) || (len
== 0)) {
6839 return NT_STATUS_INVALID_PARAMETER
;
6842 if (req
->posix_pathnames
) {
6843 srvstr_get_path_posix(ctx
,
6852 srvstr_get_path(ctx
,
6861 if (!NT_STATUS_IS_OK(status
)) {
6865 DEBUG(10,("smb_file_link_information: got name |%s|\n",
6868 status
= filename_convert(ctx
,
6874 if (!NT_STATUS_IS_OK(status
)) {
6878 if (fsp
->base_fsp
) {
6879 /* No stream names. */
6880 return NT_STATUS_NOT_SUPPORTED
;
6883 DEBUG(10,("smb_file_link_information: "
6884 "SMB_FILE_LINK_INFORMATION (%s) %s -> %s\n",
6885 fsp_fnum_dbg(fsp
), fsp_str_dbg(fsp
),
6886 smb_fname_str_dbg(smb_fname_dst
)));
6887 status
= hardlink_internals(ctx
,
6894 TALLOC_FREE(smb_fname_dst
);
6898 /****************************************************************************
6899 Deal with SMB_FILE_RENAME_INFORMATION.
6900 ****************************************************************************/
6902 static NTSTATUS
smb_file_rename_information(connection_struct
*conn
,
6903 struct smb_request
*req
,
6907 struct smb_filename
*smb_fname_src
)
6912 char *newname
= NULL
;
6913 struct smb_filename
*smb_fname_dst
= NULL
;
6914 bool dest_has_wcard
= False
;
6915 NTSTATUS status
= NT_STATUS_OK
;
6917 TALLOC_CTX
*ctx
= talloc_tos();
6919 if (total_data
< 13) {
6920 return NT_STATUS_INVALID_PARAMETER
;
6923 overwrite
= (CVAL(pdata
,0) ? True
: False
);
6924 root_fid
= IVAL(pdata
,4);
6925 len
= IVAL(pdata
,8);
6927 if (len
> (total_data
- 12) || (len
== 0) || (root_fid
!= 0)) {
6928 return NT_STATUS_INVALID_PARAMETER
;
6931 if (req
->posix_pathnames
) {
6932 srvstr_get_path_wcard_posix(ctx
,
6942 srvstr_get_path_wcard(ctx
,
6952 if (!NT_STATUS_IS_OK(status
)) {
6956 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
6959 if (req
->flags2
& FLAGS2_DFS_PATHNAMES
) {
6960 status
= resolve_dfspath_wcard(ctx
, conn
,
6962 UCF_COND_ALLOW_WCARD_LCOMP
,
6963 !conn
->sconn
->using_smb2
,
6966 if (!NT_STATUS_IS_OK(status
)) {
6971 /* Check the new name has no '/' characters. */
6972 if (strchr_m(newname
, '/')) {
6973 return NT_STATUS_NOT_SUPPORTED
;
6976 if (fsp
&& fsp
->base_fsp
) {
6977 /* newname must be a stream name. */
6978 if (newname
[0] != ':') {
6979 return NT_STATUS_NOT_SUPPORTED
;
6982 /* Create an smb_fname to call rename_internals_fsp() with. */
6983 smb_fname_dst
= synthetic_smb_fname(talloc_tos(),
6984 fsp
->base_fsp
->fsp_name
->base_name
,
6987 fsp
->base_fsp
->fsp_name
->flags
);
6988 if (smb_fname_dst
== NULL
) {
6989 status
= NT_STATUS_NO_MEMORY
;
6994 * Set the original last component, since
6995 * rename_internals_fsp() requires it.
6997 smb_fname_dst
->original_lcomp
= talloc_strdup(smb_fname_dst
,
6999 if (smb_fname_dst
->original_lcomp
== NULL
) {
7000 status
= NT_STATUS_NO_MEMORY
;
7006 * Build up an smb_fname_dst based on the filename passed in.
7007 * We basically just strip off the last component, and put on
7008 * the newname instead.
7010 char *base_name
= NULL
;
7011 uint32_t ucf_flags
= UCF_SAVE_LCOMP
|
7012 ucf_flags_from_smb_request(req
);
7014 if (dest_has_wcard
) {
7015 ucf_flags
|= UCF_ALWAYS_ALLOW_WCARD_LCOMP
;
7018 /* newname must *not* be a stream name. */
7019 if (newname
[0] == ':') {
7020 return NT_STATUS_NOT_SUPPORTED
;
7024 * Strip off the last component (filename) of the path passed
7027 base_name
= talloc_strdup(ctx
, smb_fname_src
->base_name
);
7029 return NT_STATUS_NO_MEMORY
;
7031 p
= strrchr_m(base_name
, '/');
7035 base_name
= talloc_strdup(ctx
, "");
7037 return NT_STATUS_NO_MEMORY
;
7040 /* Append the new name. */
7041 base_name
= talloc_asprintf_append(base_name
,
7045 return NT_STATUS_NO_MEMORY
;
7048 status
= unix_convert(ctx
, conn
, base_name
, &smb_fname_dst
,
7051 /* If an error we expect this to be
7052 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
7054 if (!NT_STATUS_IS_OK(status
)) {
7055 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND
,
7059 /* Create an smb_fname to call rename_internals_fsp() */
7060 smb_fname_dst
= synthetic_smb_fname(ctx
,
7064 smb_fname_src
->flags
);
7065 if (smb_fname_dst
== NULL
) {
7066 status
= NT_STATUS_NO_MEMORY
;
7073 DEBUG(10,("smb_file_rename_information: "
7074 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
7075 fsp_fnum_dbg(fsp
), fsp_str_dbg(fsp
),
7076 smb_fname_str_dbg(smb_fname_dst
)));
7077 status
= rename_internals_fsp(conn
, fsp
, smb_fname_dst
, 0,
7080 DEBUG(10,("smb_file_rename_information: "
7081 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
7082 smb_fname_str_dbg(smb_fname_src
),
7083 smb_fname_str_dbg(smb_fname_dst
)));
7084 status
= rename_internals(ctx
, conn
, req
, smb_fname_src
,
7085 smb_fname_dst
, 0, overwrite
, false,
7087 FILE_WRITE_ATTRIBUTES
);
7090 TALLOC_FREE(smb_fname_dst
);
7094 /****************************************************************************
7095 Deal with SMB_SET_POSIX_ACL.
7096 ****************************************************************************/
7098 #if defined(HAVE_POSIX_ACLS)
7099 static NTSTATUS
smb_set_posix_acl(connection_struct
*conn
,
7103 const struct smb_filename
*smb_fname
)
7105 uint16_t posix_acl_version
;
7106 uint16_t num_file_acls
;
7107 uint16_t num_def_acls
;
7108 bool valid_file_acls
= True
;
7109 bool valid_def_acls
= True
;
7112 if (total_data
< SMB_POSIX_ACL_HEADER_SIZE
) {
7113 return NT_STATUS_INVALID_PARAMETER
;
7115 posix_acl_version
= SVAL(pdata
,0);
7116 num_file_acls
= SVAL(pdata
,2);
7117 num_def_acls
= SVAL(pdata
,4);
7119 if (num_file_acls
== SMB_POSIX_IGNORE_ACE_ENTRIES
) {
7120 valid_file_acls
= False
;
7124 if (num_def_acls
== SMB_POSIX_IGNORE_ACE_ENTRIES
) {
7125 valid_def_acls
= False
;
7129 if (posix_acl_version
!= SMB_POSIX_ACL_VERSION
) {
7130 return NT_STATUS_INVALID_PARAMETER
;
7133 if (total_data
< SMB_POSIX_ACL_HEADER_SIZE
+
7134 (num_file_acls
+num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
) {
7135 return NT_STATUS_INVALID_PARAMETER
;
7138 status
= refuse_symlink(conn
, fsp
, smb_fname
);
7139 if (!NT_STATUS_IS_OK(status
)) {
7143 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
7144 smb_fname
? smb_fname_str_dbg(smb_fname
) : fsp_str_dbg(fsp
),
7145 (unsigned int)num_file_acls
,
7146 (unsigned int)num_def_acls
));
7148 if (valid_file_acls
&& !set_unix_posix_acl(conn
, fsp
,
7149 smb_fname
, num_file_acls
,
7150 pdata
+ SMB_POSIX_ACL_HEADER_SIZE
)) {
7151 return map_nt_error_from_unix(errno
);
7154 if (valid_def_acls
&& !set_unix_posix_default_acl(conn
,
7155 smb_fname
, num_def_acls
,
7156 pdata
+ SMB_POSIX_ACL_HEADER_SIZE
+
7157 (num_file_acls
*SMB_POSIX_ACL_ENTRY_SIZE
))) {
7158 return map_nt_error_from_unix(errno
);
7160 return NT_STATUS_OK
;
7164 /****************************************************************************
7165 Deal with SMB_SET_POSIX_LOCK.
7166 ****************************************************************************/
7168 static NTSTATUS
smb_set_posix_lock(connection_struct
*conn
,
7169 struct smb_request
*req
,
7177 bool blocking_lock
= False
;
7178 enum brl_type lock_type
;
7180 NTSTATUS status
= NT_STATUS_OK
;
7182 if (fsp
== NULL
|| fsp
->fh
->fd
== -1) {
7183 return NT_STATUS_INVALID_HANDLE
;
7186 if (total_data
!= POSIX_LOCK_DATA_SIZE
) {
7187 return NT_STATUS_INVALID_PARAMETER
;
7190 switch (SVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
)) {
7191 case POSIX_LOCK_TYPE_READ
:
7192 lock_type
= READ_LOCK
;
7194 case POSIX_LOCK_TYPE_WRITE
:
7195 /* Return the right POSIX-mappable error code for files opened read-only. */
7196 if (!fsp
->can_write
) {
7197 return NT_STATUS_INVALID_HANDLE
;
7199 lock_type
= WRITE_LOCK
;
7201 case POSIX_LOCK_TYPE_UNLOCK
:
7202 lock_type
= UNLOCK_LOCK
;
7205 return NT_STATUS_INVALID_PARAMETER
;
7208 if (SVAL(pdata
,POSIX_LOCK_FLAGS_OFFSET
) == POSIX_LOCK_FLAG_NOWAIT
) {
7209 blocking_lock
= False
;
7210 } else if (SVAL(pdata
,POSIX_LOCK_FLAGS_OFFSET
) == POSIX_LOCK_FLAG_WAIT
) {
7211 blocking_lock
= True
;
7213 return NT_STATUS_INVALID_PARAMETER
;
7216 if (!lp_blocking_locks(SNUM(conn
))) {
7217 blocking_lock
= False
;
7220 smblctx
= (uint64_t)IVAL(pdata
, POSIX_LOCK_PID_OFFSET
);
7221 offset
= (((uint64_t) IVAL(pdata
,(POSIX_LOCK_START_OFFSET
+4))) << 32) |
7222 ((uint64_t) IVAL(pdata
,POSIX_LOCK_START_OFFSET
));
7223 count
= (((uint64_t) IVAL(pdata
,(POSIX_LOCK_LEN_OFFSET
+4))) << 32) |
7224 ((uint64_t) IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
));
7226 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
7227 "smblctx = %llu, count = %.0f, offset = %.0f\n",
7229 (unsigned int)lock_type
,
7230 (unsigned long long)smblctx
,
7234 if (lock_type
== UNLOCK_LOCK
) {
7235 status
= do_unlock(req
->sconn
->msg_ctx
,
7242 uint64_t block_smblctx
;
7244 struct byte_range_lock
*br_lck
= do_lock(req
->sconn
->msg_ctx
,
7255 if (br_lck
&& blocking_lock
&& ERROR_WAS_LOCK_DENIED(status
)) {
7257 * A blocking lock was requested. Package up
7258 * this smb into a queued request and push it
7259 * onto the blocking lock queue.
7261 if(push_blocking_lock_request(br_lck
,
7264 -1, /* infinite timeout. */
7272 TALLOC_FREE(br_lck
);
7276 TALLOC_FREE(br_lck
);
7282 /****************************************************************************
7283 Deal with SMB_SET_FILE_BASIC_INFO.
7284 ****************************************************************************/
7286 static NTSTATUS
smb_set_file_basic_info(connection_struct
*conn
,
7290 const struct smb_filename
*smb_fname
)
7292 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
7293 struct smb_file_time ft
;
7294 uint32_t dosmode
= 0;
7295 NTSTATUS status
= NT_STATUS_OK
;
7299 if (total_data
< 36) {
7300 return NT_STATUS_INVALID_PARAMETER
;
7303 status
= check_access(conn
, fsp
, smb_fname
, FILE_WRITE_ATTRIBUTES
);
7304 if (!NT_STATUS_IS_OK(status
)) {
7308 /* Set the attributes */
7309 dosmode
= IVAL(pdata
,32);
7310 status
= smb_set_file_dosmode(conn
, smb_fname
, dosmode
);
7311 if (!NT_STATUS_IS_OK(status
)) {
7316 ft
.create_time
= interpret_long_date(pdata
);
7319 ft
.atime
= interpret_long_date(pdata
+8);
7322 ft
.mtime
= interpret_long_date(pdata
+16);
7325 ft
.ctime
= interpret_long_date(pdata
+24);
7327 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
7328 smb_fname_str_dbg(smb_fname
)));
7330 return smb_set_file_time(conn
, fsp
, smb_fname
, &ft
,
7334 /****************************************************************************
7335 Deal with SMB_INFO_STANDARD.
7336 ****************************************************************************/
7338 static NTSTATUS
smb_set_info_standard(connection_struct
*conn
,
7342 const struct smb_filename
*smb_fname
)
7345 struct smb_file_time ft
;
7349 if (total_data
< 12) {
7350 return NT_STATUS_INVALID_PARAMETER
;
7354 ft
.create_time
= convert_time_t_to_timespec(srv_make_unix_date2(pdata
));
7356 ft
.atime
= convert_time_t_to_timespec(srv_make_unix_date2(pdata
+4));
7358 ft
.mtime
= convert_time_t_to_timespec(srv_make_unix_date2(pdata
+8));
7360 DEBUG(10,("smb_set_info_standard: file %s\n",
7361 smb_fname_str_dbg(smb_fname
)));
7363 status
= check_access(conn
, fsp
, smb_fname
, FILE_WRITE_ATTRIBUTES
);
7364 if (!NT_STATUS_IS_OK(status
)) {
7368 return smb_set_file_time(conn
,
7375 /****************************************************************************
7376 Deal with SMB_SET_FILE_ALLOCATION_INFO.
7377 ****************************************************************************/
7379 static NTSTATUS
smb_set_file_allocation_info(connection_struct
*conn
,
7380 struct smb_request
*req
,
7384 struct smb_filename
*smb_fname
)
7386 uint64_t allocation_size
= 0;
7387 NTSTATUS status
= NT_STATUS_OK
;
7388 files_struct
*new_fsp
= NULL
;
7390 if (!VALID_STAT(smb_fname
->st
)) {
7391 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
7394 if (total_data
< 8) {
7395 return NT_STATUS_INVALID_PARAMETER
;
7398 allocation_size
= (uint64_t)IVAL(pdata
,0);
7399 allocation_size
|= (((uint64_t)IVAL(pdata
,4)) << 32);
7400 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
7401 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname
),
7402 (double)allocation_size
));
7404 if (allocation_size
) {
7405 allocation_size
= smb_roundup(conn
, allocation_size
);
7408 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
7409 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname
),
7410 (double)allocation_size
));
7412 if (fsp
&& fsp
->fh
->fd
!= -1) {
7413 /* Open file handle. */
7414 if (!(fsp
->access_mask
& FILE_WRITE_DATA
)) {
7415 return NT_STATUS_ACCESS_DENIED
;
7418 /* Only change if needed. */
7419 if (allocation_size
!= get_file_size_stat(&smb_fname
->st
)) {
7420 if (vfs_allocate_file_space(fsp
, allocation_size
) == -1) {
7421 return map_nt_error_from_unix(errno
);
7424 /* But always update the time. */
7426 * This is equivalent to a write. Ensure it's seen immediately
7427 * if there are no pending writes.
7429 trigger_write_time_update_immediate(fsp
);
7430 return NT_STATUS_OK
;
7433 /* Pathname or stat or directory file. */
7434 status
= SMB_VFS_CREATE_FILE(
7437 0, /* root_dir_fid */
7438 smb_fname
, /* fname */
7439 FILE_WRITE_DATA
, /* access_mask */
7440 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
7442 FILE_OPEN
, /* create_disposition*/
7443 0, /* create_options */
7444 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
7445 0, /* oplock_request */
7447 0, /* allocation_size */
7448 0, /* private_flags */
7451 &new_fsp
, /* result */
7453 NULL
, NULL
); /* create context */
7455 if (!NT_STATUS_IS_OK(status
)) {
7456 /* NB. We check for open_was_deferred in the caller. */
7460 /* Only change if needed. */
7461 if (allocation_size
!= get_file_size_stat(&smb_fname
->st
)) {
7462 if (vfs_allocate_file_space(new_fsp
, allocation_size
) == -1) {
7463 status
= map_nt_error_from_unix(errno
);
7464 close_file(req
, new_fsp
, NORMAL_CLOSE
);
7469 /* Changing the allocation size should set the last mod time. */
7471 * This is equivalent to a write. Ensure it's seen immediately
7472 * if there are no pending writes.
7474 trigger_write_time_update_immediate(new_fsp
);
7475 close_file(req
, new_fsp
, NORMAL_CLOSE
);
7476 return NT_STATUS_OK
;
7479 /****************************************************************************
7480 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
7481 ****************************************************************************/
7483 static NTSTATUS
smb_set_file_end_of_file_info(connection_struct
*conn
,
7484 struct smb_request
*req
,
7488 const struct smb_filename
*smb_fname
,
7489 bool fail_after_createfile
)
7493 if (total_data
< 8) {
7494 return NT_STATUS_INVALID_PARAMETER
;
7497 size
= IVAL(pdata
,0);
7498 size
|= (((off_t
)IVAL(pdata
,4)) << 32);
7499 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
7500 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname
),
7503 return smb_set_file_size(conn
, req
,
7508 fail_after_createfile
);
7511 /****************************************************************************
7512 Allow a UNIX info mknod.
7513 ****************************************************************************/
7515 static NTSTATUS
smb_unix_mknod(connection_struct
*conn
,
7518 const struct smb_filename
*smb_fname
)
7520 uint32_t file_type
= IVAL(pdata
,56);
7521 #if defined(HAVE_MAKEDEV)
7522 uint32_t dev_major
= IVAL(pdata
,60);
7523 uint32_t dev_minor
= IVAL(pdata
,68);
7525 SMB_DEV_T dev
= (SMB_DEV_T
)0;
7526 uint32_t raw_unixmode
= IVAL(pdata
,84);
7530 if (total_data
< 100) {
7531 return NT_STATUS_INVALID_PARAMETER
;
7534 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
7535 PERM_NEW_FILE
, &unixmode
);
7536 if (!NT_STATUS_IS_OK(status
)) {
7540 #if defined(HAVE_MAKEDEV)
7541 dev
= makedev(dev_major
, dev_minor
);
7544 switch (file_type
) {
7545 #if defined(S_IFIFO)
7546 case UNIX_TYPE_FIFO
:
7547 unixmode
|= S_IFIFO
;
7550 #if defined(S_IFSOCK)
7551 case UNIX_TYPE_SOCKET
:
7552 unixmode
|= S_IFSOCK
;
7555 #if defined(S_IFCHR)
7556 case UNIX_TYPE_CHARDEV
:
7557 unixmode
|= S_IFCHR
;
7560 #if defined(S_IFBLK)
7561 case UNIX_TYPE_BLKDEV
:
7562 unixmode
|= S_IFBLK
;
7566 return NT_STATUS_INVALID_PARAMETER
;
7569 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
7570 "%.0f mode 0%o for file %s\n", (double)dev
,
7571 (unsigned int)unixmode
, smb_fname_str_dbg(smb_fname
)));
7573 /* Ok - do the mknod. */
7574 if (SMB_VFS_MKNOD(conn
, smb_fname
, unixmode
, dev
) != 0) {
7575 return map_nt_error_from_unix(errno
);
7578 /* If any of the other "set" calls fail we
7579 * don't want to end up with a half-constructed mknod.
7582 if (lp_inherit_permissions(SNUM(conn
))) {
7584 if (!parent_dirname(talloc_tos(), smb_fname
->base_name
,
7586 return NT_STATUS_NO_MEMORY
;
7588 inherit_access_posix_acl(conn
, parent
, smb_fname
,
7590 TALLOC_FREE(parent
);
7593 return NT_STATUS_OK
;
7596 /****************************************************************************
7597 Deal with SMB_SET_FILE_UNIX_BASIC.
7598 ****************************************************************************/
7600 static NTSTATUS
smb_set_file_unix_basic(connection_struct
*conn
,
7601 struct smb_request
*req
,
7605 const struct smb_filename
*smb_fname
)
7607 struct smb_file_time ft
;
7608 uint32_t raw_unixmode
;
7611 uid_t set_owner
= (uid_t
)SMB_UID_NO_CHANGE
;
7612 gid_t set_grp
= (uid_t
)SMB_GID_NO_CHANGE
;
7613 NTSTATUS status
= NT_STATUS_OK
;
7614 bool delete_on_fail
= False
;
7615 enum perm_type ptype
;
7616 files_struct
*all_fsps
= NULL
;
7617 bool modify_mtime
= true;
7619 struct smb_filename
*smb_fname_tmp
= NULL
;
7620 SMB_STRUCT_STAT sbuf
;
7624 if (total_data
< 100) {
7625 return NT_STATUS_INVALID_PARAMETER
;
7628 if(IVAL(pdata
, 0) != SMB_SIZE_NO_CHANGE_LO
&&
7629 IVAL(pdata
, 4) != SMB_SIZE_NO_CHANGE_HI
) {
7630 size
=IVAL(pdata
,0); /* first 8 Bytes are size */
7631 size
|= (((off_t
)IVAL(pdata
,4)) << 32);
7634 ft
.atime
= interpret_long_date(pdata
+24); /* access_time */
7635 ft
.mtime
= interpret_long_date(pdata
+32); /* modification_time */
7636 set_owner
= (uid_t
)IVAL(pdata
,40);
7637 set_grp
= (gid_t
)IVAL(pdata
,48);
7638 raw_unixmode
= IVAL(pdata
,84);
7640 if (VALID_STAT(smb_fname
->st
)) {
7641 if (S_ISDIR(smb_fname
->st
.st_ex_mode
)) {
7642 ptype
= PERM_EXISTING_DIR
;
7644 ptype
= PERM_EXISTING_FILE
;
7647 ptype
= PERM_NEW_FILE
;
7650 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
7652 if (!NT_STATUS_IS_OK(status
)) {
7656 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
7657 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
7658 smb_fname_str_dbg(smb_fname
), (double)size
,
7659 (unsigned int)set_owner
, (unsigned int)set_grp
,
7660 (int)raw_unixmode
));
7662 sbuf
= smb_fname
->st
;
7664 if (!VALID_STAT(sbuf
)) {
7666 * The only valid use of this is to create character and block
7667 * devices, and named pipes. This is deprecated (IMHO) and
7668 * a new info level should be used for mknod. JRA.
7671 status
= smb_unix_mknod(conn
,
7675 if (!NT_STATUS_IS_OK(status
)) {
7679 smb_fname_tmp
= cp_smb_filename(talloc_tos(), smb_fname
);
7680 if (smb_fname_tmp
== NULL
) {
7681 return NT_STATUS_NO_MEMORY
;
7684 if (SMB_VFS_STAT(conn
, smb_fname_tmp
) != 0) {
7685 status
= map_nt_error_from_unix(errno
);
7686 TALLOC_FREE(smb_fname_tmp
);
7687 SMB_VFS_UNLINK(conn
, smb_fname
);
7691 sbuf
= smb_fname_tmp
->st
;
7692 smb_fname
= smb_fname_tmp
;
7694 /* Ensure we don't try and change anything else. */
7695 raw_unixmode
= SMB_MODE_NO_CHANGE
;
7696 size
= get_file_size_stat(&sbuf
);
7697 ft
.atime
= sbuf
.st_ex_atime
;
7698 ft
.mtime
= sbuf
.st_ex_mtime
;
7700 * We continue here as we might want to change the
7703 delete_on_fail
= True
;
7707 /* Horrible backwards compatibility hack as an old server bug
7708 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
7712 size
= get_file_size_stat(&sbuf
);
7717 * Deal with the UNIX specific mode set.
7720 if (raw_unixmode
!= SMB_MODE_NO_CHANGE
) {
7723 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7724 "setting mode 0%o for file %s\n",
7725 (unsigned int)unixmode
,
7726 smb_fname_str_dbg(smb_fname
)));
7727 if (fsp
&& fsp
->fh
->fd
!= -1) {
7728 ret
= SMB_VFS_FCHMOD(fsp
, unixmode
);
7730 ret
= SMB_VFS_CHMOD(conn
, smb_fname
, unixmode
);
7733 return map_nt_error_from_unix(errno
);
7738 * Deal with the UNIX specific uid set.
7741 if ((set_owner
!= (uid_t
)SMB_UID_NO_CHANGE
) &&
7742 (sbuf
.st_ex_uid
!= set_owner
)) {
7745 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7746 "changing owner %u for path %s\n",
7747 (unsigned int)set_owner
,
7748 smb_fname_str_dbg(smb_fname
)));
7750 if (fsp
&& fsp
->fh
->fd
!= -1) {
7751 ret
= SMB_VFS_FCHOWN(fsp
, set_owner
, (gid_t
)-1);
7754 * UNIX extensions calls must always operate
7757 ret
= SMB_VFS_LCHOWN(conn
, smb_fname
,
7758 set_owner
, (gid_t
)-1);
7762 status
= map_nt_error_from_unix(errno
);
7763 if (delete_on_fail
) {
7764 SMB_VFS_UNLINK(conn
, smb_fname
);
7771 * Deal with the UNIX specific gid set.
7774 if ((set_grp
!= (uid_t
)SMB_GID_NO_CHANGE
) &&
7775 (sbuf
.st_ex_gid
!= set_grp
)) {
7778 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7779 "changing group %u for file %s\n",
7780 (unsigned int)set_owner
,
7781 smb_fname_str_dbg(smb_fname
)));
7782 if (fsp
&& fsp
->fh
->fd
!= -1) {
7783 ret
= SMB_VFS_FCHOWN(fsp
, set_owner
, (gid_t
)-1);
7786 * UNIX extensions calls must always operate
7789 ret
= SMB_VFS_LCHOWN(conn
, smb_fname
, (uid_t
)-1,
7793 status
= map_nt_error_from_unix(errno
);
7794 if (delete_on_fail
) {
7795 SMB_VFS_UNLINK(conn
, smb_fname
);
7801 /* Deal with any size changes. */
7803 status
= smb_set_file_size(conn
, req
,
7809 if (!NT_STATUS_IS_OK(status
)) {
7813 /* Deal with any time changes. */
7814 if (null_timespec(ft
.mtime
) && null_timespec(ft
.atime
)) {
7815 /* No change, don't cancel anything. */
7819 id
= vfs_file_id_from_sbuf(conn
, &sbuf
);
7820 for(all_fsps
= file_find_di_first(conn
->sconn
, id
); all_fsps
;
7821 all_fsps
= file_find_di_next(all_fsps
)) {
7823 * We're setting the time explicitly for UNIX.
7824 * Cancel any pending changes over all handles.
7826 all_fsps
->update_write_time_on_close
= false;
7827 TALLOC_FREE(all_fsps
->update_write_time_event
);
7831 * Override the "setting_write_time"
7832 * parameter here as it almost does what
7833 * we need. Just remember if we modified
7834 * mtime and send the notify ourselves.
7836 if (null_timespec(ft
.mtime
)) {
7837 modify_mtime
= false;
7840 status
= smb_set_file_time(conn
,
7846 notify_fname(conn
, NOTIFY_ACTION_MODIFIED
,
7847 FILE_NOTIFY_CHANGE_LAST_WRITE
, smb_fname
->base_name
);
7852 /****************************************************************************
7853 Deal with SMB_SET_FILE_UNIX_INFO2.
7854 ****************************************************************************/
7856 static NTSTATUS
smb_set_file_unix_info2(connection_struct
*conn
,
7857 struct smb_request
*req
,
7861 const struct smb_filename
*smb_fname
)
7864 uint32_t smb_fflags
;
7867 if (total_data
< 116) {
7868 return NT_STATUS_INVALID_PARAMETER
;
7871 /* Start by setting all the fields that are common between UNIX_BASIC
7874 status
= smb_set_file_unix_basic(conn
, req
, pdata
, total_data
,
7876 if (!NT_STATUS_IS_OK(status
)) {
7880 smb_fflags
= IVAL(pdata
, 108);
7881 smb_fmask
= IVAL(pdata
, 112);
7883 /* NB: We should only attempt to alter the file flags if the client
7884 * sends a non-zero mask.
7886 if (smb_fmask
!= 0) {
7887 int stat_fflags
= 0;
7889 if (!map_info2_flags_to_sbuf(&smb_fname
->st
, smb_fflags
,
7890 smb_fmask
, &stat_fflags
)) {
7891 /* Client asked to alter a flag we don't understand. */
7892 return NT_STATUS_INVALID_PARAMETER
;
7895 if (fsp
&& fsp
->fh
->fd
!= -1) {
7896 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
7897 return NT_STATUS_NOT_SUPPORTED
;
7899 if (SMB_VFS_CHFLAGS(conn
, smb_fname
,
7900 stat_fflags
) != 0) {
7901 return map_nt_error_from_unix(errno
);
7906 /* XXX: need to add support for changing the create_time here. You
7907 * can do this for paths on Darwin with setattrlist(2). The right way
7908 * to hook this up is probably by extending the VFS utimes interface.
7911 return NT_STATUS_OK
;
7914 /****************************************************************************
7915 Create a directory with POSIX semantics.
7916 ****************************************************************************/
7918 static NTSTATUS
smb_posix_mkdir(connection_struct
*conn
,
7919 struct smb_request
*req
,
7922 struct smb_filename
*smb_fname
,
7923 int *pdata_return_size
)
7925 NTSTATUS status
= NT_STATUS_OK
;
7926 uint32_t raw_unixmode
= 0;
7927 uint32_t mod_unixmode
= 0;
7928 mode_t unixmode
= (mode_t
)0;
7929 files_struct
*fsp
= NULL
;
7930 uint16_t info_level_return
= 0;
7932 char *pdata
= *ppdata
;
7934 if (total_data
< 18) {
7935 return NT_STATUS_INVALID_PARAMETER
;
7938 raw_unixmode
= IVAL(pdata
,8);
7939 /* Next 4 bytes are not yet defined. */
7941 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
7942 PERM_NEW_DIR
, &unixmode
);
7943 if (!NT_STATUS_IS_OK(status
)) {
7947 mod_unixmode
= (uint32_t)unixmode
| FILE_FLAG_POSIX_SEMANTICS
;
7949 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
7950 smb_fname_str_dbg(smb_fname
), (unsigned int)unixmode
));
7952 status
= SMB_VFS_CREATE_FILE(
7955 0, /* root_dir_fid */
7956 smb_fname
, /* fname */
7957 FILE_READ_ATTRIBUTES
, /* access_mask */
7958 FILE_SHARE_NONE
, /* share_access */
7959 FILE_CREATE
, /* create_disposition*/
7960 FILE_DIRECTORY_FILE
, /* create_options */
7961 mod_unixmode
, /* file_attributes */
7962 0, /* oplock_request */
7964 0, /* allocation_size */
7965 0, /* private_flags */
7970 NULL
, NULL
); /* create context */
7972 if (NT_STATUS_IS_OK(status
)) {
7973 close_file(req
, fsp
, NORMAL_CLOSE
);
7976 info_level_return
= SVAL(pdata
,16);
7978 if (info_level_return
== SMB_QUERY_FILE_UNIX_BASIC
) {
7979 *pdata_return_size
= 12 + SMB_FILE_UNIX_BASIC_SIZE
;
7980 } else if (info_level_return
== SMB_QUERY_FILE_UNIX_INFO2
) {
7981 *pdata_return_size
= 12 + SMB_FILE_UNIX_INFO2_SIZE
;
7983 *pdata_return_size
= 12;
7986 /* Realloc the data size */
7987 *ppdata
= (char *)SMB_REALLOC(*ppdata
,*pdata_return_size
);
7988 if (*ppdata
== NULL
) {
7989 *pdata_return_size
= 0;
7990 return NT_STATUS_NO_MEMORY
;
7994 SSVAL(pdata
,0,NO_OPLOCK_RETURN
);
7995 SSVAL(pdata
,2,0); /* No fnum. */
7996 SIVAL(pdata
,4,info
); /* Was directory created. */
7998 switch (info_level_return
) {
7999 case SMB_QUERY_FILE_UNIX_BASIC
:
8000 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_BASIC
);
8001 SSVAL(pdata
,10,0); /* Padding. */
8002 store_file_unix_basic(conn
, pdata
+ 12, fsp
,
8005 case SMB_QUERY_FILE_UNIX_INFO2
:
8006 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_INFO2
);
8007 SSVAL(pdata
,10,0); /* Padding. */
8008 store_file_unix_basic_info2(conn
, pdata
+ 12, fsp
,
8012 SSVAL(pdata
,8,SMB_NO_INFO_LEVEL_RETURNED
);
8013 SSVAL(pdata
,10,0); /* Padding. */
8020 /****************************************************************************
8021 Open/Create a file with POSIX semantics.
8022 ****************************************************************************/
8024 #define SMB_O_RDONLY_MAPPING (FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA)
8025 #define SMB_O_WRONLY_MAPPING (FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA)
8027 static NTSTATUS
smb_posix_open(connection_struct
*conn
,
8028 struct smb_request
*req
,
8031 struct smb_filename
*smb_fname
,
8032 int *pdata_return_size
)
8034 bool extended_oplock_granted
= False
;
8035 char *pdata
= *ppdata
;
8037 uint32_t wire_open_mode
= 0;
8038 uint32_t raw_unixmode
= 0;
8039 uint32_t mod_unixmode
= 0;
8040 uint32_t create_disp
= 0;
8041 uint32_t access_mask
= 0;
8042 uint32_t create_options
= FILE_NON_DIRECTORY_FILE
;
8043 NTSTATUS status
= NT_STATUS_OK
;
8044 mode_t unixmode
= (mode_t
)0;
8045 files_struct
*fsp
= NULL
;
8046 int oplock_request
= 0;
8048 uint16_t info_level_return
= 0;
8050 if (total_data
< 18) {
8051 return NT_STATUS_INVALID_PARAMETER
;
8054 flags
= IVAL(pdata
,0);
8055 oplock_request
= (flags
& REQUEST_OPLOCK
) ? EXCLUSIVE_OPLOCK
: 0;
8056 if (oplock_request
) {
8057 oplock_request
|= (flags
& REQUEST_BATCH_OPLOCK
) ? BATCH_OPLOCK
: 0;
8060 wire_open_mode
= IVAL(pdata
,4);
8062 if (wire_open_mode
== (SMB_O_CREAT
|SMB_O_DIRECTORY
)) {
8063 return smb_posix_mkdir(conn
, req
,
8070 switch (wire_open_mode
& SMB_ACCMODE
) {
8072 access_mask
= SMB_O_RDONLY_MAPPING
;
8075 access_mask
= SMB_O_WRONLY_MAPPING
;
8078 access_mask
= (SMB_O_RDONLY_MAPPING
|
8079 SMB_O_WRONLY_MAPPING
);
8082 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
8083 (unsigned int)wire_open_mode
));
8084 return NT_STATUS_INVALID_PARAMETER
;
8087 wire_open_mode
&= ~SMB_ACCMODE
;
8089 /* First take care of O_CREAT|O_EXCL interactions. */
8090 switch (wire_open_mode
& (SMB_O_CREAT
| SMB_O_EXCL
)) {
8091 case (SMB_O_CREAT
| SMB_O_EXCL
):
8092 /* File exists fail. File not exist create. */
8093 create_disp
= FILE_CREATE
;
8096 /* File exists open. File not exist create. */
8097 create_disp
= FILE_OPEN_IF
;
8100 /* O_EXCL on its own without O_CREAT is undefined.
8101 We deliberately ignore it as some versions of
8102 Linux CIFSFS can send a bare O_EXCL on the
8103 wire which other filesystems in the kernel
8104 ignore. See bug 9519 for details. */
8109 /* File exists open. File not exist fail. */
8110 create_disp
= FILE_OPEN
;
8113 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
8114 (unsigned int)wire_open_mode
));
8115 return NT_STATUS_INVALID_PARAMETER
;
8118 /* Next factor in the effects of O_TRUNC. */
8119 wire_open_mode
&= ~(SMB_O_CREAT
| SMB_O_EXCL
);
8121 if (wire_open_mode
& SMB_O_TRUNC
) {
8122 switch (create_disp
) {
8124 /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
8125 /* Leave create_disp alone as
8126 (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
8128 /* File exists fail. File not exist create. */
8131 /* SMB_O_CREAT | SMB_O_TRUNC */
8132 /* File exists overwrite. File not exist create. */
8133 create_disp
= FILE_OVERWRITE_IF
;
8137 /* File exists overwrite. File not exist fail. */
8138 create_disp
= FILE_OVERWRITE
;
8141 /* Cannot get here. */
8142 smb_panic("smb_posix_open: logic error");
8143 return NT_STATUS_INVALID_PARAMETER
;
8147 raw_unixmode
= IVAL(pdata
,8);
8148 /* Next 4 bytes are not yet defined. */
8150 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
8151 (VALID_STAT(smb_fname
->st
) ?
8152 PERM_EXISTING_FILE
: PERM_NEW_FILE
),
8155 if (!NT_STATUS_IS_OK(status
)) {
8159 mod_unixmode
= (uint32_t)unixmode
| FILE_FLAG_POSIX_SEMANTICS
;
8161 if (wire_open_mode
& SMB_O_SYNC
) {
8162 create_options
|= FILE_WRITE_THROUGH
;
8164 if (wire_open_mode
& SMB_O_APPEND
) {
8165 access_mask
|= FILE_APPEND_DATA
;
8167 if (wire_open_mode
& SMB_O_DIRECT
) {
8168 mod_unixmode
|= FILE_FLAG_NO_BUFFERING
;
8171 if ((wire_open_mode
& SMB_O_DIRECTORY
) ||
8172 VALID_STAT_OF_DIR(smb_fname
->st
)) {
8173 if (access_mask
!= SMB_O_RDONLY_MAPPING
) {
8174 return NT_STATUS_FILE_IS_A_DIRECTORY
;
8176 create_options
&= ~FILE_NON_DIRECTORY_FILE
;
8177 create_options
|= FILE_DIRECTORY_FILE
;
8180 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
8181 smb_fname_str_dbg(smb_fname
),
8182 (unsigned int)wire_open_mode
,
8183 (unsigned int)unixmode
));
8185 status
= SMB_VFS_CREATE_FILE(
8188 0, /* root_dir_fid */
8189 smb_fname
, /* fname */
8190 access_mask
, /* access_mask */
8191 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
8193 create_disp
, /* create_disposition*/
8194 create_options
, /* create_options */
8195 mod_unixmode
, /* file_attributes */
8196 oplock_request
, /* oplock_request */
8198 0, /* allocation_size */
8199 0, /* private_flags */
8204 NULL
, NULL
); /* create context */
8206 if (!NT_STATUS_IS_OK(status
)) {
8210 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
8211 extended_oplock_granted
= True
;
8214 if(oplock_request
&& EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
8215 extended_oplock_granted
= True
;
8218 info_level_return
= SVAL(pdata
,16);
8220 /* Allocate the correct return size. */
8222 if (info_level_return
== SMB_QUERY_FILE_UNIX_BASIC
) {
8223 *pdata_return_size
= 12 + SMB_FILE_UNIX_BASIC_SIZE
;
8224 } else if (info_level_return
== SMB_QUERY_FILE_UNIX_INFO2
) {
8225 *pdata_return_size
= 12 + SMB_FILE_UNIX_INFO2_SIZE
;
8227 *pdata_return_size
= 12;
8230 /* Realloc the data size */
8231 *ppdata
= (char *)SMB_REALLOC(*ppdata
,*pdata_return_size
);
8232 if (*ppdata
== NULL
) {
8233 close_file(req
, fsp
, ERROR_CLOSE
);
8234 *pdata_return_size
= 0;
8235 return NT_STATUS_NO_MEMORY
;
8239 if (extended_oplock_granted
) {
8240 if (flags
& REQUEST_BATCH_OPLOCK
) {
8241 SSVAL(pdata
,0, BATCH_OPLOCK_RETURN
);
8243 SSVAL(pdata
,0, EXCLUSIVE_OPLOCK_RETURN
);
8245 } else if (fsp
->oplock_type
== LEVEL_II_OPLOCK
) {
8246 SSVAL(pdata
,0, LEVEL_II_OPLOCK_RETURN
);
8248 SSVAL(pdata
,0,NO_OPLOCK_RETURN
);
8251 SSVAL(pdata
,2,fsp
->fnum
);
8252 SIVAL(pdata
,4,info
); /* Was file created etc. */
8254 switch (info_level_return
) {
8255 case SMB_QUERY_FILE_UNIX_BASIC
:
8256 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_BASIC
);
8257 SSVAL(pdata
,10,0); /* padding. */
8258 store_file_unix_basic(conn
, pdata
+ 12, fsp
,
8261 case SMB_QUERY_FILE_UNIX_INFO2
:
8262 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_INFO2
);
8263 SSVAL(pdata
,10,0); /* padding. */
8264 store_file_unix_basic_info2(conn
, pdata
+ 12, fsp
,
8268 SSVAL(pdata
,8,SMB_NO_INFO_LEVEL_RETURNED
);
8269 SSVAL(pdata
,10,0); /* padding. */
8272 return NT_STATUS_OK
;
8275 /****************************************************************************
8276 Delete a file with POSIX semantics.
8277 ****************************************************************************/
8279 static NTSTATUS
smb_posix_unlink(connection_struct
*conn
,
8280 struct smb_request
*req
,
8283 struct smb_filename
*smb_fname
)
8285 NTSTATUS status
= NT_STATUS_OK
;
8286 files_struct
*fsp
= NULL
;
8290 int create_options
= 0;
8292 struct share_mode_lock
*lck
= NULL
;
8294 if (total_data
< 2) {
8295 return NT_STATUS_INVALID_PARAMETER
;
8298 flags
= SVAL(pdata
,0);
8300 if (!VALID_STAT(smb_fname
->st
)) {
8301 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
8304 if ((flags
== SMB_POSIX_UNLINK_DIRECTORY_TARGET
) &&
8305 !VALID_STAT_OF_DIR(smb_fname
->st
)) {
8306 return NT_STATUS_NOT_A_DIRECTORY
;
8309 DEBUG(10,("smb_posix_unlink: %s %s\n",
8310 (flags
== SMB_POSIX_UNLINK_DIRECTORY_TARGET
) ? "directory" : "file",
8311 smb_fname_str_dbg(smb_fname
)));
8313 if (VALID_STAT_OF_DIR(smb_fname
->st
)) {
8314 create_options
|= FILE_DIRECTORY_FILE
;
8317 status
= SMB_VFS_CREATE_FILE(
8320 0, /* root_dir_fid */
8321 smb_fname
, /* fname */
8322 DELETE_ACCESS
, /* access_mask */
8323 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
8325 FILE_OPEN
, /* create_disposition*/
8326 create_options
, /* create_options */
8327 FILE_FLAG_POSIX_SEMANTICS
|0777, /* file_attributes */
8328 0, /* oplock_request */
8330 0, /* allocation_size */
8331 0, /* private_flags */
8336 NULL
, NULL
); /* create context */
8338 if (!NT_STATUS_IS_OK(status
)) {
8343 * Don't lie to client. If we can't really delete due to
8344 * non-POSIX opens return SHARING_VIOLATION.
8347 lck
= get_existing_share_mode_lock(talloc_tos(), fsp
->file_id
);
8349 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
8350 "lock for file %s\n", fsp_str_dbg(fsp
)));
8351 close_file(req
, fsp
, NORMAL_CLOSE
);
8352 return NT_STATUS_INVALID_PARAMETER
;
8356 * See if others still have the file open. If this is the case, then
8357 * don't delete. If all opens are POSIX delete we can set the delete
8358 * on close disposition.
8360 for (i
=0; i
<lck
->data
->num_share_modes
; i
++) {
8361 struct share_mode_entry
*e
= &lck
->data
->share_modes
[i
];
8362 if (is_valid_share_mode_entry(e
)) {
8363 if (e
->flags
& SHARE_MODE_FLAG_POSIX_OPEN
) {
8366 if (share_mode_stale_pid(lck
->data
, i
)) {
8369 /* Fail with sharing violation. */
8371 close_file(req
, fsp
, NORMAL_CLOSE
);
8372 return NT_STATUS_SHARING_VIOLATION
;
8377 * Set the delete on close.
8379 status
= smb_set_file_disposition_info(conn
,
8387 if (!NT_STATUS_IS_OK(status
)) {
8388 close_file(req
, fsp
, NORMAL_CLOSE
);
8391 return close_file(req
, fsp
, NORMAL_CLOSE
);
8394 NTSTATUS
smbd_do_setfilepathinfo(connection_struct
*conn
,
8395 struct smb_request
*req
,
8396 TALLOC_CTX
*mem_ctx
,
8397 uint16_t info_level
,
8399 struct smb_filename
*smb_fname
,
8400 char **ppdata
, int total_data
,
8403 char *pdata
= *ppdata
;
8404 NTSTATUS status
= NT_STATUS_OK
;
8405 int data_return_size
= 0;
8409 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
8410 return NT_STATUS_INVALID_LEVEL
;
8413 if (!CAN_WRITE(conn
)) {
8414 /* Allow POSIX opens. The open path will deny
8415 * any non-readonly opens. */
8416 if (info_level
!= SMB_POSIX_PATH_OPEN
) {
8417 return NT_STATUS_DOS(ERRSRV
, ERRaccess
);
8421 DEBUG(3,("smbd_do_setfilepathinfo: %s (%s) info_level=%d "
8422 "totdata=%d\n", smb_fname_str_dbg(smb_fname
),
8424 info_level
, total_data
));
8426 switch (info_level
) {
8428 case SMB_INFO_STANDARD
:
8430 status
= smb_set_info_standard(conn
,
8438 case SMB_INFO_SET_EA
:
8440 status
= smb_info_set_ea(conn
,
8448 case SMB_SET_FILE_BASIC_INFO
:
8449 case SMB_FILE_BASIC_INFORMATION
:
8451 status
= smb_set_file_basic_info(conn
,
8459 case SMB_FILE_ALLOCATION_INFORMATION
:
8460 case SMB_SET_FILE_ALLOCATION_INFO
:
8462 status
= smb_set_file_allocation_info(conn
, req
,
8470 case SMB_FILE_END_OF_FILE_INFORMATION
:
8471 case SMB_SET_FILE_END_OF_FILE_INFO
:
8474 * XP/Win7 both fail after the createfile with
8475 * SMB_SET_FILE_END_OF_FILE_INFO but not
8476 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
8477 * The level is known here, so pass it down
8481 (info_level
== SMB_SET_FILE_END_OF_FILE_INFO
);
8483 status
= smb_set_file_end_of_file_info(conn
, req
,
8492 case SMB_FILE_DISPOSITION_INFORMATION
:
8493 case SMB_SET_FILE_DISPOSITION_INFO
: /* Set delete on close for open file. */
8496 /* JRA - We used to just ignore this on a path ?
8497 * Shouldn't this be invalid level on a pathname
8500 if (tran_call
!= TRANSACT2_SETFILEINFO
) {
8501 return ERROR_NT(NT_STATUS_INVALID_LEVEL
);
8504 status
= smb_set_file_disposition_info(conn
,
8512 case SMB_FILE_POSITION_INFORMATION
:
8514 status
= smb_file_position_information(conn
,
8521 case SMB_FILE_FULL_EA_INFORMATION
:
8523 status
= smb_set_file_full_ea_info(conn
,
8530 /* From tridge Samba4 :
8531 * MODE_INFORMATION in setfileinfo (I have no
8532 * idea what "mode information" on a file is - it takes a value of 0,
8533 * 2, 4 or 6. What could it be?).
8536 case SMB_FILE_MODE_INFORMATION
:
8538 status
= smb_file_mode_information(conn
,
8545 * CIFS UNIX extensions.
8548 case SMB_SET_FILE_UNIX_BASIC
:
8550 status
= smb_set_file_unix_basic(conn
, req
,
8558 case SMB_SET_FILE_UNIX_INFO2
:
8560 status
= smb_set_file_unix_info2(conn
, req
,
8568 case SMB_SET_FILE_UNIX_LINK
:
8571 /* We must have a pathname for this. */
8572 return NT_STATUS_INVALID_LEVEL
;
8574 status
= smb_set_file_unix_link(conn
, req
, pdata
,
8575 total_data
, smb_fname
);
8579 case SMB_SET_FILE_UNIX_HLINK
:
8582 /* We must have a pathname for this. */
8583 return NT_STATUS_INVALID_LEVEL
;
8585 status
= smb_set_file_unix_hlink(conn
, req
,
8591 case SMB_FILE_RENAME_INFORMATION
:
8593 status
= smb_file_rename_information(conn
, req
,
8599 case SMB2_FILE_RENAME_INFORMATION_INTERNAL
:
8601 /* SMB2 rename information. */
8602 status
= smb2_file_rename_information(conn
, req
,
8608 case SMB_FILE_LINK_INFORMATION
:
8610 status
= smb_file_link_information(conn
, req
,
8616 #if defined(HAVE_POSIX_ACLS)
8617 case SMB_SET_POSIX_ACL
:
8619 status
= smb_set_posix_acl(conn
,
8628 case SMB_SET_POSIX_LOCK
:
8631 return NT_STATUS_INVALID_LEVEL
;
8633 status
= smb_set_posix_lock(conn
, req
,
8634 pdata
, total_data
, fsp
);
8638 case SMB_POSIX_PATH_OPEN
:
8641 /* We must have a pathname for this. */
8642 return NT_STATUS_INVALID_LEVEL
;
8645 status
= smb_posix_open(conn
, req
,
8653 case SMB_POSIX_PATH_UNLINK
:
8656 /* We must have a pathname for this. */
8657 return NT_STATUS_INVALID_LEVEL
;
8660 status
= smb_posix_unlink(conn
, req
,
8668 return NT_STATUS_INVALID_LEVEL
;
8671 if (!NT_STATUS_IS_OK(status
)) {
8675 *ret_data_size
= data_return_size
;
8676 return NT_STATUS_OK
;
8679 /****************************************************************************
8680 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
8681 ****************************************************************************/
8683 static void call_trans2setfilepathinfo(connection_struct
*conn
,
8684 struct smb_request
*req
,
8685 unsigned int tran_call
,
8686 char **pparams
, int total_params
,
8687 char **ppdata
, int total_data
,
8688 unsigned int max_data_bytes
)
8690 char *params
= *pparams
;
8691 char *pdata
= *ppdata
;
8692 uint16_t info_level
;
8693 struct smb_filename
*smb_fname
= NULL
;
8694 files_struct
*fsp
= NULL
;
8695 NTSTATUS status
= NT_STATUS_OK
;
8696 int data_return_size
= 0;
8699 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8703 if (tran_call
== TRANSACT2_SETFILEINFO
) {
8704 if (total_params
< 4) {
8705 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8709 fsp
= file_fsp(req
, SVAL(params
,0));
8710 /* Basic check for non-null fsp. */
8711 if (!check_fsp_open(conn
, req
, fsp
)) {
8714 info_level
= SVAL(params
,2);
8716 smb_fname
= cp_smb_filename(talloc_tos(), fsp
->fsp_name
);
8717 if (smb_fname
== NULL
) {
8718 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8722 if(fsp
->fh
->fd
== -1) {
8724 * This is actually a SETFILEINFO on a directory
8725 * handle (returned from an NT SMB). NT5.0 seems
8726 * to do this call. JRA.
8728 if (INFO_LEVEL_IS_UNIX(info_level
)) {
8729 /* Always do lstat for UNIX calls. */
8730 if (SMB_VFS_LSTAT(conn
, smb_fname
)) {
8731 DEBUG(3,("call_trans2setfilepathinfo: "
8732 "SMB_VFS_LSTAT of %s failed "
8734 smb_fname_str_dbg(smb_fname
),
8736 reply_nterror(req
, map_nt_error_from_unix(errno
));
8740 if (SMB_VFS_STAT(conn
, smb_fname
) != 0) {
8741 DEBUG(3,("call_trans2setfilepathinfo: "
8742 "fileinfo of %s failed (%s)\n",
8743 smb_fname_str_dbg(smb_fname
),
8745 reply_nterror(req
, map_nt_error_from_unix(errno
));
8749 } else if (fsp
->print_file
) {
8751 * Doing a DELETE_ON_CLOSE should cancel a print job.
8753 if ((info_level
== SMB_SET_FILE_DISPOSITION_INFO
) && CVAL(pdata
,0)) {
8754 fsp
->fh
->private_options
|= NTCREATEX_OPTIONS_PRIVATE_DELETE_ON_CLOSE
;
8756 DEBUG(3,("call_trans2setfilepathinfo: "
8757 "Cancelling print job (%s)\n",
8761 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 2,
8767 NT_STATUS_OBJECT_PATH_NOT_FOUND
);
8772 * Original code - this is an open file.
8774 if (SMB_VFS_FSTAT(fsp
, &smb_fname
->st
) != 0) {
8775 DEBUG(3,("call_trans2setfilepathinfo: fstat "
8776 "of %s failed (%s)\n", fsp_fnum_dbg(fsp
),
8778 reply_nterror(req
, map_nt_error_from_unix(errno
));
8784 uint32_t ucf_flags
= ucf_flags_from_smb_request(req
);
8787 if (total_params
< 7) {
8788 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8792 info_level
= SVAL(params
,0);
8793 if (req
->posix_pathnames
) {
8794 srvstr_get_path_posix(req
,
8803 srvstr_get_path(req
,
8812 if (!NT_STATUS_IS_OK(status
)) {
8813 reply_nterror(req
, status
);
8817 if (info_level
== SMB_SET_FILE_UNIX_BASIC
||
8818 info_level
== SMB_SET_FILE_UNIX_INFO2
||
8819 info_level
== SMB_FILE_RENAME_INFORMATION
||
8820 info_level
== SMB_POSIX_PATH_UNLINK
) {
8821 ucf_flags
|= UCF_UNIX_NAME_LOOKUP
;
8824 status
= filename_convert(req
, conn
,
8829 if (!NT_STATUS_IS_OK(status
)) {
8830 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
8831 reply_botherror(req
,
8832 NT_STATUS_PATH_NOT_COVERED
,
8833 ERRSRV
, ERRbadpath
);
8836 reply_nterror(req
, status
);
8840 if (INFO_LEVEL_IS_UNIX(info_level
)) {
8842 * For CIFS UNIX extensions the target name may not exist.
8845 /* Always do lstat for UNIX calls. */
8846 SMB_VFS_LSTAT(conn
, smb_fname
);
8848 } else if (!VALID_STAT(smb_fname
->st
) &&
8849 SMB_VFS_STAT(conn
, smb_fname
)) {
8850 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
8852 smb_fname_str_dbg(smb_fname
),
8854 reply_nterror(req
, map_nt_error_from_unix(errno
));
8859 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (%s) info_level=%d "
8860 "totdata=%d\n", tran_call
, smb_fname_str_dbg(smb_fname
),
8862 info_level
,total_data
));
8864 /* Realloc the parameter size */
8865 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
8866 if (*pparams
== NULL
) {
8867 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8874 status
= smbd_do_setfilepathinfo(conn
, req
, req
,
8880 if (!NT_STATUS_IS_OK(status
)) {
8881 if (open_was_deferred(req
->xconn
, req
->mid
)) {
8882 /* We have re-scheduled this call. */
8885 if (blocking_lock_was_deferred_smb1(req
->sconn
, req
->mid
)) {
8886 /* We have re-scheduled this call. */
8889 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
8890 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
8891 ERRSRV
, ERRbadpath
);
8894 if (info_level
== SMB_POSIX_PATH_OPEN
) {
8895 reply_openerror(req
, status
);
8900 * Invalid EA name needs to return 2 param bytes,
8901 * not a zero-length error packet.
8903 if (NT_STATUS_EQUAL(status
, STATUS_INVALID_EA_NAME
)) {
8904 send_trans2_replies(conn
, req
, status
, params
, 2, NULL
, 0,
8907 reply_nterror(req
, status
);
8912 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 2, *ppdata
, data_return_size
,
8918 /****************************************************************************
8919 Reply to a TRANS2_MKDIR (make directory with extended attributes).
8920 ****************************************************************************/
8922 static void call_trans2mkdir(connection_struct
*conn
, struct smb_request
*req
,
8923 char **pparams
, int total_params
,
8924 char **ppdata
, int total_data
,
8925 unsigned int max_data_bytes
)
8927 struct smb_filename
*smb_dname
= NULL
;
8928 char *params
= *pparams
;
8929 char *pdata
= *ppdata
;
8930 char *directory
= NULL
;
8931 NTSTATUS status
= NT_STATUS_OK
;
8932 struct ea_list
*ea_list
= NULL
;
8933 uint32_t ucf_flags
= ucf_flags_from_smb_request(req
);
8934 TALLOC_CTX
*ctx
= talloc_tos();
8936 if (!CAN_WRITE(conn
)) {
8937 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
8941 if (total_params
< 5) {
8942 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8946 if (req
->posix_pathnames
) {
8947 srvstr_get_path_posix(ctx
,
8956 srvstr_get_path(ctx
,
8965 if (!NT_STATUS_IS_OK(status
)) {
8966 reply_nterror(req
, status
);
8970 DEBUG(3,("call_trans2mkdir : name = %s\n", directory
));
8972 status
= filename_convert(ctx
,
8979 if (!NT_STATUS_IS_OK(status
)) {
8980 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
8981 reply_botherror(req
,
8982 NT_STATUS_PATH_NOT_COVERED
,
8983 ERRSRV
, ERRbadpath
);
8986 reply_nterror(req
, status
);
8991 * OS/2 workplace shell seems to send SET_EA requests of "null"
8992 * length (4 bytes containing IVAL 4).
8993 * They seem to have no effect. Bug #3212. JRA.
8996 if (total_data
&& (total_data
!= 4)) {
8997 /* Any data in this call is an EA list. */
8998 if (total_data
< 10) {
8999 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
9003 if (IVAL(pdata
,0) > total_data
) {
9004 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
9005 IVAL(pdata
,0), (unsigned int)total_data
));
9006 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
9010 ea_list
= read_ea_list(talloc_tos(), pdata
+ 4,
9013 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
9017 if (!lp_ea_support(SNUM(conn
))) {
9018 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
9022 /* If total_data == 4 Windows doesn't care what values
9023 * are placed in that field, it just ignores them.
9024 * The System i QNTC IBM SMB client puts bad values here,
9025 * so ignore them. */
9027 status
= create_directory(conn
, req
, smb_dname
);
9029 if (!NT_STATUS_IS_OK(status
)) {
9030 reply_nterror(req
, status
);
9034 /* Try and set any given EA. */
9036 status
= set_ea(conn
, NULL
, smb_dname
, ea_list
);
9037 if (!NT_STATUS_IS_OK(status
)) {
9038 reply_nterror(req
, status
);
9043 /* Realloc the parameter and data sizes */
9044 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
9045 if(*pparams
== NULL
) {
9046 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
9053 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 2, *ppdata
, 0, max_data_bytes
);
9056 TALLOC_FREE(smb_dname
);
9060 /****************************************************************************
9061 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
9062 We don't actually do this - we just send a null response.
9063 ****************************************************************************/
9065 static void call_trans2findnotifyfirst(connection_struct
*conn
,
9066 struct smb_request
*req
,
9067 char **pparams
, int total_params
,
9068 char **ppdata
, int total_data
,
9069 unsigned int max_data_bytes
)
9071 char *params
= *pparams
;
9072 uint16_t info_level
;
9074 if (total_params
< 6) {
9075 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
9079 info_level
= SVAL(params
,4);
9080 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level
));
9082 switch (info_level
) {
9087 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
9091 /* Realloc the parameter and data sizes */
9092 *pparams
= (char *)SMB_REALLOC(*pparams
,6);
9093 if (*pparams
== NULL
) {
9094 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
9099 SSVAL(params
,0,fnf_handle
);
9100 SSVAL(params
,2,0); /* No changes */
9101 SSVAL(params
,4,0); /* No EA errors */
9108 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 6, *ppdata
, 0, max_data_bytes
);
9113 /****************************************************************************
9114 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
9115 changes). Currently this does nothing.
9116 ****************************************************************************/
9118 static void call_trans2findnotifynext(connection_struct
*conn
,
9119 struct smb_request
*req
,
9120 char **pparams
, int total_params
,
9121 char **ppdata
, int total_data
,
9122 unsigned int max_data_bytes
)
9124 char *params
= *pparams
;
9126 DEBUG(3,("call_trans2findnotifynext\n"));
9128 /* Realloc the parameter and data sizes */
9129 *pparams
= (char *)SMB_REALLOC(*pparams
,4);
9130 if (*pparams
== NULL
) {
9131 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
9136 SSVAL(params
,0,0); /* No changes */
9137 SSVAL(params
,2,0); /* No EA errors */
9139 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 4, *ppdata
, 0, max_data_bytes
);
9144 /****************************************************************************
9145 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
9146 ****************************************************************************/
9148 static void call_trans2getdfsreferral(connection_struct
*conn
,
9149 struct smb_request
*req
,
9150 char **pparams
, int total_params
,
9151 char **ppdata
, int total_data
,
9152 unsigned int max_data_bytes
)
9154 char *params
= *pparams
;
9155 char *pathname
= NULL
;
9157 int max_referral_level
;
9158 NTSTATUS status
= NT_STATUS_OK
;
9159 TALLOC_CTX
*ctx
= talloc_tos();
9161 DEBUG(10,("call_trans2getdfsreferral\n"));
9163 if (total_params
< 3) {
9164 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
9168 max_referral_level
= SVAL(params
,0);
9170 if(!lp_host_msdfs()) {
9171 reply_nterror(req
, NT_STATUS_NOT_IMPLEMENTED
);
9175 srvstr_pull_talloc(ctx
, params
, req
->flags2
, &pathname
, ¶ms
[2],
9176 total_params
- 2, STR_TERMINATE
);
9178 reply_nterror(req
, NT_STATUS_NOT_FOUND
);
9181 if((reply_size
= setup_dfs_referral(conn
, pathname
, max_referral_level
,
9182 ppdata
,&status
)) < 0) {
9183 reply_nterror(req
, status
);
9187 SSVAL((discard_const_p(uint8_t, req
->inbuf
)), smb_flg2
,
9188 SVAL(req
->inbuf
,smb_flg2
) | FLAGS2_DFS_PATHNAMES
);
9189 send_trans2_replies(conn
, req
, NT_STATUS_OK
, 0,0,*ppdata
,reply_size
, max_data_bytes
);
9194 #define LMCAT_SPL 0x53
9195 #define LMFUNC_GETJOBID 0x60
9197 /****************************************************************************
9198 Reply to a TRANS2_IOCTL - used for OS/2 printing.
9199 ****************************************************************************/
9201 static void call_trans2ioctl(connection_struct
*conn
,
9202 struct smb_request
*req
,
9203 char **pparams
, int total_params
,
9204 char **ppdata
, int total_data
,
9205 unsigned int max_data_bytes
)
9207 char *pdata
= *ppdata
;
9208 files_struct
*fsp
= file_fsp(req
, SVAL(req
->vwv
+15, 0));
9212 /* check for an invalid fid before proceeding */
9215 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
9219 if ((SVAL(req
->vwv
+16, 0) == LMCAT_SPL
)
9220 && (SVAL(req
->vwv
+17, 0) == LMFUNC_GETJOBID
)) {
9221 *ppdata
= (char *)SMB_REALLOC(*ppdata
, 32);
9222 if (*ppdata
== NULL
) {
9223 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
9228 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
9229 CAN ACCEPT THIS IN UNICODE. JRA. */
9232 SSVAL(pdata
, 0, print_spool_rap_jobid(fsp
->print_file
));
9234 status
= srvstr_push(pdata
, req
->flags2
, pdata
+ 2,
9235 lp_netbios_name(), 15,
9236 STR_ASCII
|STR_TERMINATE
, &len
); /* Our NetBIOS name */
9237 if (!NT_STATUS_IS_OK(status
)) {
9238 reply_nterror(req
, status
);
9241 status
= srvstr_push(pdata
, req
->flags2
, pdata
+18,
9242 lp_servicename(talloc_tos(), SNUM(conn
)), 13,
9243 STR_ASCII
|STR_TERMINATE
, &len
); /* Service name */
9244 if (!NT_STATUS_IS_OK(status
)) {
9245 reply_nterror(req
, status
);
9248 send_trans2_replies(conn
, req
, NT_STATUS_OK
, *pparams
, 0, *ppdata
, 32,
9253 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
9254 reply_nterror(req
, NT_STATUS_NOT_IMPLEMENTED
);
9257 /****************************************************************************
9258 Reply to a SMBfindclose (stop trans2 directory search).
9259 ****************************************************************************/
9261 void reply_findclose(struct smb_request
*req
)
9264 struct smbd_server_connection
*sconn
= req
->sconn
;
9266 START_PROFILE(SMBfindclose
);
9269 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
9270 END_PROFILE(SMBfindclose
);
9274 dptr_num
= SVALS(req
->vwv
+0, 0);
9276 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num
));
9278 dptr_close(sconn
, &dptr_num
);
9280 reply_outbuf(req
, 0, 0);
9282 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num
));
9284 END_PROFILE(SMBfindclose
);
9288 /****************************************************************************
9289 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
9290 ****************************************************************************/
9292 void reply_findnclose(struct smb_request
*req
)
9296 START_PROFILE(SMBfindnclose
);
9299 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
9300 END_PROFILE(SMBfindnclose
);
9304 dptr_num
= SVAL(req
->vwv
+0, 0);
9306 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num
));
9308 /* We never give out valid handles for a
9309 findnotifyfirst - so any dptr_num is ok here.
9312 reply_outbuf(req
, 0, 0);
9314 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num
));
9316 END_PROFILE(SMBfindnclose
);
9320 static void handle_trans2(connection_struct
*conn
, struct smb_request
*req
,
9321 struct trans_state
*state
)
9323 if (get_Protocol() >= PROTOCOL_NT1
) {
9324 req
->flags2
|= 0x40; /* IS_LONG_NAME */
9325 SSVAL((discard_const_p(uint8_t, req
->inbuf
)),smb_flg2
,req
->flags2
);
9328 if (ENCRYPTION_REQUIRED(conn
) && !req
->encrypted
) {
9329 if (state
->call
!= TRANSACT2_QFSINFO
&&
9330 state
->call
!= TRANSACT2_SETFSINFO
) {
9331 DEBUG(0,("handle_trans2: encryption required "
9333 (unsigned int)state
->call
));
9334 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
9339 SMB_PERFCOUNT_SET_SUBOP(&req
->pcd
, state
->call
);
9341 /* Now we must call the relevant TRANS2 function */
9342 switch(state
->call
) {
9343 case TRANSACT2_OPEN
:
9345 START_PROFILE(Trans2_open
);
9346 call_trans2open(conn
, req
,
9347 &state
->param
, state
->total_param
,
9348 &state
->data
, state
->total_data
,
9349 state
->max_data_return
);
9350 END_PROFILE(Trans2_open
);
9354 case TRANSACT2_FINDFIRST
:
9356 START_PROFILE(Trans2_findfirst
);
9357 call_trans2findfirst(conn
, req
,
9358 &state
->param
, state
->total_param
,
9359 &state
->data
, state
->total_data
,
9360 state
->max_data_return
);
9361 END_PROFILE(Trans2_findfirst
);
9365 case TRANSACT2_FINDNEXT
:
9367 START_PROFILE(Trans2_findnext
);
9368 call_trans2findnext(conn
, req
,
9369 &state
->param
, state
->total_param
,
9370 &state
->data
, state
->total_data
,
9371 state
->max_data_return
);
9372 END_PROFILE(Trans2_findnext
);
9376 case TRANSACT2_QFSINFO
:
9378 START_PROFILE(Trans2_qfsinfo
);
9379 call_trans2qfsinfo(conn
, req
,
9380 &state
->param
, state
->total_param
,
9381 &state
->data
, state
->total_data
,
9382 state
->max_data_return
);
9383 END_PROFILE(Trans2_qfsinfo
);
9387 case TRANSACT2_SETFSINFO
:
9389 START_PROFILE(Trans2_setfsinfo
);
9390 call_trans2setfsinfo(conn
, req
,
9391 &state
->param
, state
->total_param
,
9392 &state
->data
, state
->total_data
,
9393 state
->max_data_return
);
9394 END_PROFILE(Trans2_setfsinfo
);
9398 case TRANSACT2_QPATHINFO
:
9399 case TRANSACT2_QFILEINFO
:
9401 START_PROFILE(Trans2_qpathinfo
);
9402 call_trans2qfilepathinfo(conn
, req
, state
->call
,
9403 &state
->param
, state
->total_param
,
9404 &state
->data
, state
->total_data
,
9405 state
->max_data_return
);
9406 END_PROFILE(Trans2_qpathinfo
);
9410 case TRANSACT2_SETPATHINFO
:
9411 case TRANSACT2_SETFILEINFO
:
9413 START_PROFILE(Trans2_setpathinfo
);
9414 call_trans2setfilepathinfo(conn
, req
, state
->call
,
9415 &state
->param
, state
->total_param
,
9416 &state
->data
, state
->total_data
,
9417 state
->max_data_return
);
9418 END_PROFILE(Trans2_setpathinfo
);
9422 case TRANSACT2_FINDNOTIFYFIRST
:
9424 START_PROFILE(Trans2_findnotifyfirst
);
9425 call_trans2findnotifyfirst(conn
, req
,
9426 &state
->param
, state
->total_param
,
9427 &state
->data
, state
->total_data
,
9428 state
->max_data_return
);
9429 END_PROFILE(Trans2_findnotifyfirst
);
9433 case TRANSACT2_FINDNOTIFYNEXT
:
9435 START_PROFILE(Trans2_findnotifynext
);
9436 call_trans2findnotifynext(conn
, req
,
9437 &state
->param
, state
->total_param
,
9438 &state
->data
, state
->total_data
,
9439 state
->max_data_return
);
9440 END_PROFILE(Trans2_findnotifynext
);
9444 case TRANSACT2_MKDIR
:
9446 START_PROFILE(Trans2_mkdir
);
9447 call_trans2mkdir(conn
, req
,
9448 &state
->param
, state
->total_param
,
9449 &state
->data
, state
->total_data
,
9450 state
->max_data_return
);
9451 END_PROFILE(Trans2_mkdir
);
9455 case TRANSACT2_GET_DFS_REFERRAL
:
9457 START_PROFILE(Trans2_get_dfs_referral
);
9458 call_trans2getdfsreferral(conn
, req
,
9459 &state
->param
, state
->total_param
,
9460 &state
->data
, state
->total_data
,
9461 state
->max_data_return
);
9462 END_PROFILE(Trans2_get_dfs_referral
);
9466 case TRANSACT2_IOCTL
:
9468 START_PROFILE(Trans2_ioctl
);
9469 call_trans2ioctl(conn
, req
,
9470 &state
->param
, state
->total_param
,
9471 &state
->data
, state
->total_data
,
9472 state
->max_data_return
);
9473 END_PROFILE(Trans2_ioctl
);
9478 /* Error in request */
9479 DEBUG(2,("Unknown request %d in trans2 call\n", state
->call
));
9480 reply_nterror(req
, NT_STATUS_NOT_IMPLEMENTED
);
9484 /****************************************************************************
9485 Reply to a SMBtrans2.
9486 ****************************************************************************/
9488 void reply_trans2(struct smb_request
*req
)
9490 connection_struct
*conn
= req
->conn
;
9495 unsigned int tran_call
;
9496 struct trans_state
*state
;
9499 START_PROFILE(SMBtrans2
);
9501 if (req
->wct
< 14) {
9502 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
9503 END_PROFILE(SMBtrans2
);
9507 dsoff
= SVAL(req
->vwv
+12, 0);
9508 dscnt
= SVAL(req
->vwv
+11, 0);
9509 psoff
= SVAL(req
->vwv
+10, 0);
9510 pscnt
= SVAL(req
->vwv
+9, 0);
9511 tran_call
= SVAL(req
->vwv
+14, 0);
9513 result
= allow_new_trans(conn
->pending_trans
, req
->mid
);
9514 if (!NT_STATUS_IS_OK(result
)) {
9515 DEBUG(2, ("Got invalid trans2 request: %s\n",
9516 nt_errstr(result
)));
9517 reply_nterror(req
, result
);
9518 END_PROFILE(SMBtrans2
);
9523 switch (tran_call
) {
9524 /* List the allowed trans2 calls on IPC$ */
9525 case TRANSACT2_OPEN
:
9526 case TRANSACT2_GET_DFS_REFERRAL
:
9527 case TRANSACT2_QFILEINFO
:
9528 case TRANSACT2_QFSINFO
:
9529 case TRANSACT2_SETFSINFO
:
9532 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
9533 END_PROFILE(SMBtrans2
);
9538 if ((state
= talloc(conn
, struct trans_state
)) == NULL
) {
9539 DEBUG(0, ("talloc failed\n"));
9540 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
9541 END_PROFILE(SMBtrans2
);
9545 state
->cmd
= SMBtrans2
;
9547 state
->mid
= req
->mid
;
9548 state
->vuid
= req
->vuid
;
9549 state
->setup_count
= SVAL(req
->vwv
+13, 0);
9550 state
->setup
= NULL
;
9551 state
->total_param
= SVAL(req
->vwv
+0, 0);
9552 state
->param
= NULL
;
9553 state
->total_data
= SVAL(req
->vwv
+1, 0);
9555 state
->max_param_return
= SVAL(req
->vwv
+2, 0);
9556 state
->max_data_return
= SVAL(req
->vwv
+3, 0);
9557 state
->max_setup_return
= SVAL(req
->vwv
+4, 0);
9558 state
->close_on_completion
= BITSETW(req
->vwv
+5, 0);
9559 state
->one_way
= BITSETW(req
->vwv
+5, 1);
9561 state
->call
= tran_call
;
9563 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
9564 is so as a sanity check */
9565 if (state
->setup_count
!= 1) {
9567 * Need to have rc=0 for ioctl to get job id for OS/2.
9568 * Network printing will fail if function is not successful.
9569 * Similar function in reply.c will be used if protocol
9570 * is LANMAN1.0 instead of LM1.2X002.
9571 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
9572 * outbuf doesn't have to be set(only job id is used).
9574 if ( (state
->setup_count
== 4)
9575 && (tran_call
== TRANSACT2_IOCTL
)
9576 && (SVAL(req
->vwv
+16, 0) == LMCAT_SPL
)
9577 && (SVAL(req
->vwv
+17, 0) == LMFUNC_GETJOBID
)) {
9578 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
9580 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state
->setup_count
));
9581 DEBUG(2,("Transaction is %d\n",tran_call
));
9583 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
9584 END_PROFILE(SMBtrans2
);
9589 if ((dscnt
> state
->total_data
) || (pscnt
> state
->total_param
))
9592 if (state
->total_data
) {
9594 if (trans_oob(state
->total_data
, 0, dscnt
)
9595 || trans_oob(smb_len(req
->inbuf
), dsoff
, dscnt
)) {
9599 /* Can't use talloc here, the core routines do realloc on the
9600 * params and data. */
9601 state
->data
= (char *)SMB_MALLOC(state
->total_data
);
9602 if (state
->data
== NULL
) {
9603 DEBUG(0,("reply_trans2: data malloc fail for %u "
9604 "bytes !\n", (unsigned int)state
->total_data
));
9606 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
9607 END_PROFILE(SMBtrans2
);
9611 memcpy(state
->data
,smb_base(req
->inbuf
)+dsoff
,dscnt
);
9614 if (state
->total_param
) {
9616 if (trans_oob(state
->total_param
, 0, pscnt
)
9617 || trans_oob(smb_len(req
->inbuf
), psoff
, pscnt
)) {
9621 /* Can't use talloc here, the core routines do realloc on the
9622 * params and data. */
9623 state
->param
= (char *)SMB_MALLOC(state
->total_param
);
9624 if (state
->param
== NULL
) {
9625 DEBUG(0,("reply_trans: param malloc fail for %u "
9626 "bytes !\n", (unsigned int)state
->total_param
));
9627 SAFE_FREE(state
->data
);
9629 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
9630 END_PROFILE(SMBtrans2
);
9634 memcpy(state
->param
,smb_base(req
->inbuf
)+psoff
,pscnt
);
9637 state
->received_data
= dscnt
;
9638 state
->received_param
= pscnt
;
9640 if ((state
->received_param
== state
->total_param
) &&
9641 (state
->received_data
== state
->total_data
)) {
9643 handle_trans2(conn
, req
, state
);
9645 SAFE_FREE(state
->data
);
9646 SAFE_FREE(state
->param
);
9648 END_PROFILE(SMBtrans2
);
9652 DLIST_ADD(conn
->pending_trans
, state
);
9654 /* We need to send an interim response then receive the rest
9655 of the parameter/data bytes */
9656 reply_outbuf(req
, 0, 0);
9657 show_msg((char *)req
->outbuf
);
9658 END_PROFILE(SMBtrans2
);
9663 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
9664 SAFE_FREE(state
->data
);
9665 SAFE_FREE(state
->param
);
9667 END_PROFILE(SMBtrans2
);
9668 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
9672 /****************************************************************************
9673 Reply to a SMBtranss2
9674 ****************************************************************************/
9676 void reply_transs2(struct smb_request
*req
)
9678 connection_struct
*conn
= req
->conn
;
9679 unsigned int pcnt
,poff
,dcnt
,doff
,pdisp
,ddisp
;
9680 struct trans_state
*state
;
9682 START_PROFILE(SMBtranss2
);
9684 show_msg((const char *)req
->inbuf
);
9686 /* Windows clients expect all replies to
9687 a transact secondary (SMBtranss2 0x33)
9688 to have a command code of transact
9689 (SMBtrans2 0x32). See bug #8989
9690 and also [MS-CIFS] section 2.2.4.47.2
9693 req
->cmd
= SMBtrans2
;
9696 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
9697 END_PROFILE(SMBtranss2
);
9701 for (state
= conn
->pending_trans
; state
!= NULL
;
9702 state
= state
->next
) {
9703 if (state
->mid
== req
->mid
) {
9708 if ((state
== NULL
) || (state
->cmd
!= SMBtrans2
)) {
9709 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
9710 END_PROFILE(SMBtranss2
);
9714 /* Revise state->total_param and state->total_data in case they have
9715 changed downwards */
9717 if (SVAL(req
->vwv
+0, 0) < state
->total_param
)
9718 state
->total_param
= SVAL(req
->vwv
+0, 0);
9719 if (SVAL(req
->vwv
+1, 0) < state
->total_data
)
9720 state
->total_data
= SVAL(req
->vwv
+1, 0);
9722 pcnt
= SVAL(req
->vwv
+2, 0);
9723 poff
= SVAL(req
->vwv
+3, 0);
9724 pdisp
= SVAL(req
->vwv
+4, 0);
9726 dcnt
= SVAL(req
->vwv
+5, 0);
9727 doff
= SVAL(req
->vwv
+6, 0);
9728 ddisp
= SVAL(req
->vwv
+7, 0);
9730 state
->received_param
+= pcnt
;
9731 state
->received_data
+= dcnt
;
9733 if ((state
->received_data
> state
->total_data
) ||
9734 (state
->received_param
> state
->total_param
))
9738 if (trans_oob(state
->total_param
, pdisp
, pcnt
)
9739 || trans_oob(smb_len(req
->inbuf
), poff
, pcnt
)) {
9742 memcpy(state
->param
+pdisp
,smb_base(req
->inbuf
)+poff
,pcnt
);
9746 if (trans_oob(state
->total_data
, ddisp
, dcnt
)
9747 || trans_oob(smb_len(req
->inbuf
), doff
, dcnt
)) {
9750 memcpy(state
->data
+ddisp
, smb_base(req
->inbuf
)+doff
,dcnt
);
9753 if ((state
->received_param
< state
->total_param
) ||
9754 (state
->received_data
< state
->total_data
)) {
9755 END_PROFILE(SMBtranss2
);
9759 handle_trans2(conn
, req
, state
);
9761 DLIST_REMOVE(conn
->pending_trans
, state
);
9762 SAFE_FREE(state
->data
);
9763 SAFE_FREE(state
->param
);
9766 END_PROFILE(SMBtranss2
);
9771 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
9772 DLIST_REMOVE(conn
->pending_trans
, state
);
9773 SAFE_FREE(state
->data
);
9774 SAFE_FREE(state
->param
);
9776 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
9777 END_PROFILE(SMBtranss2
);