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 pathname 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
;
71 int ret
= vfs_stat_smb_basename(conn
,
75 return map_nt_error_from_unix(errno
);
79 if (S_ISLNK(pst
->st_ex_mode
)) {
80 return NT_STATUS_ACCESS_DENIED
;
85 NTSTATUS
check_access_fsp(const struct files_struct
*fsp
,
88 if (!(fsp
->access_mask
& access_mask
)) {
89 return NT_STATUS_ACCESS_DENIED
;
94 /********************************************************************
95 The canonical "check access" based on object handle or path function.
96 ********************************************************************/
98 NTSTATUS
check_access(connection_struct
*conn
,
100 const struct smb_filename
*smb_fname
,
101 uint32_t access_mask
)
106 status
= check_access_fsp(fsp
, access_mask
);
108 status
= smbd_check_access_rights(conn
, smb_fname
,
115 /********************************************************************
116 Roundup a value to the nearest allocation roundup size boundary.
117 Only do this for Windows clients.
118 ********************************************************************/
120 uint64_t smb_roundup(connection_struct
*conn
, uint64_t val
)
122 uint64_t rval
= lp_allocation_roundup_size(SNUM(conn
));
124 /* Only roundup for Windows clients. */
125 enum remote_arch_types ra_type
= get_remote_arch();
126 if (rval
&& (ra_type
!= RA_SAMBA
) && (ra_type
!= RA_CIFSFS
)) {
127 val
= SMB_ROUNDUP(val
,rval
);
132 /********************************************************************
133 Create a 64 bit FileIndex. If the file is on the same device as
134 the root of the share, just return the 64-bit inode. If it isn't,
135 mangle as we used to do.
136 ********************************************************************/
138 uint64_t get_FileIndex(connection_struct
*conn
, const SMB_STRUCT_STAT
*psbuf
)
141 if (conn
->base_share_dev
== psbuf
->st_ex_dev
) {
142 return (uint64_t)psbuf
->st_ex_ino
;
144 file_index
= ((psbuf
->st_ex_ino
) & UINT32_MAX
); /* FileIndexLow */
145 file_index
|= ((uint64_t)((psbuf
->st_ex_dev
) & UINT32_MAX
)) << 32; /* FileIndexHigh */
149 /****************************************************************************
150 Utility functions for dealing with extended attributes.
151 ****************************************************************************/
153 /****************************************************************************
154 Refuse to allow clients to overwrite our private xattrs.
155 ****************************************************************************/
157 bool samba_private_attr_name(const char *unix_ea_name
)
159 static const char * const prohibited_ea_names
[] = {
160 SAMBA_POSIX_INHERITANCE_EA_NAME
,
161 SAMBA_XATTR_DOS_ATTRIB
,
169 for (i
= 0; prohibited_ea_names
[i
]; i
++) {
170 if (strequal( prohibited_ea_names
[i
], unix_ea_name
))
173 if (strncasecmp_m(unix_ea_name
, SAMBA_XATTR_DOSSTREAM_PREFIX
,
174 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX
)) == 0) {
180 /****************************************************************************
181 Get one EA value. Fill in a struct ea_struct.
182 ****************************************************************************/
184 NTSTATUS
get_ea_value(TALLOC_CTX
*mem_ctx
, connection_struct
*conn
,
185 files_struct
*fsp
, const char *fname
,
186 const char *ea_name
, struct ea_struct
*pea
)
188 /* Get the value of this xattr. Max size is 64k. */
189 size_t attr_size
= 256;
195 val
= talloc_realloc(mem_ctx
, val
, char, attr_size
);
197 return NT_STATUS_NO_MEMORY
;
200 if (fsp
&& fsp
->fh
->fd
!= -1) {
201 sizeret
= SMB_VFS_FGETXATTR(fsp
, ea_name
, val
, attr_size
);
203 sizeret
= SMB_VFS_GETXATTR(conn
, fname
, ea_name
, val
, attr_size
);
206 if (sizeret
== -1 && errno
== ERANGE
&& attr_size
!= 65536) {
212 return map_nt_error_from_unix(errno
);
215 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name
, (unsigned int)sizeret
));
216 dump_data(10, (uint8_t *)val
, sizeret
);
219 if (strnequal(ea_name
, "user.", 5)) {
220 pea
->name
= talloc_strdup(mem_ctx
, &ea_name
[5]);
222 pea
->name
= talloc_strdup(mem_ctx
, ea_name
);
224 if (pea
->name
== NULL
) {
226 return NT_STATUS_NO_MEMORY
;
228 pea
->value
.data
= (unsigned char *)val
;
229 pea
->value
.length
= (size_t)sizeret
;
233 NTSTATUS
get_ea_names_from_file(TALLOC_CTX
*mem_ctx
,
234 connection_struct
*conn
,
236 const struct smb_filename
*smb_fname
,
240 /* Get a list of all xattrs. Max namesize is 64k. */
241 size_t ea_namelist_size
= 1024;
242 char *ea_namelist
= NULL
;
247 ssize_t sizeret
= -1;
255 if (!lp_ea_support(SNUM(conn
))) {
259 status
= refuse_symlink(conn
, fsp
, smb_fname
);
260 if (!NT_STATUS_IS_OK(status
)) {
262 * Just return no EA's on a symlink.
268 * TALLOC the result early to get the talloc hierarchy right.
271 names
= talloc_array(mem_ctx
, char *, 1);
273 DEBUG(0, ("talloc failed\n"));
274 return NT_STATUS_NO_MEMORY
;
277 while (ea_namelist_size
<= 65536) {
279 ea_namelist
= talloc_realloc(
280 names
, ea_namelist
, char, ea_namelist_size
);
281 if (ea_namelist
== NULL
) {
282 DEBUG(0, ("talloc failed\n"));
284 return NT_STATUS_NO_MEMORY
;
287 if (fsp
&& fsp
->fh
->fd
!= -1) {
288 sizeret
= SMB_VFS_FLISTXATTR(fsp
, ea_namelist
,
291 sizeret
= SMB_VFS_LISTXATTR(conn
,
292 smb_fname
->base_name
,
297 if ((sizeret
== -1) && (errno
== ERANGE
)) {
298 ea_namelist_size
*= 2;
307 return map_nt_error_from_unix(errno
);
310 DEBUG(10, ("%s: ea_namelist size = %u\n",
311 __func__
, (unsigned int)sizeret
));
319 * Ensure the result is 0-terminated
322 if (ea_namelist
[sizeret
-1] != '\0') {
324 return NT_STATUS_INTERNAL_ERROR
;
332 for (p
= ea_namelist
; p
- ea_namelist
< sizeret
; p
+= strlen(p
)+1) {
336 tmp
= talloc_realloc(mem_ctx
, names
, char *, num_names
);
338 DEBUG(0, ("talloc failed\n"));
340 return NT_STATUS_NO_MEMORY
;
346 for (p
= ea_namelist
; p
- ea_namelist
< sizeret
; p
+= strlen(p
)+1) {
347 names
[num_names
++] = p
;
355 *pnum_names
= num_names
;
359 /****************************************************************************
360 Return a linked list of the total EA's. Plus the total size
361 ****************************************************************************/
363 static NTSTATUS
get_ea_list_from_file_path(TALLOC_CTX
*mem_ctx
,
364 connection_struct
*conn
,
366 const struct smb_filename
*smb_fname
,
367 size_t *pea_total_len
,
368 struct ea_list
**ea_list
)
370 /* Get a list of all xattrs. Max namesize is 64k. */
373 struct ea_list
*ea_list_head
= NULL
;
374 bool posix_pathnames
= false;
382 (fsp
->fsp_name
->flags
& SMB_FILENAME_POSIX_PATH
);
384 posix_pathnames
= (smb_fname
->flags
& SMB_FILENAME_POSIX_PATH
);
387 status
= get_ea_names_from_file(talloc_tos(),
394 if (!NT_STATUS_IS_OK(status
)) {
398 if (num_names
== 0) {
403 for (i
=0; i
<num_names
; i
++) {
404 struct ea_list
*listp
;
407 if (strnequal(names
[i
], "system.", 7)
408 || samba_private_attr_name(names
[i
]))
412 * Filter out any underlying POSIX EA names
413 * that a Windows client can't handle.
415 if (!posix_pathnames
&&
416 is_invalid_windows_ea_name(names
[i
])) {
420 listp
= talloc(mem_ctx
, struct ea_list
);
422 return NT_STATUS_NO_MEMORY
;
425 status
= get_ea_value(listp
,
428 smb_fname
->base_name
,
432 if (!NT_STATUS_IS_OK(status
)) {
437 if (listp
->ea
.value
.length
== 0) {
439 * We can never return a zero length EA.
440 * Windows reports the EA's as corrupted.
446 push_ascii_fstring(dos_ea_name
, listp
->ea
.name
);
449 4 + strlen(dos_ea_name
) + 1 + listp
->ea
.value
.length
;
451 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
452 "= %u\n", (unsigned int)*pea_total_len
, dos_ea_name
,
453 (unsigned int)listp
->ea
.value
.length
));
455 DLIST_ADD_END(ea_list_head
, listp
);
459 /* Add on 4 for total length. */
460 if (*pea_total_len
) {
464 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
465 (unsigned int)*pea_total_len
));
467 *ea_list
= ea_list_head
;
471 static NTSTATUS
get_ea_list_from_file(TALLOC_CTX
*mem_ctx
, connection_struct
*conn
, files_struct
*fsp
,
472 const struct smb_filename
*smb_fname
, size_t *pea_total_len
, struct ea_list
**ea_list
)
477 if (!lp_ea_support(SNUM(conn
))) {
481 if (is_ntfs_stream_smb_fname(smb_fname
)) {
482 return NT_STATUS_INVALID_PARAMETER
;
485 return get_ea_list_from_file_path(mem_ctx
,
493 /****************************************************************************
494 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
496 ****************************************************************************/
498 static unsigned int fill_ea_buffer(TALLOC_CTX
*mem_ctx
, char *pdata
, unsigned int total_data_size
,
499 connection_struct
*conn
, struct ea_list
*ea_list
)
501 unsigned int ret_data_size
= 4;
504 SMB_ASSERT(total_data_size
>= 4);
506 if (!lp_ea_support(SNUM(conn
))) {
511 for (p
= pdata
+ 4; ea_list
; ea_list
= ea_list
->next
) {
514 push_ascii_fstring(dos_ea_name
, ea_list
->ea
.name
);
515 dos_namelen
= strlen(dos_ea_name
);
516 if (dos_namelen
> 255 || dos_namelen
== 0) {
519 if (ea_list
->ea
.value
.length
> 65535) {
522 if (4 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
> total_data_size
) {
526 /* We know we have room. */
527 SCVAL(p
,0,ea_list
->ea
.flags
);
528 SCVAL(p
,1,dos_namelen
);
529 SSVAL(p
,2,ea_list
->ea
.value
.length
);
530 strlcpy(p
+4, dos_ea_name
, dos_namelen
+1);
531 memcpy( p
+ 4 + dos_namelen
+ 1, ea_list
->ea
.value
.data
, ea_list
->ea
.value
.length
);
533 total_data_size
-= 4 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
;
534 p
+= 4 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
;
537 ret_data_size
= PTR_DIFF(p
, pdata
);
538 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size
));
539 SIVAL(pdata
,0,ret_data_size
);
540 return ret_data_size
;
543 static NTSTATUS
fill_ea_chained_buffer(TALLOC_CTX
*mem_ctx
,
545 unsigned int total_data_size
,
546 unsigned int *ret_data_size
,
547 connection_struct
*conn
,
548 struct ea_list
*ea_list
)
550 uint8_t *p
= (uint8_t *)pdata
;
551 uint8_t *last_start
= NULL
;
552 bool do_store_data
= (pdata
!= NULL
);
556 if (!lp_ea_support(SNUM(conn
))) {
557 return NT_STATUS_NO_EAS_ON_FILE
;
560 for (; ea_list
; ea_list
= ea_list
->next
) {
566 if (last_start
!= NULL
&& do_store_data
) {
567 SIVAL(last_start
, 0, PTR_DIFF(p
, last_start
));
571 push_ascii_fstring(dos_ea_name
, ea_list
->ea
.name
);
572 dos_namelen
= strlen(dos_ea_name
);
573 if (dos_namelen
> 255 || dos_namelen
== 0) {
574 return NT_STATUS_INTERNAL_ERROR
;
576 if (ea_list
->ea
.value
.length
> 65535) {
577 return NT_STATUS_INTERNAL_ERROR
;
580 this_size
= 0x08 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
;
583 pad
= (4 - (this_size
% 4)) % 4;
588 if (this_size
> total_data_size
) {
589 return NT_STATUS_INFO_LENGTH_MISMATCH
;
592 /* We know we have room. */
593 SIVAL(p
, 0x00, 0); /* next offset */
594 SCVAL(p
, 0x04, ea_list
->ea
.flags
);
595 SCVAL(p
, 0x05, dos_namelen
);
596 SSVAL(p
, 0x06, ea_list
->ea
.value
.length
);
597 strlcpy((char *)(p
+0x08), dos_ea_name
, dos_namelen
+1);
598 memcpy(p
+ 0x08 + dos_namelen
+ 1, ea_list
->ea
.value
.data
, ea_list
->ea
.value
.length
);
600 memset(p
+ 0x08 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
,
604 total_data_size
-= this_size
;
610 *ret_data_size
= PTR_DIFF(p
, pdata
);
611 DEBUG(10,("fill_ea_chained_buffer: data_size = %u\n", *ret_data_size
));
615 static unsigned int estimate_ea_size(connection_struct
*conn
, files_struct
*fsp
, const struct smb_filename
*smb_fname
)
617 size_t total_ea_len
= 0;
619 struct ea_list
*ea_list
= NULL
;
621 if (!lp_ea_support(SNUM(conn
))) {
624 mem_ctx
= talloc_stackframe();
626 /* If this is a stream fsp, then we need to instead find the
627 * estimated ea len from the main file, not the stream
628 * (streams cannot have EAs), but the estimate isn't just 0 in
630 if (is_ntfs_stream_smb_fname(smb_fname
)) {
633 (void)get_ea_list_from_file_path(mem_ctx
,
639 if(conn
->sconn
->using_smb2
) {
641 unsigned int ret_data_size
;
643 * We're going to be using fill_ea_chained_buffer() to
644 * marshall EA's - this size is significantly larger
645 * than the SMB1 buffer. Re-calculate the size without
648 status
= fill_ea_chained_buffer(mem_ctx
,
654 if (!NT_STATUS_IS_OK(status
)) {
657 total_ea_len
= ret_data_size
;
659 TALLOC_FREE(mem_ctx
);
663 /****************************************************************************
664 Ensure the EA name is case insensitive by matching any existing EA name.
665 ****************************************************************************/
667 static void canonicalize_ea_name(connection_struct
*conn
,
669 const struct smb_filename
*smb_fname
,
670 fstring unix_ea_name
)
673 TALLOC_CTX
*mem_ctx
= talloc_tos();
674 struct ea_list
*ea_list
;
675 NTSTATUS status
= get_ea_list_from_file_path(mem_ctx
,
681 if (!NT_STATUS_IS_OK(status
)) {
685 for (; ea_list
; ea_list
= ea_list
->next
) {
686 if (strequal(&unix_ea_name
[5], ea_list
->ea
.name
)) {
687 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
688 &unix_ea_name
[5], ea_list
->ea
.name
));
689 strlcpy(&unix_ea_name
[5], ea_list
->ea
.name
, sizeof(fstring
)-5);
695 /****************************************************************************
696 Set or delete an extended attribute.
697 ****************************************************************************/
699 NTSTATUS
set_ea(connection_struct
*conn
, files_struct
*fsp
,
700 const struct smb_filename
*smb_fname
, struct ea_list
*ea_list
)
703 bool posix_pathnames
= false;
705 if (!lp_ea_support(SNUM(conn
))) {
706 return NT_STATUS_EAS_NOT_SUPPORTED
;
711 (fsp
->fsp_name
->flags
& SMB_FILENAME_POSIX_PATH
);
713 posix_pathnames
= (smb_fname
->flags
& SMB_FILENAME_POSIX_PATH
);
716 status
= refuse_symlink(conn
, fsp
, smb_fname
);
717 if (!NT_STATUS_IS_OK(status
)) {
721 status
= check_access(conn
, fsp
, smb_fname
, FILE_WRITE_EA
);
722 if (!NT_STATUS_IS_OK(status
)) {
726 /* Setting EAs on streams isn't supported. */
727 if (is_ntfs_stream_smb_fname(smb_fname
)) {
728 return NT_STATUS_INVALID_PARAMETER
;
732 * Filter out invalid Windows EA names - before
733 * we set *any* of them.
736 if (!posix_pathnames
&& ea_list_has_invalid_name(ea_list
)) {
737 return STATUS_INVALID_EA_NAME
;
740 for (;ea_list
; ea_list
= ea_list
->next
) {
742 fstring unix_ea_name
;
744 fstrcpy(unix_ea_name
, "user."); /* All EA's must start with user. */
745 fstrcat(unix_ea_name
, ea_list
->ea
.name
);
747 canonicalize_ea_name(conn
,
752 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name
, (unsigned int)ea_list
->ea
.value
.length
));
754 if (samba_private_attr_name(unix_ea_name
)) {
755 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name
));
756 return NT_STATUS_ACCESS_DENIED
;
759 if (ea_list
->ea
.value
.length
== 0) {
760 /* Remove the attribute. */
761 if (fsp
&& (fsp
->fh
->fd
!= -1)) {
762 DEBUG(10,("set_ea: deleting ea name %s on "
763 "file %s by file descriptor.\n",
764 unix_ea_name
, fsp_str_dbg(fsp
)));
765 ret
= SMB_VFS_FREMOVEXATTR(fsp
, unix_ea_name
);
767 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
768 unix_ea_name
, smb_fname
->base_name
));
769 ret
= SMB_VFS_REMOVEXATTR(conn
,
770 smb_fname
->base_name
,
774 /* Removing a non existent attribute always succeeds. */
775 if (ret
== -1 && errno
== ENOATTR
) {
776 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
782 if (fsp
&& (fsp
->fh
->fd
!= -1)) {
783 DEBUG(10,("set_ea: setting ea name %s on file "
784 "%s by file descriptor.\n",
785 unix_ea_name
, fsp_str_dbg(fsp
)));
786 ret
= SMB_VFS_FSETXATTR(fsp
, unix_ea_name
,
787 ea_list
->ea
.value
.data
, ea_list
->ea
.value
.length
, 0);
789 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
790 unix_ea_name
, smb_fname
->base_name
));
791 ret
= SMB_VFS_SETXATTR(conn
,
792 smb_fname
->base_name
,
794 ea_list
->ea
.value
.data
,
795 ea_list
->ea
.value
.length
,
802 if (errno
== ENOTSUP
) {
803 return NT_STATUS_EAS_NOT_SUPPORTED
;
806 return map_nt_error_from_unix(errno
);
812 /****************************************************************************
813 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
814 ****************************************************************************/
816 static struct ea_list
*read_ea_name_list(TALLOC_CTX
*ctx
, const char *pdata
, size_t data_size
)
818 struct ea_list
*ea_list_head
= NULL
;
819 size_t converted_size
, offset
= 0;
821 while (offset
+ 2 < data_size
) {
822 struct ea_list
*eal
= talloc_zero(ctx
, struct ea_list
);
823 unsigned int namelen
= CVAL(pdata
,offset
);
825 offset
++; /* Go past the namelen byte. */
827 /* integer wrap paranioa. */
828 if ((offset
+ namelen
< offset
) || (offset
+ namelen
< namelen
) ||
829 (offset
> data_size
) || (namelen
> data_size
) ||
830 (offset
+ namelen
>= data_size
)) {
833 /* Ensure the name is null terminated. */
834 if (pdata
[offset
+ namelen
] != '\0') {
837 if (!pull_ascii_talloc(ctx
, &eal
->ea
.name
, &pdata
[offset
],
839 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
840 "failed: %s", strerror(errno
)));
846 offset
+= (namelen
+ 1); /* Go past the name + terminating zero. */
847 DLIST_ADD_END(ea_list_head
, eal
);
848 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal
->ea
.name
));
854 /****************************************************************************
855 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
856 ****************************************************************************/
858 static struct ea_list
*read_ea_list(TALLOC_CTX
*ctx
, const char *pdata
, size_t data_size
)
860 struct ea_list
*ea_list_head
= NULL
;
862 size_t bytes_used
= 0;
864 while (offset
< data_size
) {
865 struct ea_list
*eal
= read_ea_list_entry(ctx
, pdata
+ offset
, data_size
- offset
, &bytes_used
);
871 DLIST_ADD_END(ea_list_head
, eal
);
872 offset
+= bytes_used
;
878 /****************************************************************************
879 Count the total EA size needed.
880 ****************************************************************************/
882 static size_t ea_list_size(struct ea_list
*ealist
)
885 struct ea_list
*listp
;
888 for (listp
= ealist
; listp
; listp
= listp
->next
) {
889 push_ascii_fstring(dos_ea_name
, listp
->ea
.name
);
890 ret
+= 4 + strlen(dos_ea_name
) + 1 + listp
->ea
.value
.length
;
892 /* Add on 4 for total length. */
900 /****************************************************************************
901 Return a union of EA's from a file list and a list of names.
902 The TALLOC context for the two lists *MUST* be identical as we steal
903 memory from one list to add to another. JRA.
904 ****************************************************************************/
906 static struct ea_list
*ea_list_union(struct ea_list
*name_list
, struct ea_list
*file_list
, size_t *total_ea_len
)
908 struct ea_list
*nlistp
, *flistp
;
910 for (nlistp
= name_list
; nlistp
; nlistp
= nlistp
->next
) {
911 for (flistp
= file_list
; flistp
; flistp
= flistp
->next
) {
912 if (strequal(nlistp
->ea
.name
, flistp
->ea
.name
)) {
918 /* Copy the data from this entry. */
919 nlistp
->ea
.flags
= flistp
->ea
.flags
;
920 nlistp
->ea
.value
= flistp
->ea
.value
;
923 nlistp
->ea
.flags
= 0;
924 ZERO_STRUCT(nlistp
->ea
.value
);
928 *total_ea_len
= ea_list_size(name_list
);
932 /****************************************************************************
933 Send the required number of replies back.
934 We assume all fields other than the data fields are
935 set correctly for the type of call.
936 HACK ! Always assumes smb_setup field is zero.
937 ****************************************************************************/
939 void send_trans2_replies(connection_struct
*conn
,
940 struct smb_request
*req
,
948 /* As we are using a protocol > LANMAN1 then the max_send
949 variable must have been set in the sessetupX call.
950 This takes precedence over the max_xmit field in the
951 global struct. These different max_xmit variables should
952 be merged as this is now too confusing */
954 int data_to_send
= datasize
;
955 int params_to_send
= paramsize
;
957 const char *pp
= params
;
958 const char *pd
= pdata
;
959 int params_sent_thistime
, data_sent_thistime
, total_sent_thistime
;
960 int alignment_offset
= 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
961 int data_alignment_offset
= 0;
962 bool overflow
= False
;
963 struct smbXsrv_connection
*xconn
= req
->xconn
;
964 int max_send
= xconn
->smb1
.sessions
.max_send
;
966 /* Modify the data_to_send and datasize and set the error if
967 we're trying to send more than max_data_bytes. We still send
968 the part of the packet(s) that fit. Strange, but needed
971 if (max_data_bytes
> 0 && datasize
> max_data_bytes
) {
972 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
973 max_data_bytes
, datasize
));
974 datasize
= data_to_send
= max_data_bytes
;
978 /* If there genuinely are no parameters or data to send just send the empty packet */
980 if(params_to_send
== 0 && data_to_send
== 0) {
981 reply_outbuf(req
, 10, 0);
982 if (NT_STATUS_V(status
)) {
985 ntstatus_to_dos(status
, &eclass
, &ecode
);
986 error_packet_set((char *)req
->outbuf
,
987 eclass
, ecode
, status
,
990 show_msg((char *)req
->outbuf
);
991 if (!srv_send_smb(xconn
,
994 IS_CONN_ENCRYPTED(conn
),
996 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
998 TALLOC_FREE(req
->outbuf
);
1002 /* When sending params and data ensure that both are nicely aligned */
1003 /* Only do this alignment when there is also data to send - else
1004 can cause NT redirector problems. */
1006 if (((params_to_send
% 4) != 0) && (data_to_send
!= 0))
1007 data_alignment_offset
= 4 - (params_to_send
% 4);
1009 /* Space is bufsize minus Netbios over TCP header minus SMB header */
1010 /* The alignment_offset is to align the param bytes on an even byte
1011 boundary. NT 4.0 Beta needs this to work correctly. */
1013 useable_space
= max_send
- (smb_size
1016 + data_alignment_offset
);
1018 if (useable_space
< 0) {
1019 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
1020 "= %d!!!", useable_space
));
1021 exit_server_cleanly("send_trans2_replies: Not enough space");
1024 while (params_to_send
|| data_to_send
) {
1025 /* Calculate whether we will totally or partially fill this packet */
1027 total_sent_thistime
= params_to_send
+ data_to_send
;
1029 /* We can never send more than useable_space */
1031 * Note that 'useable_space' does not include the alignment offsets,
1032 * but we must include the alignment offsets in the calculation of
1033 * the length of the data we send over the wire, as the alignment offsets
1034 * are sent here. Fix from Marc_Jacobsen@hp.com.
1037 total_sent_thistime
= MIN(total_sent_thistime
, useable_space
);
1039 reply_outbuf(req
, 10, total_sent_thistime
+ alignment_offset
1040 + data_alignment_offset
);
1042 /* Set total params and data to be sent */
1043 SSVAL(req
->outbuf
,smb_tprcnt
,paramsize
);
1044 SSVAL(req
->outbuf
,smb_tdrcnt
,datasize
);
1046 /* Calculate how many parameters and data we can fit into
1047 * this packet. Parameters get precedence
1050 params_sent_thistime
= MIN(params_to_send
,useable_space
);
1051 data_sent_thistime
= useable_space
- params_sent_thistime
;
1052 data_sent_thistime
= MIN(data_sent_thistime
,data_to_send
);
1054 SSVAL(req
->outbuf
,smb_prcnt
, params_sent_thistime
);
1056 /* smb_proff is the offset from the start of the SMB header to the
1057 parameter bytes, however the first 4 bytes of outbuf are
1058 the Netbios over TCP header. Thus use smb_base() to subtract
1059 them from the calculation */
1061 SSVAL(req
->outbuf
,smb_proff
,
1062 ((smb_buf(req
->outbuf
)+alignment_offset
)
1063 - smb_base(req
->outbuf
)));
1065 if(params_sent_thistime
== 0)
1066 SSVAL(req
->outbuf
,smb_prdisp
,0);
1068 /* Absolute displacement of param bytes sent in this packet */
1069 SSVAL(req
->outbuf
,smb_prdisp
,pp
- params
);
1071 SSVAL(req
->outbuf
,smb_drcnt
, data_sent_thistime
);
1072 if(data_sent_thistime
== 0) {
1073 SSVAL(req
->outbuf
,smb_droff
,0);
1074 SSVAL(req
->outbuf
,smb_drdisp
, 0);
1076 /* The offset of the data bytes is the offset of the
1077 parameter bytes plus the number of parameters being sent this time */
1078 SSVAL(req
->outbuf
, smb_droff
,
1079 ((smb_buf(req
->outbuf
)+alignment_offset
)
1080 - smb_base(req
->outbuf
))
1081 + params_sent_thistime
+ data_alignment_offset
);
1082 SSVAL(req
->outbuf
,smb_drdisp
, pd
- pdata
);
1085 /* Initialize the padding for alignment */
1087 if (alignment_offset
!= 0) {
1088 memset(smb_buf(req
->outbuf
), 0, alignment_offset
);
1091 /* Copy the param bytes into the packet */
1093 if(params_sent_thistime
) {
1094 memcpy((smb_buf(req
->outbuf
)+alignment_offset
), pp
,
1095 params_sent_thistime
);
1098 /* Copy in the data bytes */
1099 if(data_sent_thistime
) {
1100 if (data_alignment_offset
!= 0) {
1101 memset((smb_buf(req
->outbuf
)+alignment_offset
+
1102 params_sent_thistime
), 0,
1103 data_alignment_offset
);
1105 memcpy(smb_buf(req
->outbuf
)+alignment_offset
1106 +params_sent_thistime
+data_alignment_offset
,
1107 pd
,data_sent_thistime
);
1110 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
1111 params_sent_thistime
, data_sent_thistime
, useable_space
));
1112 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
1113 params_to_send
, data_to_send
, paramsize
, datasize
));
1116 error_packet_set((char *)req
->outbuf
,
1117 ERRDOS
,ERRbufferoverflow
,
1118 STATUS_BUFFER_OVERFLOW
,
1120 } else if (NT_STATUS_V(status
)) {
1123 ntstatus_to_dos(status
, &eclass
, &ecode
);
1124 error_packet_set((char *)req
->outbuf
,
1125 eclass
, ecode
, status
,
1129 /* Send the packet */
1130 show_msg((char *)req
->outbuf
);
1131 if (!srv_send_smb(xconn
,
1132 (char *)req
->outbuf
,
1133 true, req
->seqnum
+1,
1134 IS_CONN_ENCRYPTED(conn
),
1136 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
1138 TALLOC_FREE(req
->outbuf
);
1140 pp
+= params_sent_thistime
;
1141 pd
+= data_sent_thistime
;
1143 params_to_send
-= params_sent_thistime
;
1144 data_to_send
-= data_sent_thistime
;
1147 if(params_to_send
< 0 || data_to_send
< 0) {
1148 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
1149 params_to_send
, data_to_send
));
1157 /****************************************************************************
1158 Reply to a TRANSACT2_OPEN.
1159 ****************************************************************************/
1161 static void call_trans2open(connection_struct
*conn
,
1162 struct smb_request
*req
,
1163 char **pparams
, int total_params
,
1164 char **ppdata
, int total_data
,
1165 unsigned int max_data_bytes
)
1167 struct smb_filename
*smb_fname
= NULL
;
1168 char *params
= *pparams
;
1169 char *pdata
= *ppdata
;
1172 bool oplock_request
;
1174 bool return_additional_info
;
1183 int fattr
=0,mtime
=0;
1184 SMB_INO_T inode
= 0;
1187 struct ea_list
*ea_list
= NULL
;
1190 uint32_t access_mask
;
1191 uint32_t share_mode
;
1192 uint32_t create_disposition
;
1193 uint32_t create_options
= 0;
1194 uint32_t private_flags
= 0;
1195 uint32_t ucf_flags
= (req
->posix_pathnames
? UCF_POSIX_PATHNAMES
: 0);
1196 TALLOC_CTX
*ctx
= talloc_tos();
1199 * Ensure we have enough parameters to perform the operation.
1202 if (total_params
< 29) {
1203 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1207 flags
= SVAL(params
, 0);
1208 deny_mode
= SVAL(params
, 2);
1209 open_attr
= SVAL(params
,6);
1210 oplock_request
= (flags
& REQUEST_OPLOCK
) ? EXCLUSIVE_OPLOCK
: 0;
1211 if (oplock_request
) {
1212 oplock_request
|= (flags
& REQUEST_BATCH_OPLOCK
) ? BATCH_OPLOCK
: 0;
1216 return_additional_info
= BITSETW(params
,0);
1217 open_sattr
= SVAL(params
, 4);
1218 open_time
= make_unix_date3(params
+8);
1220 open_ofun
= SVAL(params
,12);
1221 open_size
= IVAL(params
,14);
1222 pname
= ¶ms
[28];
1225 reply_nterror(req
, NT_STATUS_NETWORK_ACCESS_DENIED
);
1229 if (req
->posix_pathnames
) {
1230 srvstr_get_path_posix(ctx
,
1239 srvstr_get_path(ctx
,
1248 if (!NT_STATUS_IS_OK(status
)) {
1249 reply_nterror(req
, status
);
1253 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
1254 fname
, (unsigned int)deny_mode
, (unsigned int)open_attr
,
1255 (unsigned int)open_ofun
, open_size
));
1257 status
= filename_convert(ctx
,
1259 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
1264 if (!NT_STATUS_IS_OK(status
)) {
1265 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
1266 reply_botherror(req
,
1267 NT_STATUS_PATH_NOT_COVERED
,
1268 ERRSRV
, ERRbadpath
);
1271 reply_nterror(req
, status
);
1275 if (open_ofun
== 0) {
1276 reply_nterror(req
, NT_STATUS_OBJECT_NAME_COLLISION
);
1280 if (!map_open_params_to_ntcreate(smb_fname
->base_name
, deny_mode
,
1282 &access_mask
, &share_mode
,
1283 &create_disposition
,
1286 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
1290 /* Any data in this call is an EA list. */
1291 if (total_data
&& (total_data
!= 4)) {
1292 if (total_data
< 10) {
1293 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1297 if (IVAL(pdata
,0) > total_data
) {
1298 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
1299 IVAL(pdata
,0), (unsigned int)total_data
));
1300 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1304 ea_list
= read_ea_list(talloc_tos(), pdata
+ 4,
1307 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1311 if (!lp_ea_support(SNUM(conn
))) {
1312 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
1316 if (!req
->posix_pathnames
&&
1317 ea_list_has_invalid_name(ea_list
)) {
1319 *pparams
= (char *)SMB_REALLOC(*pparams
, param_len
);
1320 if(*pparams
== NULL
) {
1321 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1325 memset(params
, '\0', param_len
);
1326 send_trans2_replies(conn
, req
, STATUS_INVALID_EA_NAME
,
1327 params
, param_len
, NULL
, 0, max_data_bytes
);
1332 status
= SMB_VFS_CREATE_FILE(
1335 0, /* root_dir_fid */
1336 smb_fname
, /* fname */
1337 access_mask
, /* access_mask */
1338 share_mode
, /* share_access */
1339 create_disposition
, /* create_disposition*/
1340 create_options
, /* create_options */
1341 open_attr
, /* file_attributes */
1342 oplock_request
, /* oplock_request */
1344 open_size
, /* allocation_size */
1347 ea_list
, /* ea_list */
1349 &smb_action
, /* psbuf */
1350 NULL
, NULL
); /* create context */
1352 if (!NT_STATUS_IS_OK(status
)) {
1353 if (open_was_deferred(req
->xconn
, req
->mid
)) {
1354 /* We have re-scheduled this call. */
1357 reply_openerror(req
, status
);
1361 size
= get_file_size_stat(&smb_fname
->st
);
1362 fattr
= dos_mode(conn
, smb_fname
);
1363 mtime
= convert_timespec_to_time_t(smb_fname
->st
.st_ex_mtime
);
1364 inode
= smb_fname
->st
.st_ex_ino
;
1365 if (fattr
& FILE_ATTRIBUTE_DIRECTORY
) {
1366 close_file(req
, fsp
, ERROR_CLOSE
);
1367 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
1371 /* Realloc the size of parameters and data we will return */
1372 *pparams
= (char *)SMB_REALLOC(*pparams
, 30);
1373 if(*pparams
== NULL
) {
1374 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1379 SSVAL(params
,0,fsp
->fnum
);
1380 SSVAL(params
,2,fattr
);
1381 srv_put_dos_date2(params
,4, mtime
);
1382 SIVAL(params
,8, (uint32_t)size
);
1383 SSVAL(params
,12,deny_mode
);
1384 SSVAL(params
,14,0); /* open_type - file or directory. */
1385 SSVAL(params
,16,0); /* open_state - only valid for IPC device. */
1387 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
1388 smb_action
|= EXTENDED_OPLOCK_GRANTED
;
1391 SSVAL(params
,18,smb_action
);
1394 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1396 SIVAL(params
,20,inode
);
1397 SSVAL(params
,24,0); /* Padding. */
1399 uint32_t ea_size
= estimate_ea_size(conn
, fsp
,
1401 SIVAL(params
, 26, ea_size
);
1403 SIVAL(params
, 26, 0);
1406 /* Send the required number of replies */
1407 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 30, *ppdata
, 0, max_data_bytes
);
1409 TALLOC_FREE(smb_fname
);
1412 /*********************************************************
1413 Routine to check if a given string matches exactly.
1414 as a special case a mask of "." does NOT match. That
1415 is required for correct wildcard semantics
1416 Case can be significant or not.
1417 **********************************************************/
1419 static bool exact_match(bool has_wild
,
1420 bool case_sensitive
,
1424 if (mask
[0] == '.' && mask
[1] == 0) {
1432 if (case_sensitive
) {
1433 return strcmp(str
,mask
)==0;
1435 return strcasecmp_m(str
,mask
) == 0;
1439 /****************************************************************************
1440 Return the filetype for UNIX extensions.
1441 ****************************************************************************/
1443 static uint32_t unix_filetype(mode_t mode
)
1446 return UNIX_TYPE_FILE
;
1447 else if(S_ISDIR(mode
))
1448 return UNIX_TYPE_DIR
;
1450 else if(S_ISLNK(mode
))
1451 return UNIX_TYPE_SYMLINK
;
1454 else if(S_ISCHR(mode
))
1455 return UNIX_TYPE_CHARDEV
;
1458 else if(S_ISBLK(mode
))
1459 return UNIX_TYPE_BLKDEV
;
1462 else if(S_ISFIFO(mode
))
1463 return UNIX_TYPE_FIFO
;
1466 else if(S_ISSOCK(mode
))
1467 return UNIX_TYPE_SOCKET
;
1470 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode
));
1471 return UNIX_TYPE_UNKNOWN
;
1474 /****************************************************************************
1475 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1476 ****************************************************************************/
1478 enum perm_type
{ PERM_NEW_FILE
, PERM_NEW_DIR
, PERM_EXISTING_FILE
, PERM_EXISTING_DIR
};
1480 static NTSTATUS
unix_perms_from_wire( connection_struct
*conn
,
1481 const SMB_STRUCT_STAT
*psbuf
,
1483 enum perm_type ptype
,
1488 if (perms
== SMB_MODE_NO_CHANGE
) {
1489 if (!VALID_STAT(*psbuf
)) {
1490 return NT_STATUS_INVALID_PARAMETER
;
1492 *ret_perms
= psbuf
->st_ex_mode
;
1493 return NT_STATUS_OK
;
1497 ret
|= ((perms
& UNIX_X_OTH
) ? S_IXOTH
: 0);
1498 ret
|= ((perms
& UNIX_W_OTH
) ? S_IWOTH
: 0);
1499 ret
|= ((perms
& UNIX_R_OTH
) ? S_IROTH
: 0);
1500 ret
|= ((perms
& UNIX_X_GRP
) ? S_IXGRP
: 0);
1501 ret
|= ((perms
& UNIX_W_GRP
) ? S_IWGRP
: 0);
1502 ret
|= ((perms
& UNIX_R_GRP
) ? S_IRGRP
: 0);
1503 ret
|= ((perms
& UNIX_X_USR
) ? S_IXUSR
: 0);
1504 ret
|= ((perms
& UNIX_W_USR
) ? S_IWUSR
: 0);
1505 ret
|= ((perms
& UNIX_R_USR
) ? S_IRUSR
: 0);
1507 ret
|= ((perms
& UNIX_STICKY
) ? S_ISVTX
: 0);
1510 ret
|= ((perms
& UNIX_SET_GID
) ? S_ISGID
: 0);
1513 ret
|= ((perms
& UNIX_SET_UID
) ? S_ISUID
: 0);
1516 if (ptype
== PERM_NEW_FILE
) {
1518 * "create mask"/"force create mode" are
1519 * only applied to new files, not existing ones.
1521 ret
&= lp_create_mask(SNUM(conn
));
1522 /* Add in force bits */
1523 ret
|= lp_force_create_mode(SNUM(conn
));
1524 } else if (ptype
== PERM_NEW_DIR
) {
1526 * "directory mask"/"force directory mode" are
1527 * only applied to new directories, not existing ones.
1529 ret
&= lp_directory_mask(SNUM(conn
));
1530 /* Add in force bits */
1531 ret
|= lp_force_directory_mode(SNUM(conn
));
1535 return NT_STATUS_OK
;
1538 /****************************************************************************
1539 Needed to show the msdfs symlinks as directories. Modifies psbuf
1540 to be a directory if it's a msdfs link.
1541 ****************************************************************************/
1543 static bool check_msdfs_link(connection_struct
*conn
,
1544 const char *pathname
,
1545 SMB_STRUCT_STAT
*psbuf
)
1547 int saved_errno
= errno
;
1548 if(lp_host_msdfs() &&
1549 lp_msdfs_root(SNUM(conn
)) &&
1550 is_msdfs_link(conn
, pathname
, psbuf
)) {
1552 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1555 psbuf
->st_ex_mode
= (psbuf
->st_ex_mode
& 0xFFF) | S_IFDIR
;
1556 errno
= saved_errno
;
1559 errno
= saved_errno
;
1564 /****************************************************************************
1565 Get a level dependent lanman2 dir entry.
1566 ****************************************************************************/
1568 struct smbd_dirptr_lanman2_state
{
1569 connection_struct
*conn
;
1570 uint32_t info_level
;
1571 bool check_mangled_names
;
1573 bool got_exact_match
;
1576 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX
*ctx
,
1582 struct smbd_dirptr_lanman2_state
*state
=
1583 (struct smbd_dirptr_lanman2_state
*)private_data
;
1585 char mangled_name
[13]; /* mangled 8.3 name. */
1589 /* Mangle fname if it's an illegal name. */
1590 if (mangle_must_mangle(dname
, state
->conn
->params
)) {
1592 * Slow path - ensure we can push the original name as UCS2. If
1593 * not, then just don't return this name.
1597 size_t len
= (strlen(dname
) + 2) * 4; /* Allow enough space. */
1598 uint8_t *tmp
= talloc_array(talloc_tos(),
1602 status
= srvstr_push(NULL
,
1603 FLAGS2_UNICODE_STRINGS
,
1612 if (!NT_STATUS_IS_OK(status
)) {
1616 ok
= name_to_8_3(dname
, mangled_name
,
1617 true, state
->conn
->params
);
1621 fname
= mangled_name
;
1626 got_match
= exact_match(state
->has_wild
,
1627 state
->conn
->case_sensitive
,
1629 state
->got_exact_match
= got_match
;
1631 got_match
= mask_match(fname
, mask
,
1632 state
->conn
->case_sensitive
);
1635 if(!got_match
&& state
->check_mangled_names
&&
1636 !mangle_is_8_3(fname
, false, state
->conn
->params
)) {
1638 * It turns out that NT matches wildcards against
1639 * both long *and* short names. This may explain some
1640 * of the wildcard wierdness from old DOS clients
1641 * that some people have been seeing.... JRA.
1643 /* Force the mangling into 8.3. */
1644 ok
= name_to_8_3(fname
, mangled_name
,
1645 false, state
->conn
->params
);
1650 got_match
= exact_match(state
->has_wild
,
1651 state
->conn
->case_sensitive
,
1652 mangled_name
, mask
);
1653 state
->got_exact_match
= got_match
;
1655 got_match
= mask_match(mangled_name
, mask
,
1656 state
->conn
->case_sensitive
);
1664 *_fname
= talloc_strdup(ctx
, fname
);
1665 if (*_fname
== NULL
) {
1672 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX
*ctx
,
1674 struct smb_filename
*smb_fname
,
1677 struct smbd_dirptr_lanman2_state
*state
=
1678 (struct smbd_dirptr_lanman2_state
*)private_data
;
1679 bool ms_dfs_link
= false;
1682 if (INFO_LEVEL_IS_UNIX(state
->info_level
)) {
1683 if (SMB_VFS_LSTAT(state
->conn
, smb_fname
) != 0) {
1684 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1685 "Couldn't lstat [%s] (%s)\n",
1686 smb_fname_str_dbg(smb_fname
),
1690 } else if (!VALID_STAT(smb_fname
->st
) &&
1691 SMB_VFS_STAT(state
->conn
, smb_fname
) != 0) {
1692 /* Needed to show the msdfs symlinks as
1695 ms_dfs_link
= check_msdfs_link(state
->conn
,
1696 smb_fname
->base_name
,
1699 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1700 "Couldn't stat [%s] (%s)\n",
1701 smb_fname_str_dbg(smb_fname
),
1708 mode
= dos_mode_msdfs(state
->conn
, smb_fname
);
1710 mode
= dos_mode(state
->conn
, smb_fname
);
1717 static NTSTATUS
smbd_marshall_dir_entry(TALLOC_CTX
*ctx
,
1718 connection_struct
*conn
,
1720 uint32_t info_level
,
1721 struct ea_list
*name_list
,
1722 bool check_mangled_names
,
1723 bool requires_resume_key
,
1726 const struct smb_filename
*smb_fname
,
1727 int space_remaining
,
1733 uint64_t *last_entry_off
)
1735 char *p
, *q
, *pdata
= *ppdata
;
1737 uint64_t file_size
= 0;
1738 uint64_t allocation_size
= 0;
1739 uint64_t file_index
= 0;
1741 struct timespec mdate_ts
= {0};
1742 struct timespec adate_ts
= {0};
1743 struct timespec cdate_ts
= {0};
1744 struct timespec create_date_ts
= {0};
1745 time_t mdate
= (time_t)0, adate
= (time_t)0, create_date
= (time_t)0;
1747 char *last_entry_ptr
;
1752 struct readdir_attr_data
*readdir_attr_data
= NULL
;
1754 if (!(mode
& FILE_ATTRIBUTE_DIRECTORY
)) {
1755 file_size
= get_file_size_stat(&smb_fname
->st
);
1757 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
, NULL
, &smb_fname
->st
);
1759 status
= SMB_VFS_READDIR_ATTR(conn
, smb_fname
, ctx
, &readdir_attr_data
);
1760 if (!NT_STATUS_IS_OK(status
)) {
1761 if (!NT_STATUS_EQUAL(NT_STATUS_NOT_SUPPORTED
, status
)) {
1766 file_index
= get_FileIndex(conn
, &smb_fname
->st
);
1768 mdate_ts
= smb_fname
->st
.st_ex_mtime
;
1769 adate_ts
= smb_fname
->st
.st_ex_atime
;
1770 create_date_ts
= get_create_timespec(conn
, NULL
, smb_fname
);
1771 cdate_ts
= get_change_timespec(conn
, NULL
, smb_fname
);
1773 if (lp_dos_filetime_resolution(SNUM(conn
))) {
1774 dos_filetime_timespec(&create_date_ts
);
1775 dos_filetime_timespec(&mdate_ts
);
1776 dos_filetime_timespec(&adate_ts
);
1777 dos_filetime_timespec(&cdate_ts
);
1780 create_date
= convert_timespec_to_time_t(create_date_ts
);
1781 mdate
= convert_timespec_to_time_t(mdate_ts
);
1782 adate
= convert_timespec_to_time_t(adate_ts
);
1784 /* align the record */
1785 SMB_ASSERT(align
>= 1);
1787 off
= (int)PTR_DIFF(pdata
, base_data
);
1788 pad
= (off
+ (align
-1)) & ~(align
-1);
1791 if (pad
&& pad
> space_remaining
) {
1792 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1793 "for padding (wanted %u, had %d)\n",
1796 return STATUS_MORE_ENTRIES
; /* Not finished - just out of space */
1800 /* initialize padding to 0 */
1802 memset(pdata
, 0, pad
);
1804 space_remaining
-= pad
;
1806 DEBUG(10,("smbd_marshall_dir_entry: space_remaining = %d\n",
1816 switch (info_level
) {
1817 case SMB_FIND_INFO_STANDARD
:
1818 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1819 if(requires_resume_key
) {
1823 srv_put_dos_date2(p
,0,create_date
);
1824 srv_put_dos_date2(p
,4,adate
);
1825 srv_put_dos_date2(p
,8,mdate
);
1826 SIVAL(p
,12,(uint32_t)file_size
);
1827 SIVAL(p
,16,(uint32_t)allocation_size
);
1831 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1832 p
+= ucs2_align(base_data
, p
, 0);
1834 status
= srvstr_push(base_data
, flags2
, p
,
1835 fname
, PTR_DIFF(end_data
, p
),
1836 STR_TERMINATE
, &len
);
1837 if (!NT_STATUS_IS_OK(status
)) {
1840 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1842 SCVAL(nameptr
, -1, len
- 2);
1844 SCVAL(nameptr
, -1, 0);
1848 SCVAL(nameptr
, -1, len
- 1);
1850 SCVAL(nameptr
, -1, 0);
1856 case SMB_FIND_EA_SIZE
:
1857 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
1858 if (requires_resume_key
) {
1862 srv_put_dos_date2(p
,0,create_date
);
1863 srv_put_dos_date2(p
,4,adate
);
1864 srv_put_dos_date2(p
,8,mdate
);
1865 SIVAL(p
,12,(uint32_t)file_size
);
1866 SIVAL(p
,16,(uint32_t)allocation_size
);
1869 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
1871 SIVAL(p
,22,ea_size
); /* Extended attributes */
1875 status
= srvstr_push(base_data
, flags2
,
1876 p
, fname
, PTR_DIFF(end_data
, p
),
1877 STR_TERMINATE
| STR_NOALIGN
, &len
);
1878 if (!NT_STATUS_IS_OK(status
)) {
1881 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1894 SCVAL(nameptr
,0,len
);
1896 SCVAL(p
,0,0); p
+= 1; /* Extra zero byte ? - why.. */
1899 case SMB_FIND_EA_LIST
:
1901 struct ea_list
*file_list
= NULL
;
1904 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
1906 return NT_STATUS_INVALID_PARAMETER
;
1908 if (requires_resume_key
) {
1912 srv_put_dos_date2(p
,0,create_date
);
1913 srv_put_dos_date2(p
,4,adate
);
1914 srv_put_dos_date2(p
,8,mdate
);
1915 SIVAL(p
,12,(uint32_t)file_size
);
1916 SIVAL(p
,16,(uint32_t)allocation_size
);
1918 p
+= 22; /* p now points to the EA area. */
1920 status
= get_ea_list_from_file(ctx
, conn
, NULL
,
1922 &ea_len
, &file_list
);
1923 if (!NT_STATUS_IS_OK(status
)) {
1926 name_list
= ea_list_union(name_list
, file_list
, &ea_len
);
1928 /* We need to determine if this entry will fit in the space available. */
1929 /* Max string size is 255 bytes. */
1930 if (PTR_DIFF(p
+ 255 + ea_len
,pdata
) > space_remaining
) {
1931 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1932 "(wanted %u, had %d)\n",
1933 (unsigned int)PTR_DIFF(p
+ 255 + ea_len
,pdata
),
1935 return STATUS_MORE_ENTRIES
; /* Not finished - just out of space */
1938 /* Push the ea_data followed by the name. */
1939 p
+= fill_ea_buffer(ctx
, p
, space_remaining
, conn
, name_list
);
1941 status
= srvstr_push(base_data
, flags2
,
1942 p
+ 1, fname
, PTR_DIFF(end_data
, p
+1),
1943 STR_TERMINATE
| STR_NOALIGN
, &len
);
1944 if (!NT_STATUS_IS_OK(status
)) {
1947 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1960 SCVAL(nameptr
,0,len
);
1962 SCVAL(p
,0,0); p
+= 1; /* Extra zero byte ? - why.. */
1966 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
1967 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1968 was_8_3
= mangle_is_8_3(fname
, True
, conn
->params
);
1970 SIVAL(p
,0,reskey
); p
+= 4;
1971 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
1972 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
1973 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
1974 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
1975 SOFF_T(p
,0,file_size
); p
+= 8;
1976 SOFF_T(p
,0,allocation_size
); p
+= 8;
1977 SIVAL(p
,0,mode
); p
+= 4;
1978 q
= p
; p
+= 4; /* q is placeholder for name length. */
1979 if (mode
& FILE_ATTRIBUTE_REPARSE_POINT
) {
1980 SIVAL(p
, 0, IO_REPARSE_TAG_DFS
);
1982 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
1984 SIVAL(p
,0,ea_size
); /* Extended attributes */
1987 /* Clear the short name buffer. This is
1988 * IMPORTANT as not doing so will trigger
1989 * a Win2k client bug. JRA.
1991 if (!was_8_3
&& check_mangled_names
) {
1992 char mangled_name
[13]; /* mangled 8.3 name. */
1993 if (!name_to_8_3(fname
,mangled_name
,True
,
1995 /* Error - mangle failed ! */
1996 memset(mangled_name
,'\0',12);
1998 mangled_name
[12] = 0;
1999 status
= srvstr_push(base_data
, flags2
,
2000 p
+2, mangled_name
, 24,
2001 STR_UPPER
|STR_UNICODE
, &len
);
2002 if (!NT_STATUS_IS_OK(status
)) {
2006 memset(p
+ 2 + len
,'\0',24 - len
);
2013 status
= srvstr_push(base_data
, flags2
, p
,
2014 fname
, PTR_DIFF(end_data
, p
),
2015 STR_TERMINATE_ASCII
, &len
);
2016 if (!NT_STATUS_IS_OK(status
)) {
2022 len
= PTR_DIFF(p
, pdata
);
2023 pad
= (len
+ (align
-1)) & ~(align
-1);
2025 * offset to the next entry, the caller
2026 * will overwrite it for the last entry
2027 * that's why we always include the padding
2031 * set padding to zero
2034 memset(p
, 0, pad
- len
);
2041 case SMB_FIND_FILE_DIRECTORY_INFO
:
2042 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
2044 SIVAL(p
,0,reskey
); p
+= 4;
2045 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
2046 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
2047 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
2048 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
2049 SOFF_T(p
,0,file_size
); p
+= 8;
2050 SOFF_T(p
,0,allocation_size
); p
+= 8;
2051 SIVAL(p
,0,mode
); p
+= 4;
2052 status
= srvstr_push(base_data
, flags2
,
2053 p
+ 4, fname
, PTR_DIFF(end_data
, p
+4),
2054 STR_TERMINATE_ASCII
, &len
);
2055 if (!NT_STATUS_IS_OK(status
)) {
2061 len
= PTR_DIFF(p
, pdata
);
2062 pad
= (len
+ (align
-1)) & ~(align
-1);
2064 * offset to the next entry, the caller
2065 * will overwrite it for the last entry
2066 * that's why we always include the padding
2070 * set padding to zero
2073 memset(p
, 0, pad
- len
);
2080 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
2081 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
2083 SIVAL(p
,0,reskey
); p
+= 4;
2084 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
2085 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
2086 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
2087 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
2088 SOFF_T(p
,0,file_size
); p
+= 8;
2089 SOFF_T(p
,0,allocation_size
); p
+= 8;
2090 SIVAL(p
,0,mode
); p
+= 4;
2091 q
= p
; p
+= 4; /* q is placeholder for name length. */
2093 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
2095 SIVAL(p
,0,ea_size
); /* Extended attributes */
2098 status
= srvstr_push(base_data
, flags2
, p
,
2099 fname
, PTR_DIFF(end_data
, p
),
2100 STR_TERMINATE_ASCII
, &len
);
2101 if (!NT_STATUS_IS_OK(status
)) {
2107 len
= PTR_DIFF(p
, pdata
);
2108 pad
= (len
+ (align
-1)) & ~(align
-1);
2110 * offset to the next entry, the caller
2111 * will overwrite it for the last entry
2112 * that's why we always include the padding
2116 * set padding to zero
2119 memset(p
, 0, pad
- len
);
2126 case SMB_FIND_FILE_NAMES_INFO
:
2127 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
2129 SIVAL(p
,0,reskey
); p
+= 4;
2131 /* this must *not* be null terminated or w2k gets in a loop trying to set an
2132 acl on a dir (tridge) */
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_ID_FULL_DIRECTORY_INFO
:
2162 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
2164 SIVAL(p
,0,reskey
); p
+= 4;
2165 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
2166 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
2167 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
2168 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
2169 SOFF_T(p
,0,file_size
); p
+= 8;
2170 SOFF_T(p
,0,allocation_size
); p
+= 8;
2171 SIVAL(p
,0,mode
); p
+= 4;
2172 q
= p
; p
+= 4; /* q is placeholder for name length. */
2173 if (mode
& FILE_ATTRIBUTE_REPARSE_POINT
) {
2174 SIVAL(p
, 0, IO_REPARSE_TAG_DFS
);
2176 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
2178 SIVAL(p
,0,ea_size
); /* Extended attributes */
2181 SIVAL(p
,0,0); p
+= 4; /* Unknown - reserved ? */
2182 SBVAL(p
,0,file_index
); p
+= 8;
2183 status
= srvstr_push(base_data
, flags2
, p
,
2184 fname
, PTR_DIFF(end_data
, p
),
2185 STR_TERMINATE_ASCII
, &len
);
2186 if (!NT_STATUS_IS_OK(status
)) {
2192 len
= PTR_DIFF(p
, pdata
);
2193 pad
= (len
+ (align
-1)) & ~(align
-1);
2195 * offset to the next entry, the caller
2196 * will overwrite it for the last entry
2197 * that's why we always include the padding
2201 * set padding to zero
2204 memset(p
, 0, pad
- len
);
2211 case SMB_FIND_ID_BOTH_DIRECTORY_INFO
:
2212 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
2213 was_8_3
= mangle_is_8_3(fname
, True
, conn
->params
);
2215 SIVAL(p
,0,reskey
); p
+= 4;
2216 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
2217 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
2218 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
2219 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
2220 SOFF_T(p
,0,file_size
); p
+= 8;
2221 SOFF_T(p
,0,allocation_size
); p
+= 8;
2222 SIVAL(p
,0,mode
); p
+= 4;
2223 q
= p
; p
+= 4; /* q is placeholder for name length */
2224 if (mode
& FILE_ATTRIBUTE_REPARSE_POINT
) {
2225 SIVAL(p
, 0, IO_REPARSE_TAG_DFS
);
2226 } else if (readdir_attr_data
&&
2227 readdir_attr_data
->type
== RDATTR_AAPL
) {
2229 * OS X specific SMB2 extension negotiated via
2230 * AAPL create context: return max_access in
2233 SIVAL(p
, 0, readdir_attr_data
->attr_data
.aapl
.max_access
);
2235 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
2237 SIVAL(p
,0,ea_size
); /* Extended attributes */
2241 if (readdir_attr_data
&&
2242 readdir_attr_data
->type
== RDATTR_AAPL
) {
2244 * OS X specific SMB2 extension negotiated via
2245 * AAPL create context: return resource fork
2246 * length and compressed FinderInfo in
2249 * According to documentation short_name_len
2250 * should be 0, but on the wire behaviour
2251 * shows its set to 24 by clients.
2255 /* Resourefork length */
2256 SBVAL(p
, 2, readdir_attr_data
->attr_data
.aapl
.rfork_size
);
2258 /* Compressed FinderInfo */
2259 memcpy(p
+ 10, &readdir_attr_data
->attr_data
.aapl
.finder_info
, 16);
2260 } else if (!was_8_3
&& check_mangled_names
) {
2261 char mangled_name
[13]; /* mangled 8.3 name. */
2262 if (!name_to_8_3(fname
,mangled_name
,True
,
2264 /* Error - mangle failed ! */
2265 memset(mangled_name
,'\0',12);
2267 mangled_name
[12] = 0;
2268 status
= srvstr_push(base_data
, flags2
,
2269 p
+2, mangled_name
, 24,
2270 STR_UPPER
|STR_UNICODE
, &len
);
2271 if (!NT_STATUS_IS_OK(status
)) {
2276 memset(p
+ 2 + len
,'\0',24 - len
);
2280 /* Clear the short name buffer. This is
2281 * IMPORTANT as not doing so will trigger
2282 * a Win2k client bug. JRA.
2289 if (readdir_attr_data
&&
2290 readdir_attr_data
->type
== RDATTR_AAPL
) {
2292 * OS X specific SMB2 extension negotiated via
2293 * AAPL create context: return UNIX mode in
2296 uint16_t aapl_mode
= (uint16_t)readdir_attr_data
->attr_data
.aapl
.unix_mode
;
2297 SSVAL(p
, 0, aapl_mode
);
2303 SBVAL(p
,0,file_index
); p
+= 8;
2304 status
= srvstr_push(base_data
, flags2
, p
,
2305 fname
, PTR_DIFF(end_data
, p
),
2306 STR_TERMINATE_ASCII
, &len
);
2307 if (!NT_STATUS_IS_OK(status
)) {
2313 len
= PTR_DIFF(p
, pdata
);
2314 pad
= (len
+ (align
-1)) & ~(align
-1);
2316 * offset to the next entry, the caller
2317 * will overwrite it for the last entry
2318 * that's why we always include the padding
2322 * set padding to zero
2325 memset(p
, 0, pad
- len
);
2332 /* CIFS UNIX Extension. */
2334 case SMB_FIND_FILE_UNIX
:
2335 case SMB_FIND_FILE_UNIX_INFO2
:
2337 SIVAL(p
,0,reskey
); p
+= 4; /* Used for continuing search. */
2339 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
2341 if (info_level
== SMB_FIND_FILE_UNIX
) {
2342 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
2343 p
= store_file_unix_basic(conn
, p
,
2344 NULL
, &smb_fname
->st
);
2345 status
= srvstr_push(base_data
, flags2
, p
,
2346 fname
, PTR_DIFF(end_data
, p
),
2347 STR_TERMINATE
, &len
);
2348 if (!NT_STATUS_IS_OK(status
)) {
2352 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
2353 p
= store_file_unix_basic_info2(conn
, p
,
2354 NULL
, &smb_fname
->st
);
2357 status
= srvstr_push(base_data
, flags2
, p
, fname
,
2358 PTR_DIFF(end_data
, p
), 0, &len
);
2359 if (!NT_STATUS_IS_OK(status
)) {
2362 SIVAL(nameptr
, 0, len
);
2367 len
= PTR_DIFF(p
, pdata
);
2368 pad
= (len
+ (align
-1)) & ~(align
-1);
2370 * offset to the next entry, the caller
2371 * will overwrite it for the last entry
2372 * that's why we always include the padding
2376 * set padding to zero
2379 memset(p
, 0, pad
- len
);
2384 /* End of SMB_QUERY_FILE_UNIX_BASIC */
2389 return NT_STATUS_INVALID_LEVEL
;
2392 if (PTR_DIFF(p
,pdata
) > space_remaining
) {
2393 DEBUG(9,("smbd_marshall_dir_entry: out of space "
2394 "(wanted %u, had %d)\n",
2395 (unsigned int)PTR_DIFF(p
,pdata
),
2397 return STATUS_MORE_ENTRIES
; /* Not finished - just out of space */
2400 /* Setup the last entry pointer, as an offset from base_data */
2401 *last_entry_off
= PTR_DIFF(last_entry_ptr
,base_data
);
2402 /* Advance the data pointer to the next slot */
2405 return NT_STATUS_OK
;
2408 NTSTATUS
smbd_dirptr_lanman2_entry(TALLOC_CTX
*ctx
,
2409 connection_struct
*conn
,
2410 struct dptr_struct
*dirptr
,
2412 const char *path_mask
,
2415 int requires_resume_key
,
2423 int space_remaining
,
2424 bool *got_exact_match
,
2425 int *_last_entry_off
,
2426 struct ea_list
*name_list
)
2429 const char *mask
= NULL
;
2430 long prev_dirpos
= 0;
2433 struct smb_filename
*smb_fname
= NULL
;
2434 struct smbd_dirptr_lanman2_state state
;
2436 uint64_t last_entry_off
= 0;
2441 state
.info_level
= info_level
;
2442 state
.check_mangled_names
= lp_mangled_names(conn
->params
);
2443 state
.has_wild
= dptr_has_wild(dirptr
);
2444 state
.got_exact_match
= false;
2446 *got_exact_match
= false;
2448 p
= strrchr_m(path_mask
,'/');
2459 ok
= smbd_dirptr_get_entry(ctx
,
2465 smbd_dirptr_lanman2_match_fn
,
2466 smbd_dirptr_lanman2_mode_fn
,
2473 return NT_STATUS_END_OF_FILE
;
2476 *got_exact_match
= state
.got_exact_match
;
2478 status
= smbd_marshall_dir_entry(ctx
,
2483 state
.check_mangled_names
,
2484 requires_resume_key
,
2495 if (NT_STATUS_EQUAL(status
, NT_STATUS_ILLEGAL_CHARACTER
)) {
2496 DEBUG(1,("Conversion error: illegal character: %s\n",
2497 smb_fname_str_dbg(smb_fname
)));
2500 TALLOC_FREE(smb_fname
);
2501 if (NT_STATUS_EQUAL(status
, STATUS_MORE_ENTRIES
)) {
2502 dptr_SeekDir(dirptr
, prev_dirpos
);
2505 if (!NT_STATUS_IS_OK(status
)) {
2509 *_last_entry_off
= last_entry_off
;
2510 return NT_STATUS_OK
;
2513 static NTSTATUS
get_lanman2_dir_entry(TALLOC_CTX
*ctx
,
2514 connection_struct
*conn
,
2515 struct dptr_struct
*dirptr
,
2517 const char *path_mask
,
2520 bool requires_resume_key
,
2526 int space_remaining
,
2527 bool *got_exact_match
,
2528 int *last_entry_off
,
2529 struct ea_list
*name_list
)
2532 const bool do_pad
= true;
2534 if (info_level
>= 1 && info_level
<= 3) {
2535 /* No alignment on earlier info levels. */
2539 return smbd_dirptr_lanman2_entry(ctx
, conn
, dirptr
, flags2
,
2540 path_mask
, dirtype
, info_level
,
2541 requires_resume_key
, dont_descend
, ask_sharemode
,
2543 ppdata
, base_data
, end_data
,
2546 last_entry_off
, name_list
);
2549 /****************************************************************************
2550 Reply to a TRANS2_FINDFIRST.
2551 ****************************************************************************/
2553 static void call_trans2findfirst(connection_struct
*conn
,
2554 struct smb_request
*req
,
2555 char **pparams
, int total_params
,
2556 char **ppdata
, int total_data
,
2557 unsigned int max_data_bytes
)
2559 /* We must be careful here that we don't return more than the
2560 allowed number of data bytes. If this means returning fewer than
2561 maxentries then so be it. We assume that the redirector has
2562 enough room for the fixed number of parameter bytes it has
2564 struct smb_filename
*smb_dname
= NULL
;
2565 char *params
= *pparams
;
2566 char *pdata
= *ppdata
;
2570 uint16_t findfirst_flags
;
2571 bool close_after_first
;
2573 bool requires_resume_key
;
2575 char *directory
= NULL
;
2578 int last_entry_off
=0;
2582 bool finished
= False
;
2583 bool dont_descend
= False
;
2584 bool out_of_space
= False
;
2585 int space_remaining
;
2586 bool mask_contains_wcard
= False
;
2587 struct ea_list
*ea_list
= NULL
;
2588 NTSTATUS ntstatus
= NT_STATUS_OK
;
2589 bool ask_sharemode
= lp_parm_bool(SNUM(conn
), "smbd", "search ask sharemode", true);
2590 struct dptr_struct
*dirptr
= NULL
;
2591 struct smbd_server_connection
*sconn
= req
->sconn
;
2592 uint32_t ucf_flags
= UCF_SAVE_LCOMP
| UCF_ALWAYS_ALLOW_WCARD_LCOMP
|
2593 (req
->posix_pathnames
? UCF_POSIX_PATHNAMES
: 0);
2594 bool backup_priv
= false;
2595 bool as_root
= false;
2597 if (total_params
< 13) {
2598 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2602 dirtype
= SVAL(params
,0);
2603 maxentries
= SVAL(params
,2);
2604 findfirst_flags
= SVAL(params
,4);
2605 close_after_first
= (findfirst_flags
& FLAG_TRANS2_FIND_CLOSE
);
2606 close_if_end
= (findfirst_flags
& FLAG_TRANS2_FIND_CLOSE_IF_END
);
2607 requires_resume_key
= (findfirst_flags
& FLAG_TRANS2_FIND_REQUIRE_RESUME
);
2608 backup_priv
= ((findfirst_flags
& FLAG_TRANS2_FIND_BACKUP_INTENT
) &&
2609 security_token_has_privilege(get_current_nttok(conn
),
2612 info_level
= SVAL(params
,6);
2614 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2615 close_if_end = %d requires_resume_key = %d backup_priv = %d level = 0x%x, max_data_bytes = %d\n",
2616 (unsigned int)dirtype
, maxentries
, close_after_first
, close_if_end
, requires_resume_key
,
2618 info_level
, max_data_bytes
));
2621 /* W2K3 seems to treat zero as 1. */
2625 switch (info_level
) {
2626 case SMB_FIND_INFO_STANDARD
:
2627 case SMB_FIND_EA_SIZE
:
2628 case SMB_FIND_EA_LIST
:
2629 case SMB_FIND_FILE_DIRECTORY_INFO
:
2630 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
2631 case SMB_FIND_FILE_NAMES_INFO
:
2632 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
2633 case SMB_FIND_ID_FULL_DIRECTORY_INFO
:
2634 case SMB_FIND_ID_BOTH_DIRECTORY_INFO
:
2636 case SMB_FIND_FILE_UNIX
:
2637 case SMB_FIND_FILE_UNIX_INFO2
:
2638 /* Always use filesystem for UNIX mtime query. */
2639 ask_sharemode
= false;
2640 if (!lp_unix_extensions()) {
2641 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2644 ucf_flags
|= UCF_UNIX_NAME_LOOKUP
;
2647 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2651 if (req
->posix_pathnames
) {
2652 srvstr_get_path_wcard_posix(talloc_tos(),
2660 &mask_contains_wcard
);
2662 srvstr_get_path_wcard(talloc_tos(),
2670 &mask_contains_wcard
);
2672 if (!NT_STATUS_IS_OK(ntstatus
)) {
2673 reply_nterror(req
, ntstatus
);
2680 ntstatus
= filename_convert_with_privilege(talloc_tos(),
2685 &mask_contains_wcard
,
2688 ntstatus
= filename_convert(talloc_tos(), conn
,
2689 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
2692 &mask_contains_wcard
,
2696 if (!NT_STATUS_IS_OK(ntstatus
)) {
2697 if (NT_STATUS_EQUAL(ntstatus
,NT_STATUS_PATH_NOT_COVERED
)) {
2698 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
2699 ERRSRV
, ERRbadpath
);
2702 reply_nterror(req
, ntstatus
);
2706 mask
= smb_dname
->original_lcomp
;
2708 directory
= smb_dname
->base_name
;
2710 p
= strrchr_m(directory
,'/');
2712 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2713 if((directory
[0] == '.') && (directory
[1] == '\0')) {
2714 mask
= talloc_strdup(talloc_tos(),"*");
2716 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2719 mask_contains_wcard
= True
;
2725 if (p
== NULL
|| p
== directory
) {
2726 /* Ensure we don't have a directory name of "". */
2727 directory
= talloc_strdup(talloc_tos(), ".");
2729 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2732 /* Ensure smb_dname->base_name matches. */
2733 smb_dname
->base_name
= directory
;
2736 DEBUG(5,("dir=%s, mask = %s\n",directory
, mask
));
2738 if (info_level
== SMB_FIND_EA_LIST
) {
2741 if (total_data
< 4) {
2742 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2746 ea_size
= IVAL(pdata
,0);
2747 if (ea_size
!= total_data
) {
2748 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2749 total_data=%u (should be %u)\n", (unsigned int)total_data
, (unsigned int)IVAL(pdata
,0) ));
2750 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2754 if (!lp_ea_support(SNUM(conn
))) {
2755 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
2759 /* Pull out the list of names. */
2760 ea_list
= read_ea_name_list(talloc_tos(), pdata
+ 4, ea_size
- 4);
2762 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2767 if (max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
< max_data_bytes
) {
2768 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2772 *ppdata
= (char *)SMB_REALLOC(
2773 *ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
2774 if(*ppdata
== NULL
) {
2775 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2779 data_end
= pdata
+ max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
- 1;
2781 * squash valgrind "writev(vector[...]) points to uninitialised byte(s)"
2784 memset(pdata
+ total_data
, 0, ((max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
) - total_data
));
2785 /* Realloc the params space */
2786 *pparams
= (char *)SMB_REALLOC(*pparams
, 10);
2787 if (*pparams
== NULL
) {
2788 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2793 /* Save the wildcard match and attribs we are using on this directory -
2794 needed as lanman2 assumes these are being saved between calls */
2796 ntstatus
= dptr_create(conn
,
2804 mask_contains_wcard
,
2808 if (!NT_STATUS_IS_OK(ntstatus
)) {
2809 reply_nterror(req
, ntstatus
);
2814 /* Remember this in case we have
2815 to do a findnext. */
2816 dptr_set_priv(dirptr
);
2819 dptr_num
= dptr_dnum(dirptr
);
2820 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num
, mask
, dirtype
));
2822 /* Initialize per TRANS2_FIND_FIRST operation data */
2823 dptr_init_search_op(dirptr
);
2825 /* We don't need to check for VOL here as this is returned by
2826 a different TRANS2 call. */
2828 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2829 directory
,lp_dont_descend(talloc_tos(), SNUM(conn
))));
2830 if (in_list(directory
,
2831 lp_dont_descend(talloc_tos(), SNUM(conn
)),
2832 conn
->case_sensitive
)) {
2833 dont_descend
= True
;
2837 space_remaining
= max_data_bytes
;
2838 out_of_space
= False
;
2840 for (i
=0;(i
<maxentries
) && !finished
&& !out_of_space
;i
++) {
2841 bool got_exact_match
= False
;
2843 /* this is a heuristic to avoid seeking the dirptr except when
2844 absolutely necessary. It allows for a filename of about 40 chars */
2845 if (space_remaining
< DIRLEN_GUESS
&& numentries
> 0) {
2846 out_of_space
= True
;
2849 ntstatus
= get_lanman2_dir_entry(talloc_tos(),
2853 mask
,dirtype
,info_level
,
2854 requires_resume_key
,dont_descend
,
2859 &last_entry_off
, ea_list
);
2860 if (NT_STATUS_EQUAL(ntstatus
,
2861 NT_STATUS_ILLEGAL_CHARACTER
)) {
2863 * Bad character conversion on name. Ignore this
2868 if (NT_STATUS_EQUAL(ntstatus
, STATUS_MORE_ENTRIES
)) {
2869 out_of_space
= true;
2871 finished
= !NT_STATUS_IS_OK(ntstatus
);
2875 if (!finished
&& !out_of_space
)
2879 * As an optimisation if we know we aren't looking
2880 * for a wildcard name (ie. the name matches the wildcard exactly)
2881 * then we can finish on any (first) match.
2882 * This speeds up large directory searches. JRA.
2888 /* Ensure space_remaining never goes -ve. */
2889 if (PTR_DIFF(p
,pdata
) > max_data_bytes
) {
2890 space_remaining
= 0;
2891 out_of_space
= true;
2893 space_remaining
= max_data_bytes
- PTR_DIFF(p
,pdata
);
2897 /* Check if we can close the dirptr */
2898 if(close_after_first
|| (finished
&& close_if_end
)) {
2899 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num
));
2900 dptr_close(sconn
, &dptr_num
);
2904 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2905 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2906 * the protocol level is less than NT1. Tested with smbclient. JRA.
2907 * This should fix the OS/2 client bug #2335.
2910 if(numentries
== 0) {
2911 dptr_close(sconn
, &dptr_num
);
2912 if (get_Protocol() < PROTOCOL_NT1
) {
2913 reply_force_doserror(req
, ERRDOS
, ERRnofiles
);
2916 reply_botherror(req
, NT_STATUS_NO_SUCH_FILE
,
2917 ERRDOS
, ERRbadfile
);
2922 /* At this point pdata points to numentries directory entries. */
2924 /* Set up the return parameter block */
2925 SSVAL(params
,0,dptr_num
);
2926 SSVAL(params
,2,numentries
);
2927 SSVAL(params
,4,finished
);
2928 SSVAL(params
,6,0); /* Never an EA error */
2929 SSVAL(params
,8,last_entry_off
);
2931 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 10, pdata
, PTR_DIFF(p
,pdata
),
2934 if ((! *directory
) && dptr_path(sconn
, dptr_num
)) {
2935 directory
= talloc_strdup(talloc_tos(),dptr_path(sconn
, dptr_num
));
2937 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2941 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2942 smb_fn_name(req
->cmd
),
2943 mask
, directory
, dirtype
, numentries
) );
2946 * Force a name mangle here to ensure that the
2947 * mask as an 8.3 name is top of the mangled cache.
2948 * The reasons for this are subtle. Don't remove
2949 * this code unless you know what you are doing
2950 * (see PR#13758). JRA.
2953 if(!mangle_is_8_3_wildcards( mask
, False
, conn
->params
)) {
2954 char mangled_name
[13];
2955 name_to_8_3(mask
, mangled_name
, True
, conn
->params
);
2963 TALLOC_FREE(smb_dname
);
2967 /****************************************************************************
2968 Reply to a TRANS2_FINDNEXT.
2969 ****************************************************************************/
2971 static void call_trans2findnext(connection_struct
*conn
,
2972 struct smb_request
*req
,
2973 char **pparams
, int total_params
,
2974 char **ppdata
, int total_data
,
2975 unsigned int max_data_bytes
)
2977 /* We must be careful here that we don't return more than the
2978 allowed number of data bytes. If this means returning fewer than
2979 maxentries then so be it. We assume that the redirector has
2980 enough room for the fixed number of parameter bytes it has
2982 char *params
= *pparams
;
2983 char *pdata
= *ppdata
;
2987 uint16_t info_level
;
2988 uint32_t resume_key
;
2989 uint16_t findnext_flags
;
2990 bool close_after_request
;
2992 bool requires_resume_key
;
2994 bool mask_contains_wcard
= False
;
2995 char *resume_name
= NULL
;
2996 const char *mask
= NULL
;
2997 const char *directory
= NULL
;
3001 int i
, last_entry_off
=0;
3002 bool finished
= False
;
3003 bool dont_descend
= False
;
3004 bool out_of_space
= False
;
3005 int space_remaining
;
3006 struct ea_list
*ea_list
= NULL
;
3007 NTSTATUS ntstatus
= NT_STATUS_OK
;
3008 bool ask_sharemode
= lp_parm_bool(SNUM(conn
), "smbd", "search ask sharemode", true);
3009 TALLOC_CTX
*ctx
= talloc_tos();
3010 struct dptr_struct
*dirptr
;
3011 struct smbd_server_connection
*sconn
= req
->sconn
;
3012 bool backup_priv
= false;
3013 bool as_root
= false;
3015 if (total_params
< 13) {
3016 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3020 dptr_num
= SVAL(params
,0);
3021 maxentries
= SVAL(params
,2);
3022 info_level
= SVAL(params
,4);
3023 resume_key
= IVAL(params
,6);
3024 findnext_flags
= SVAL(params
,10);
3025 close_after_request
= (findnext_flags
& FLAG_TRANS2_FIND_CLOSE
);
3026 close_if_end
= (findnext_flags
& FLAG_TRANS2_FIND_CLOSE_IF_END
);
3027 requires_resume_key
= (findnext_flags
& FLAG_TRANS2_FIND_REQUIRE_RESUME
);
3028 continue_bit
= (findnext_flags
& FLAG_TRANS2_FIND_CONTINUE
);
3030 if (!continue_bit
) {
3031 /* We only need resume_name if continue_bit is zero. */
3032 if (req
->posix_pathnames
) {
3033 srvstr_get_path_wcard_posix(ctx
,
3041 &mask_contains_wcard
);
3043 srvstr_get_path_wcard(ctx
,
3051 &mask_contains_wcard
);
3053 if (!NT_STATUS_IS_OK(ntstatus
)) {
3054 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
3055 complain (it thinks we're asking for the directory above the shared
3056 path or an invalid name). Catch this as the resume name is only compared, never used in
3057 a file access. JRA. */
3058 srvstr_pull_talloc(ctx
, params
, req
->flags2
,
3059 &resume_name
, params
+12,
3063 if (!resume_name
|| !(ISDOT(resume_name
) || ISDOTDOT(resume_name
))) {
3064 reply_nterror(req
, ntstatus
);
3070 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
3071 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
3072 resume_key = %d resume name = %s continue=%d level = %d\n",
3073 dptr_num
, max_data_bytes
, maxentries
, close_after_request
, close_if_end
,
3074 requires_resume_key
, resume_key
,
3075 resume_name
? resume_name
: "(NULL)", continue_bit
, info_level
));
3078 /* W2K3 seems to treat zero as 1. */
3082 switch (info_level
) {
3083 case SMB_FIND_INFO_STANDARD
:
3084 case SMB_FIND_EA_SIZE
:
3085 case SMB_FIND_EA_LIST
:
3086 case SMB_FIND_FILE_DIRECTORY_INFO
:
3087 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
3088 case SMB_FIND_FILE_NAMES_INFO
:
3089 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
3090 case SMB_FIND_ID_FULL_DIRECTORY_INFO
:
3091 case SMB_FIND_ID_BOTH_DIRECTORY_INFO
:
3093 case SMB_FIND_FILE_UNIX
:
3094 case SMB_FIND_FILE_UNIX_INFO2
:
3095 /* Always use filesystem for UNIX mtime query. */
3096 ask_sharemode
= false;
3097 if (!lp_unix_extensions()) {
3098 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
3103 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
3107 if (info_level
== SMB_FIND_EA_LIST
) {
3110 if (total_data
< 4) {
3111 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3115 ea_size
= IVAL(pdata
,0);
3116 if (ea_size
!= total_data
) {
3117 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
3118 total_data=%u (should be %u)\n", (unsigned int)total_data
, (unsigned int)IVAL(pdata
,0) ));
3119 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3123 if (!lp_ea_support(SNUM(conn
))) {
3124 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
3128 /* Pull out the list of names. */
3129 ea_list
= read_ea_name_list(ctx
, pdata
+ 4, ea_size
- 4);
3131 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3136 if (max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
< max_data_bytes
) {
3137 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3141 *ppdata
= (char *)SMB_REALLOC(
3142 *ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
3143 if(*ppdata
== NULL
) {
3144 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
3149 data_end
= pdata
+ max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
- 1;
3152 * squash valgrind "writev(vector[...]) points to uninitialised byte(s)"
3155 memset(pdata
+ total_data
, 0, (max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
) - total_data
);
3156 /* Realloc the params space */
3157 *pparams
= (char *)SMB_REALLOC(*pparams
, 6*SIZEOFWORD
);
3158 if(*pparams
== NULL
) {
3159 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
3165 /* Check that the dptr is valid */
3166 if(!(dirptr
= dptr_fetch_lanman2(sconn
, dptr_num
))) {
3167 reply_nterror(req
, STATUS_NO_MORE_FILES
);
3171 directory
= dptr_path(sconn
, dptr_num
);
3173 /* Get the wildcard mask from the dptr */
3174 if((mask
= dptr_wcard(sconn
, dptr_num
))== NULL
) {
3175 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num
));
3176 reply_nterror(req
, STATUS_NO_MORE_FILES
);
3180 /* Get the attr mask from the dptr */
3181 dirtype
= dptr_attr(sconn
, dptr_num
);
3183 backup_priv
= dptr_get_priv(dirptr
);
3185 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld) "
3186 "backup_priv = %d\n",
3187 dptr_num
, mask
, dirtype
,
3189 dptr_TellDir(dirptr
),
3192 /* Initialize per TRANS2_FIND_NEXT operation data */
3193 dptr_init_search_op(dirptr
);
3195 /* We don't need to check for VOL here as this is returned by
3196 a different TRANS2 call. */
3198 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
3199 directory
,lp_dont_descend(ctx
, SNUM(conn
))));
3200 if (in_list(directory
,lp_dont_descend(ctx
, SNUM(conn
)),conn
->case_sensitive
))
3201 dont_descend
= True
;
3204 space_remaining
= max_data_bytes
;
3205 out_of_space
= False
;
3213 * Seek to the correct position. We no longer use the resume key but
3214 * depend on the last file name instead.
3217 if(!continue_bit
&& resume_name
&& *resume_name
) {
3220 long current_pos
= 0;
3222 * Remember, name_to_8_3 is called by
3223 * get_lanman2_dir_entry(), so the resume name
3224 * could be mangled. Ensure we check the unmangled name.
3227 if (mangle_is_mangled(resume_name
, conn
->params
)) {
3228 char *new_resume_name
= NULL
;
3229 mangle_lookup_name_from_8_3(ctx
,
3233 if (new_resume_name
) {
3234 resume_name
= new_resume_name
;
3239 * Fix for NT redirector problem triggered by resume key indexes
3240 * changing between directory scans. We now return a resume key of 0
3241 * and instead look for the filename to continue from (also given
3242 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
3243 * findfirst/findnext (as is usual) then the directory pointer
3244 * should already be at the correct place.
3247 finished
= !dptr_SearchDir(dirptr
, resume_name
, ¤t_pos
, &st
);
3248 } /* end if resume_name && !continue_bit */
3250 for (i
=0;(i
<(int)maxentries
) && !finished
&& !out_of_space
;i
++) {
3251 bool got_exact_match
= False
;
3253 /* this is a heuristic to avoid seeking the dirptr except when
3254 absolutely necessary. It allows for a filename of about 40 chars */
3255 if (space_remaining
< DIRLEN_GUESS
&& numentries
> 0) {
3256 out_of_space
= True
;
3259 ntstatus
= get_lanman2_dir_entry(ctx
,
3263 mask
,dirtype
,info_level
,
3264 requires_resume_key
,dont_descend
,
3269 &last_entry_off
, ea_list
);
3270 if (NT_STATUS_EQUAL(ntstatus
,
3271 NT_STATUS_ILLEGAL_CHARACTER
)) {
3273 * Bad character conversion on name. Ignore this
3278 if (NT_STATUS_EQUAL(ntstatus
, STATUS_MORE_ENTRIES
)) {
3279 out_of_space
= true;
3281 finished
= !NT_STATUS_IS_OK(ntstatus
);
3285 if (!finished
&& !out_of_space
)
3289 * As an optimisation if we know we aren't looking
3290 * for a wildcard name (ie. the name matches the wildcard exactly)
3291 * then we can finish on any (first) match.
3292 * This speeds up large directory searches. JRA.
3298 space_remaining
= max_data_bytes
- PTR_DIFF(p
,pdata
);
3301 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
3302 smb_fn_name(req
->cmd
),
3303 mask
, directory
, dirtype
, numentries
) );
3305 /* Check if we can close the dirptr */
3306 if(close_after_request
|| (finished
&& close_if_end
)) {
3307 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num
));
3308 dptr_close(sconn
, &dptr_num
); /* This frees up the saved mask */
3315 /* Set up the return parameter block */
3316 SSVAL(params
,0,numentries
);
3317 SSVAL(params
,2,finished
);
3318 SSVAL(params
,4,0); /* Never an EA error */
3319 SSVAL(params
,6,last_entry_off
);
3321 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 8, pdata
, PTR_DIFF(p
,pdata
),
3327 unsigned char *create_volume_objectid(connection_struct
*conn
, unsigned char objid
[16])
3329 E_md4hash(lp_servicename(talloc_tos(), SNUM(conn
)),objid
);
3333 static void samba_extended_info_version(struct smb_extended_info
*extended_info
)
3335 SMB_ASSERT(extended_info
!= NULL
);
3337 extended_info
->samba_magic
= SAMBA_EXTENDED_INFO_MAGIC
;
3338 extended_info
->samba_version
= ((SAMBA_VERSION_MAJOR
& 0xff) << 24)
3339 | ((SAMBA_VERSION_MINOR
& 0xff) << 16)
3340 | ((SAMBA_VERSION_RELEASE
& 0xff) << 8);
3341 #ifdef SAMBA_VERSION_REVISION
3342 extended_info
->samba_version
|= (tolower(*SAMBA_VERSION_REVISION
) - 'a' + 1) & 0xff;
3344 extended_info
->samba_subversion
= 0;
3345 #ifdef SAMBA_VERSION_RC_RELEASE
3346 extended_info
->samba_subversion
|= (SAMBA_VERSION_RC_RELEASE
& 0xff) << 24;
3348 #ifdef SAMBA_VERSION_PRE_RELEASE
3349 extended_info
->samba_subversion
|= (SAMBA_VERSION_PRE_RELEASE
& 0xff) << 16;
3352 #ifdef SAMBA_VERSION_VENDOR_PATCH
3353 extended_info
->samba_subversion
|= (SAMBA_VERSION_VENDOR_PATCH
& 0xffff);
3355 extended_info
->samba_gitcommitdate
= 0;
3356 #ifdef SAMBA_VERSION_COMMIT_TIME
3357 unix_to_nt_time(&extended_info
->samba_gitcommitdate
, SAMBA_VERSION_COMMIT_TIME
);
3360 memset(extended_info
->samba_version_string
, 0,
3361 sizeof(extended_info
->samba_version_string
));
3363 snprintf (extended_info
->samba_version_string
,
3364 sizeof(extended_info
->samba_version_string
),
3365 "%s", samba_version_string());
3368 NTSTATUS
smbd_do_qfsinfo(struct smbXsrv_connection
*xconn
,
3369 connection_struct
*conn
,
3370 TALLOC_CTX
*mem_ctx
,
3371 uint16_t info_level
,
3373 unsigned int max_data_bytes
,
3374 size_t *fixed_portion
,
3375 struct smb_filename
*fname
,
3379 char *pdata
, *end_data
;
3382 const char *vname
= volume_label(talloc_tos(), SNUM(conn
));
3383 int snum
= SNUM(conn
);
3384 const char *fstype
= lp_fstype(SNUM(conn
));
3385 const char *filename
= NULL
;
3386 const uint64_t bytes_per_sector
= 512;
3387 uint32_t additional_flags
= 0;
3388 struct smb_filename smb_fname
;
3390 NTSTATUS status
= NT_STATUS_OK
;
3393 if (fname
== NULL
|| fname
->base_name
== NULL
) {
3396 filename
= fname
->base_name
;
3400 if (info_level
!= SMB_QUERY_CIFS_UNIX_INFO
) {
3401 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
3402 "info level (0x%x) on IPC$.\n",
3403 (unsigned int)info_level
));
3404 return NT_STATUS_ACCESS_DENIED
;
3408 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level
));
3410 ZERO_STRUCT(smb_fname
);
3411 smb_fname
.base_name
= discard_const_p(char, filename
);
3413 if(SMB_VFS_STAT(conn
, &smb_fname
) != 0) {
3414 DEBUG(2,("stat of . failed (%s)\n", strerror(errno
)));
3415 return map_nt_error_from_unix(errno
);
3420 if (max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
< max_data_bytes
) {
3421 return NT_STATUS_INVALID_PARAMETER
;
3424 *ppdata
= (char *)SMB_REALLOC(
3425 *ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
3426 if (*ppdata
== NULL
) {
3427 return NT_STATUS_NO_MEMORY
;
3431 memset((char *)pdata
,'\0',max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
3432 end_data
= pdata
+ max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
- 1;
3436 switch (info_level
) {
3437 case SMB_INFO_ALLOCATION
:
3439 uint64_t dfree
,dsize
,bsize
,block_size
,sectors_per_unit
;
3441 df_ret
= get_dfree_info(conn
, filename
, &bsize
, &dfree
,
3443 if (df_ret
== (uint64_t)-1) {
3444 return map_nt_error_from_unix(errno
);
3447 block_size
= lp_block_size(snum
);
3448 if (bsize
< block_size
) {
3449 uint64_t factor
= block_size
/bsize
;
3454 if (bsize
> block_size
) {
3455 uint64_t factor
= bsize
/block_size
;
3460 sectors_per_unit
= bsize
/bytes_per_sector
;
3462 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
3463 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st
.st_ex_dev
, (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
3464 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
3466 SIVAL(pdata
,l1_idFileSystem
,st
.st_ex_dev
);
3467 SIVAL(pdata
,l1_cSectorUnit
,sectors_per_unit
);
3468 SIVAL(pdata
,l1_cUnit
,dsize
);
3469 SIVAL(pdata
,l1_cUnitAvail
,dfree
);
3470 SSVAL(pdata
,l1_cbSector
,bytes_per_sector
);
3474 case SMB_INFO_VOLUME
:
3475 /* Return volume name */
3477 * Add volume serial number - hash of a combination of
3478 * the called hostname and the service name.
3480 SIVAL(pdata
,0,str_checksum(lp_servicename(talloc_tos(), snum
)) ^ (str_checksum(get_local_machine_name())<<16) );
3482 * Win2k3 and previous mess this up by sending a name length
3483 * one byte short. I believe only older clients (OS/2 Win9x) use
3484 * this call so try fixing this by adding a terminating null to
3485 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
3487 status
= srvstr_push(
3489 pdata
+l2_vol_szVolLabel
, vname
,
3490 PTR_DIFF(end_data
, pdata
+l2_vol_szVolLabel
),
3491 STR_NOALIGN
|STR_TERMINATE
, &len
);
3492 if (!NT_STATUS_IS_OK(status
)) {
3495 SCVAL(pdata
,l2_vol_cch
,len
);
3496 data_len
= l2_vol_szVolLabel
+ len
;
3497 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %u, name = %s\n",
3498 (unsigned)convert_timespec_to_time_t(st
.st_ex_ctime
),
3499 (unsigned)len
, vname
));
3502 case SMB_QUERY_FS_ATTRIBUTE_INFO
:
3503 case SMB_FS_ATTRIBUTE_INFORMATION
:
3505 additional_flags
= 0;
3506 #if defined(HAVE_SYS_QUOTAS)
3507 additional_flags
|= FILE_VOLUME_QUOTAS
;
3510 if(lp_nt_acl_support(SNUM(conn
))) {
3511 additional_flags
|= FILE_PERSISTENT_ACLS
;
3514 /* Capabilities are filled in at connection time through STATVFS call */
3515 additional_flags
|= conn
->fs_capabilities
;
3516 additional_flags
|= lp_parm_int(conn
->params
->service
,
3517 "share", "fake_fscaps",
3520 SIVAL(pdata
,0,FILE_CASE_PRESERVED_NAMES
|FILE_CASE_SENSITIVE_SEARCH
|
3521 FILE_SUPPORTS_OBJECT_IDS
|FILE_UNICODE_ON_DISK
|
3522 additional_flags
); /* FS ATTRIBUTES */
3524 SIVAL(pdata
,4,255); /* Max filename component length */
3525 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
3526 and will think we can't do long filenames */
3527 status
= srvstr_push(pdata
, flags2
, pdata
+12, fstype
,
3528 PTR_DIFF(end_data
, pdata
+12),
3530 if (!NT_STATUS_IS_OK(status
)) {
3534 data_len
= 12 + len
;
3535 if (max_data_bytes
>= 16 && data_len
> max_data_bytes
) {
3536 /* the client only requested a portion of the
3538 data_len
= max_data_bytes
;
3539 status
= STATUS_BUFFER_OVERFLOW
;
3541 *fixed_portion
= 16;
3544 case SMB_QUERY_FS_LABEL_INFO
:
3545 case SMB_FS_LABEL_INFORMATION
:
3546 status
= srvstr_push(pdata
, flags2
, pdata
+4, vname
,
3547 PTR_DIFF(end_data
, pdata
+4), 0, &len
);
3548 if (!NT_STATUS_IS_OK(status
)) {
3555 case SMB_QUERY_FS_VOLUME_INFO
:
3556 case SMB_FS_VOLUME_INFORMATION
:
3559 * Add volume serial number - hash of a combination of
3560 * the called hostname and the service name.
3562 SIVAL(pdata
,8,str_checksum(lp_servicename(talloc_tos(), snum
)) ^
3563 (str_checksum(get_local_machine_name())<<16));
3565 /* Max label len is 32 characters. */
3566 status
= srvstr_push(pdata
, flags2
, pdata
+18, vname
,
3567 PTR_DIFF(end_data
, pdata
+18),
3569 if (!NT_STATUS_IS_OK(status
)) {
3572 SIVAL(pdata
,12,len
);
3575 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3576 (int)strlen(vname
),vname
,
3577 lp_servicename(talloc_tos(), snum
)));
3578 if (max_data_bytes
>= 24 && data_len
> max_data_bytes
) {
3579 /* the client only requested a portion of the
3581 data_len
= max_data_bytes
;
3582 status
= STATUS_BUFFER_OVERFLOW
;
3584 *fixed_portion
= 24;
3587 case SMB_QUERY_FS_SIZE_INFO
:
3588 case SMB_FS_SIZE_INFORMATION
:
3590 uint64_t dfree
,dsize
,bsize
,block_size
,sectors_per_unit
;
3592 df_ret
= get_dfree_info(conn
, filename
, &bsize
, &dfree
,
3594 if (df_ret
== (uint64_t)-1) {
3595 return map_nt_error_from_unix(errno
);
3597 block_size
= lp_block_size(snum
);
3598 if (bsize
< block_size
) {
3599 uint64_t factor
= block_size
/bsize
;
3604 if (bsize
> block_size
) {
3605 uint64_t factor
= bsize
/block_size
;
3610 sectors_per_unit
= bsize
/bytes_per_sector
;
3611 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3612 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
3613 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
3614 SBIG_UINT(pdata
,0,dsize
);
3615 SBIG_UINT(pdata
,8,dfree
);
3616 SIVAL(pdata
,16,sectors_per_unit
);
3617 SIVAL(pdata
,20,bytes_per_sector
);
3618 *fixed_portion
= 24;
3622 case SMB_FS_FULL_SIZE_INFORMATION
:
3624 uint64_t dfree
,dsize
,bsize
,block_size
,sectors_per_unit
;
3626 df_ret
= get_dfree_info(conn
, filename
, &bsize
, &dfree
,
3628 if (df_ret
== (uint64_t)-1) {
3629 return map_nt_error_from_unix(errno
);
3631 block_size
= lp_block_size(snum
);
3632 if (bsize
< block_size
) {
3633 uint64_t factor
= block_size
/bsize
;
3638 if (bsize
> block_size
) {
3639 uint64_t factor
= bsize
/block_size
;
3644 sectors_per_unit
= bsize
/bytes_per_sector
;
3645 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3646 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
3647 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
3648 SBIG_UINT(pdata
,0,dsize
); /* Total Allocation units. */
3649 SBIG_UINT(pdata
,8,dfree
); /* Caller available allocation units. */
3650 SBIG_UINT(pdata
,16,dfree
); /* Actual available allocation units. */
3651 SIVAL(pdata
,24,sectors_per_unit
); /* Sectors per allocation unit. */
3652 SIVAL(pdata
,28,bytes_per_sector
); /* Bytes per sector. */
3653 *fixed_portion
= 32;
3657 case SMB_QUERY_FS_DEVICE_INFO
:
3658 case SMB_FS_DEVICE_INFORMATION
:
3660 uint32_t characteristics
= FILE_DEVICE_IS_MOUNTED
;
3662 if (!CAN_WRITE(conn
)) {
3663 characteristics
|= FILE_READ_ONLY_DEVICE
;
3666 SIVAL(pdata
,0,FILE_DEVICE_DISK
); /* dev type */
3667 SIVAL(pdata
,4,characteristics
);
3672 #ifdef HAVE_SYS_QUOTAS
3673 case SMB_FS_QUOTA_INFORMATION
:
3675 * what we have to send --metze:
3677 * Unknown1: 24 NULL bytes
3678 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3679 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3680 * Quota Flags: 2 byte :
3681 * Unknown3: 6 NULL bytes
3685 * details for Quota Flags:
3687 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3688 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3689 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3690 * 0x0001 Enable Quotas: enable quota for this fs
3694 /* we need to fake up a fsp here,
3695 * because its not send in this call
3698 SMB_NTQUOTA_STRUCT quotas
;
3701 ZERO_STRUCT(quotas
);
3704 fsp
.fnum
= FNUM_FIELD_INVALID
;
3707 if (get_current_uid(conn
) != 0) {
3708 DEBUG(0,("get_user_quota: access_denied "
3709 "service [%s] user [%s]\n",
3710 lp_servicename(talloc_tos(), SNUM(conn
)),
3711 conn
->session_info
->unix_info
->unix_name
));
3712 return NT_STATUS_ACCESS_DENIED
;
3715 status
= vfs_get_ntquota(&fsp
, SMB_USER_FS_QUOTA_TYPE
,
3717 if (!NT_STATUS_IS_OK(status
)) {
3718 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn
))));
3724 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3725 lp_servicename(talloc_tos(), SNUM(conn
))));
3727 /* Unknown1 24 NULL bytes*/
3728 SBIG_UINT(pdata
,0,(uint64_t)0);
3729 SBIG_UINT(pdata
,8,(uint64_t)0);
3730 SBIG_UINT(pdata
,16,(uint64_t)0);
3732 /* Default Soft Quota 8 bytes */
3733 SBIG_UINT(pdata
,24,quotas
.softlim
);
3735 /* Default Hard Quota 8 bytes */
3736 SBIG_UINT(pdata
,32,quotas
.hardlim
);
3738 /* Quota flag 2 bytes */
3739 SSVAL(pdata
,40,quotas
.qflags
);
3741 /* Unknown3 6 NULL bytes */
3747 #endif /* HAVE_SYS_QUOTAS */
3748 case SMB_FS_OBJECTID_INFORMATION
:
3750 unsigned char objid
[16];
3751 struct smb_extended_info extended_info
;
3752 memcpy(pdata
,create_volume_objectid(conn
, objid
),16);
3753 samba_extended_info_version (&extended_info
);
3754 SIVAL(pdata
,16,extended_info
.samba_magic
);
3755 SIVAL(pdata
,20,extended_info
.samba_version
);
3756 SIVAL(pdata
,24,extended_info
.samba_subversion
);
3757 SBIG_UINT(pdata
,28,extended_info
.samba_gitcommitdate
);
3758 memcpy(pdata
+36,extended_info
.samba_version_string
,28);
3763 case SMB_FS_SECTOR_SIZE_INFORMATION
:
3767 * These values match a physical Windows Server 2012
3768 * share backed by NTFS atop spinning rust.
3770 DEBUG(5, ("SMB_FS_SECTOR_SIZE_INFORMATION:"));
3771 /* logical_bytes_per_sector */
3772 SIVAL(pdata
, 0, bytes_per_sector
);
3773 /* phys_bytes_per_sector_atomic */
3774 SIVAL(pdata
, 4, bytes_per_sector
);
3775 /* phys_bytes_per_sector_perf */
3776 SIVAL(pdata
, 8, bytes_per_sector
);
3777 /* fs_effective_phys_bytes_per_sector_atomic */
3778 SIVAL(pdata
, 12, bytes_per_sector
);
3780 SIVAL(pdata
, 16, SSINFO_FLAGS_ALIGNED_DEVICE
3781 | SSINFO_FLAGS_PARTITION_ALIGNED_ON_DEVICE
);
3782 /* byte_off_sector_align */
3783 SIVAL(pdata
, 20, 0);
3784 /* byte_off_partition_align */
3785 SIVAL(pdata
, 24, 0);
3786 *fixed_portion
= 28;
3792 * Query the version and capabilities of the CIFS UNIX extensions
3796 case SMB_QUERY_CIFS_UNIX_INFO
:
3798 bool large_write
= lp_min_receive_file_size() &&
3799 !srv_is_signing_active(xconn
);
3800 bool large_read
= !srv_is_signing_active(xconn
);
3801 int encrypt_caps
= 0;
3803 if (!lp_unix_extensions()) {
3804 return NT_STATUS_INVALID_LEVEL
;
3807 switch (conn
->encrypt_level
) {
3808 case SMB_SIGNING_OFF
:
3811 case SMB_SIGNING_DESIRED
:
3812 case SMB_SIGNING_IF_REQUIRED
:
3813 case SMB_SIGNING_DEFAULT
:
3814 encrypt_caps
= CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP
;
3816 case SMB_SIGNING_REQUIRED
:
3817 encrypt_caps
= CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP
|
3818 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP
;
3819 large_write
= false;
3825 SSVAL(pdata
,0,CIFS_UNIX_MAJOR_VERSION
);
3826 SSVAL(pdata
,2,CIFS_UNIX_MINOR_VERSION
);
3828 /* We have POSIX ACLs, pathname, encryption,
3829 * large read/write, and locking capability. */
3831 SBIG_UINT(pdata
,4,((uint64_t)(
3832 CIFS_UNIX_POSIX_ACLS_CAP
|
3833 CIFS_UNIX_POSIX_PATHNAMES_CAP
|
3834 CIFS_UNIX_FCNTL_LOCKS_CAP
|
3835 CIFS_UNIX_EXTATTR_CAP
|
3836 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP
|
3838 (large_read
? CIFS_UNIX_LARGE_READ_CAP
: 0) |
3840 CIFS_UNIX_LARGE_WRITE_CAP
: 0))));
3844 case SMB_QUERY_POSIX_FS_INFO
:
3847 vfs_statvfs_struct svfs
;
3849 if (!lp_unix_extensions()) {
3850 return NT_STATUS_INVALID_LEVEL
;
3853 rc
= SMB_VFS_STATVFS(conn
, filename
, &svfs
);
3857 SIVAL(pdata
,0,svfs
.OptimalTransferSize
);
3858 SIVAL(pdata
,4,svfs
.BlockSize
);
3859 SBIG_UINT(pdata
,8,svfs
.TotalBlocks
);
3860 SBIG_UINT(pdata
,16,svfs
.BlocksAvail
);
3861 SBIG_UINT(pdata
,24,svfs
.UserBlocksAvail
);
3862 SBIG_UINT(pdata
,32,svfs
.TotalFileNodes
);
3863 SBIG_UINT(pdata
,40,svfs
.FreeFileNodes
);
3864 SBIG_UINT(pdata
,48,svfs
.FsIdentifier
);
3865 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3867 } else if (rc
== EOPNOTSUPP
) {
3868 return NT_STATUS_INVALID_LEVEL
;
3869 #endif /* EOPNOTSUPP */
3871 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn
))));
3872 return NT_STATUS_DOS(ERRSRV
, ERRerror
);
3877 case SMB_QUERY_POSIX_WHOAMI
:
3883 if (!lp_unix_extensions()) {
3884 return NT_STATUS_INVALID_LEVEL
;
3887 if (max_data_bytes
< 40) {
3888 return NT_STATUS_BUFFER_TOO_SMALL
;
3891 if (security_session_user_level(conn
->session_info
, NULL
) < SECURITY_USER
) {
3892 flags
|= SMB_WHOAMI_GUEST
;
3895 /* NOTE: 8 bytes for UID/GID, irrespective of native
3896 * platform size. This matches
3897 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3899 data_len
= 4 /* flags */
3906 + 4 /* pad/reserved */
3907 + (conn
->session_info
->unix_token
->ngroups
* 8)
3909 + (conn
->session_info
->security_token
->num_sids
*
3913 SIVAL(pdata
, 0, flags
);
3914 SIVAL(pdata
, 4, SMB_WHOAMI_MASK
);
3916 (uint64_t)conn
->session_info
->unix_token
->uid
);
3917 SBIG_UINT(pdata
, 16,
3918 (uint64_t)conn
->session_info
->unix_token
->gid
);
3921 if (data_len
>= max_data_bytes
) {
3922 /* Potential overflow, skip the GIDs and SIDs. */
3924 SIVAL(pdata
, 24, 0); /* num_groups */
3925 SIVAL(pdata
, 28, 0); /* num_sids */
3926 SIVAL(pdata
, 32, 0); /* num_sid_bytes */
3927 SIVAL(pdata
, 36, 0); /* reserved */
3933 SIVAL(pdata
, 24, conn
->session_info
->unix_token
->ngroups
);
3934 SIVAL(pdata
, 28, conn
->session_info
->security_token
->num_sids
);
3936 /* We walk the SID list twice, but this call is fairly
3937 * infrequent, and I don't expect that it's performance
3938 * sensitive -- jpeach
3940 for (i
= 0, sid_bytes
= 0;
3941 i
< conn
->session_info
->security_token
->num_sids
; ++i
) {
3942 sid_bytes
+= ndr_size_dom_sid(
3943 &conn
->session_info
->security_token
->sids
[i
],
3947 /* SID list byte count */
3948 SIVAL(pdata
, 32, sid_bytes
);
3950 /* 4 bytes pad/reserved - must be zero */
3951 SIVAL(pdata
, 36, 0);
3955 for (i
= 0; i
< conn
->session_info
->unix_token
->ngroups
; ++i
) {
3956 SBIG_UINT(pdata
, data_len
,
3957 (uint64_t)conn
->session_info
->unix_token
->groups
[i
]);
3963 i
< conn
->session_info
->security_token
->num_sids
; ++i
) {
3964 int sid_len
= ndr_size_dom_sid(
3965 &conn
->session_info
->security_token
->sids
[i
],
3968 sid_linearize((uint8_t *)(pdata
+ data_len
),
3970 &conn
->session_info
->security_token
->sids
[i
]);
3971 data_len
+= sid_len
;
3977 case SMB_MAC_QUERY_FS_INFO
:
3979 * Thursby MAC extension... ONLY on NTFS filesystems
3980 * once we do streams then we don't need this
3982 if (strequal(lp_fstype(SNUM(conn
)),"NTFS")) {
3984 SIVAL(pdata
,84,0x100); /* Don't support mac... */
3989 return NT_STATUS_INVALID_LEVEL
;
3992 *ret_data_len
= data_len
;
3996 static NTSTATUS
smb_set_fsquota(connection_struct
*conn
,
3997 struct smb_request
*req
,
3999 const DATA_BLOB
*qdata
)
4002 SMB_NTQUOTA_STRUCT quotas
;
4004 ZERO_STRUCT(quotas
);
4007 if ((get_current_uid(conn
) != 0) || !CAN_WRITE(conn
)) {
4008 DEBUG(3, ("set_fsquota: access_denied service [%s] user [%s]\n",
4009 lp_servicename(talloc_tos(), SNUM(conn
)),
4010 conn
->session_info
->unix_info
->unix_name
));
4011 return NT_STATUS_ACCESS_DENIED
;
4014 if (!check_fsp_ntquota_handle(conn
, req
,
4016 DEBUG(1, ("set_fsquota: no valid QUOTA HANDLE\n"));
4017 return NT_STATUS_INVALID_HANDLE
;
4020 /* note: normally there're 48 bytes,
4021 * but we didn't use the last 6 bytes for now
4024 if (qdata
->length
< 42) {
4025 DEBUG(0,("set_fsquota: requires total_data(%u) >= 42 bytes!\n",
4026 (unsigned int)qdata
->length
));
4027 return NT_STATUS_INVALID_PARAMETER
;
4030 /* unknown_1 24 NULL bytes in pdata*/
4032 /* the soft quotas 8 bytes (uint64_t)*/
4033 quotas
.softlim
= BVAL(qdata
->data
,24);
4035 /* the hard quotas 8 bytes (uint64_t)*/
4036 quotas
.hardlim
= BVAL(qdata
->data
,32);
4038 /* quota_flags 2 bytes **/
4039 quotas
.qflags
= SVAL(qdata
->data
,40);
4041 /* unknown_2 6 NULL bytes follow*/
4043 /* now set the quotas */
4044 if (vfs_set_ntquota(fsp
, SMB_USER_FS_QUOTA_TYPE
, NULL
, "as
)!=0) {
4045 DEBUG(1, ("vfs_set_ntquota() failed for service [%s]\n",
4046 lp_servicename(talloc_tos(), SNUM(conn
))));
4047 status
= map_nt_error_from_unix(errno
);
4049 status
= NT_STATUS_OK
;
4054 NTSTATUS
smbd_do_setfsinfo(connection_struct
*conn
,
4055 struct smb_request
*req
,
4056 TALLOC_CTX
*mem_ctx
,
4057 uint16_t info_level
,
4059 const DATA_BLOB
*pdata
)
4061 switch (info_level
) {
4062 case SMB_FS_QUOTA_INFORMATION
:
4064 return smb_set_fsquota(conn
,
4073 return NT_STATUS_INVALID_LEVEL
;
4076 /****************************************************************************
4077 Reply to a TRANS2_QFSINFO (query filesystem info).
4078 ****************************************************************************/
4080 static void call_trans2qfsinfo(connection_struct
*conn
,
4081 struct smb_request
*req
,
4082 char **pparams
, int total_params
,
4083 char **ppdata
, int total_data
,
4084 unsigned int max_data_bytes
)
4086 char *params
= *pparams
;
4087 uint16_t info_level
;
4089 size_t fixed_portion
;
4092 if (total_params
< 2) {
4093 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4097 info_level
= SVAL(params
,0);
4099 if (ENCRYPTION_REQUIRED(conn
) && !req
->encrypted
) {
4100 if (info_level
!= SMB_QUERY_CIFS_UNIX_INFO
) {
4101 DEBUG(0,("call_trans2qfsinfo: encryption required "
4102 "and info level 0x%x sent.\n",
4103 (unsigned int)info_level
));
4104 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
4109 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level
));
4111 status
= smbd_do_qfsinfo(req
->xconn
, conn
, req
,
4118 if (!NT_STATUS_IS_OK(status
)) {
4119 reply_nterror(req
, status
);
4123 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 0, *ppdata
, data_len
,
4126 DEBUG( 4, ( "%s info_level = %d\n",
4127 smb_fn_name(req
->cmd
), info_level
) );
4132 /****************************************************************************
4133 Reply to a TRANS2_SETFSINFO (set filesystem info).
4134 ****************************************************************************/
4136 static void call_trans2setfsinfo(connection_struct
*conn
,
4137 struct smb_request
*req
,
4138 char **pparams
, int total_params
,
4139 char **ppdata
, int total_data
,
4140 unsigned int max_data_bytes
)
4142 struct smbXsrv_connection
*xconn
= req
->xconn
;
4143 char *pdata
= *ppdata
;
4144 char *params
= *pparams
;
4145 uint16_t info_level
;
4147 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",
4148 lp_servicename(talloc_tos(), SNUM(conn
))));
4151 if (total_params
< 4) {
4152 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
4154 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4158 info_level
= SVAL(params
,2);
4161 if (info_level
!= SMB_REQUEST_TRANSPORT_ENCRYPTION
&&
4162 info_level
!= SMB_SET_CIFS_UNIX_INFO
) {
4163 DEBUG(0,("call_trans2setfsinfo: not an allowed "
4164 "info level (0x%x) on IPC$.\n",
4165 (unsigned int)info_level
));
4166 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
4171 if (ENCRYPTION_REQUIRED(conn
) && !req
->encrypted
) {
4172 if (info_level
!= SMB_REQUEST_TRANSPORT_ENCRYPTION
) {
4173 DEBUG(0,("call_trans2setfsinfo: encryption required "
4174 "and info level 0x%x sent.\n",
4175 (unsigned int)info_level
));
4176 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
4181 switch(info_level
) {
4182 case SMB_SET_CIFS_UNIX_INFO
:
4183 if (!lp_unix_extensions()) {
4184 DEBUG(2,("call_trans2setfsinfo: "
4185 "SMB_SET_CIFS_UNIX_INFO is invalid with "
4186 "unix extensions off\n"));
4188 NT_STATUS_INVALID_LEVEL
);
4192 /* There should be 12 bytes of capabilities set. */
4193 if (total_data
< 12) {
4196 NT_STATUS_INVALID_PARAMETER
);
4199 xconn
->smb1
.unix_info
.client_major
= SVAL(pdata
,0);
4200 xconn
->smb1
.unix_info
.client_minor
= SVAL(pdata
,2);
4201 xconn
->smb1
.unix_info
.client_cap_low
= IVAL(pdata
,4);
4202 xconn
->smb1
.unix_info
.client_cap_high
= IVAL(pdata
,8);
4203 /* Just print these values for now. */
4204 DEBUG(10, ("call_trans2setfsinfo: set unix_info info. "
4205 "major = %u, minor = %u cap_low = 0x%x, "
4207 (unsigned int)xconn
->
4208 smb1
.unix_info
.client_major
,
4209 (unsigned int)xconn
->
4210 smb1
.unix_info
.client_minor
,
4211 (unsigned int)xconn
->
4212 smb1
.unix_info
.client_cap_low
,
4213 (unsigned int)xconn
->
4214 smb1
.unix_info
.client_cap_high
));
4216 /* Here is where we must switch to posix pathname processing... */
4217 if (xconn
->smb1
.unix_info
.client_cap_low
& CIFS_UNIX_POSIX_PATHNAMES_CAP
) {
4218 lp_set_posix_pathnames();
4219 mangle_change_to_posix();
4222 if ((xconn
->smb1
.unix_info
.client_cap_low
& CIFS_UNIX_FCNTL_LOCKS_CAP
) &&
4223 !(xconn
->smb1
.unix_info
.client_cap_low
& CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP
)) {
4224 /* Client that knows how to do posix locks,
4225 * but not posix open/mkdir operations. Set a
4226 * default type for read/write checks. */
4228 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK
);
4233 case SMB_REQUEST_TRANSPORT_ENCRYPTION
:
4236 size_t param_len
= 0;
4237 size_t data_len
= total_data
;
4239 if (!lp_unix_extensions()) {
4242 NT_STATUS_INVALID_LEVEL
);
4246 if (lp_smb_encrypt(SNUM(conn
)) == SMB_SIGNING_OFF
) {
4249 NT_STATUS_NOT_SUPPORTED
);
4253 if (xconn
->smb1
.echo_handler
.trusted_fde
) {
4254 DEBUG( 2,("call_trans2setfsinfo: "
4255 "request transport encryption disabled"
4256 "with 'fork echo handler = yes'\n"));
4259 NT_STATUS_NOT_SUPPORTED
);
4263 DEBUG( 4,("call_trans2setfsinfo: "
4264 "request transport encryption.\n"));
4266 status
= srv_request_encryption_setup(conn
,
4267 (unsigned char **)ppdata
,
4269 (unsigned char **)pparams
,
4272 if (!NT_STATUS_EQUAL(status
, NT_STATUS_MORE_PROCESSING_REQUIRED
) &&
4273 !NT_STATUS_IS_OK(status
)) {
4274 reply_nterror(req
, status
);
4278 send_trans2_replies(conn
, req
,
4286 if (NT_STATUS_IS_OK(status
)) {
4287 /* Server-side transport
4288 * encryption is now *on*. */
4289 status
= srv_encryption_start(conn
);
4290 if (!NT_STATUS_IS_OK(status
)) {
4291 char *reason
= talloc_asprintf(talloc_tos(),
4292 "Failure in setting "
4293 "up encrypted transport: %s",
4295 exit_server_cleanly(reason
);
4301 case SMB_FS_QUOTA_INFORMATION
:
4305 .data
= (uint8_t *)pdata
,
4306 .length
= total_data
4308 files_struct
*fsp
= NULL
;
4309 fsp
= file_fsp(req
, SVAL(params
,0));
4311 status
= smb_set_fsquota(conn
,
4315 if (!NT_STATUS_IS_OK(status
)) {
4316 reply_nterror(req
, status
);
4322 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
4324 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
4330 * sending this reply works fine,
4331 * but I'm not sure it's the same
4332 * like windows do...
4335 reply_outbuf(req
, 10, 0);
4338 #if defined(HAVE_POSIX_ACLS)
4339 /****************************************************************************
4340 Utility function to count the number of entries in a POSIX acl.
4341 ****************************************************************************/
4343 static unsigned int count_acl_entries(connection_struct
*conn
, SMB_ACL_T posix_acl
)
4345 unsigned int ace_count
= 0;
4346 int entry_id
= SMB_ACL_FIRST_ENTRY
;
4347 SMB_ACL_ENTRY_T entry
;
4349 while ( posix_acl
&& (sys_acl_get_entry(posix_acl
, entry_id
, &entry
) == 1)) {
4351 if (entry_id
== SMB_ACL_FIRST_ENTRY
) {
4352 entry_id
= SMB_ACL_NEXT_ENTRY
;
4359 /****************************************************************************
4360 Utility function to marshall a POSIX acl into wire format.
4361 ****************************************************************************/
4363 static bool marshall_posix_acl(connection_struct
*conn
, char *pdata
, SMB_STRUCT_STAT
*pst
, SMB_ACL_T posix_acl
)
4365 int entry_id
= SMB_ACL_FIRST_ENTRY
;
4366 SMB_ACL_ENTRY_T entry
;
4368 while ( posix_acl
&& (sys_acl_get_entry(posix_acl
, entry_id
, &entry
) == 1)) {
4369 SMB_ACL_TAG_T tagtype
;
4370 SMB_ACL_PERMSET_T permset
;
4371 unsigned char perms
= 0;
4372 unsigned int own_grp
;
4375 if (entry_id
== SMB_ACL_FIRST_ENTRY
) {
4376 entry_id
= SMB_ACL_NEXT_ENTRY
;
4379 if (sys_acl_get_tag_type(entry
, &tagtype
) == -1) {
4380 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
4384 if (sys_acl_get_permset(entry
, &permset
) == -1) {
4385 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
4389 perms
|= (sys_acl_get_perm(permset
, SMB_ACL_READ
) ? SMB_POSIX_ACL_READ
: 0);
4390 perms
|= (sys_acl_get_perm(permset
, SMB_ACL_WRITE
) ? SMB_POSIX_ACL_WRITE
: 0);
4391 perms
|= (sys_acl_get_perm(permset
, SMB_ACL_EXECUTE
) ? SMB_POSIX_ACL_EXECUTE
: 0);
4393 SCVAL(pdata
,1,perms
);
4396 case SMB_ACL_USER_OBJ
:
4397 SCVAL(pdata
,0,SMB_POSIX_ACL_USER_OBJ
);
4398 own_grp
= (unsigned int)pst
->st_ex_uid
;
4399 SIVAL(pdata
,2,own_grp
);
4404 uid_t
*puid
= (uid_t
*)sys_acl_get_qualifier(entry
);
4406 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
4409 own_grp
= (unsigned int)*puid
;
4410 SCVAL(pdata
,0,SMB_POSIX_ACL_USER
);
4411 SIVAL(pdata
,2,own_grp
);
4415 case SMB_ACL_GROUP_OBJ
:
4416 SCVAL(pdata
,0,SMB_POSIX_ACL_GROUP_OBJ
);
4417 own_grp
= (unsigned int)pst
->st_ex_gid
;
4418 SIVAL(pdata
,2,own_grp
);
4423 gid_t
*pgid
= (gid_t
*)sys_acl_get_qualifier(entry
);
4425 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
4428 own_grp
= (unsigned int)*pgid
;
4429 SCVAL(pdata
,0,SMB_POSIX_ACL_GROUP
);
4430 SIVAL(pdata
,2,own_grp
);
4435 SCVAL(pdata
,0,SMB_POSIX_ACL_MASK
);
4436 SIVAL(pdata
,2,0xFFFFFFFF);
4437 SIVAL(pdata
,6,0xFFFFFFFF);
4440 SCVAL(pdata
,0,SMB_POSIX_ACL_OTHER
);
4441 SIVAL(pdata
,2,0xFFFFFFFF);
4442 SIVAL(pdata
,6,0xFFFFFFFF);
4445 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
4448 pdata
+= SMB_POSIX_ACL_ENTRY_SIZE
;
4455 /****************************************************************************
4456 Store the FILE_UNIX_BASIC info.
4457 ****************************************************************************/
4459 static char *store_file_unix_basic(connection_struct
*conn
,
4462 const SMB_STRUCT_STAT
*psbuf
)
4464 uint64_t file_index
= get_FileIndex(conn
, psbuf
);
4467 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
4468 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf
->st_ex_mode
));
4470 SOFF_T(pdata
,0,get_file_size_stat(psbuf
)); /* File size 64 Bit */
4473 SOFF_T(pdata
,0,SMB_VFS_GET_ALLOC_SIZE(conn
,fsp
,psbuf
)); /* Number of bytes used on disk - 64 Bit */
4476 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER
, pdata
, psbuf
->st_ex_ctime
); /* Change Time 64 Bit */
4477 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER
,pdata
+8, psbuf
->st_ex_atime
); /* Last access time 64 Bit */
4478 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER
, pdata
+16, psbuf
->st_ex_mtime
); /* Last modification time 64 Bit */
4481 SIVAL(pdata
,0,psbuf
->st_ex_uid
); /* user id for the owner */
4485 SIVAL(pdata
,0,psbuf
->st_ex_gid
); /* group id of owner */
4489 SIVAL(pdata
,0,unix_filetype(psbuf
->st_ex_mode
));
4492 if (S_ISBLK(psbuf
->st_ex_mode
) || S_ISCHR(psbuf
->st_ex_mode
)) {
4493 devno
= psbuf
->st_ex_rdev
;
4495 devno
= psbuf
->st_ex_dev
;
4498 SIVAL(pdata
,0,unix_dev_major(devno
)); /* Major device number if type is device */
4502 SIVAL(pdata
,0,unix_dev_minor(devno
)); /* Minor device number if type is device */
4506 SINO_T_VAL(pdata
,0,(SMB_INO_T
)file_index
); /* inode number */
4509 SIVAL(pdata
,0, unix_perms_to_wire(psbuf
->st_ex_mode
)); /* Standard UNIX file permissions */
4513 SIVAL(pdata
,0,psbuf
->st_ex_nlink
); /* number of hard links */
4520 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
4521 * the chflags(2) (or equivalent) flags.
4523 * XXX: this really should be behind the VFS interface. To do this, we would
4524 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
4525 * Each VFS module could then implement its own mapping as appropriate for the
4526 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
4528 static const struct {unsigned stat_fflag
; unsigned smb_fflag
;}
4532 { UF_NODUMP
, EXT_DO_NOT_BACKUP
},
4536 { UF_IMMUTABLE
, EXT_IMMUTABLE
},
4540 { UF_APPEND
, EXT_OPEN_APPEND_ONLY
},
4544 { UF_HIDDEN
, EXT_HIDDEN
},
4547 /* Do not remove. We need to guarantee that this array has at least one
4548 * entry to build on HP-UX.
4554 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT
*psbuf
,
4555 uint32_t *smb_fflags
, uint32_t *smb_fmask
)
4559 for (i
= 0; i
< ARRAY_SIZE(info2_flags_map
); ++i
) {
4560 *smb_fmask
|= info2_flags_map
[i
].smb_fflag
;
4561 if (psbuf
->st_ex_flags
& info2_flags_map
[i
].stat_fflag
) {
4562 *smb_fflags
|= info2_flags_map
[i
].smb_fflag
;
4567 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT
*psbuf
,
4568 const uint32_t smb_fflags
,
4569 const uint32_t smb_fmask
,
4572 uint32_t max_fmask
= 0;
4575 *stat_fflags
= psbuf
->st_ex_flags
;
4577 /* For each flags requested in smb_fmask, check the state of the
4578 * corresponding flag in smb_fflags and set or clear the matching
4582 for (i
= 0; i
< ARRAY_SIZE(info2_flags_map
); ++i
) {
4583 max_fmask
|= info2_flags_map
[i
].smb_fflag
;
4584 if (smb_fmask
& info2_flags_map
[i
].smb_fflag
) {
4585 if (smb_fflags
& info2_flags_map
[i
].smb_fflag
) {
4586 *stat_fflags
|= info2_flags_map
[i
].stat_fflag
;
4588 *stat_fflags
&= ~info2_flags_map
[i
].stat_fflag
;
4593 /* If smb_fmask is asking to set any bits that are not supported by
4594 * our flag mappings, we should fail.
4596 if ((smb_fmask
& max_fmask
) != smb_fmask
) {
4604 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
4605 * of file flags and birth (create) time.
4607 static char *store_file_unix_basic_info2(connection_struct
*conn
,
4610 const SMB_STRUCT_STAT
*psbuf
)
4612 uint32_t file_flags
= 0;
4613 uint32_t flags_mask
= 0;
4615 pdata
= store_file_unix_basic(conn
, pdata
, fsp
, psbuf
);
4617 /* Create (birth) time 64 bit */
4618 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER
,pdata
, psbuf
->st_ex_btime
);
4621 map_info2_flags_from_sbuf(psbuf
, &file_flags
, &flags_mask
);
4622 SIVAL(pdata
, 0, file_flags
); /* flags */
4623 SIVAL(pdata
, 4, flags_mask
); /* mask */
4629 static NTSTATUS
marshall_stream_info(unsigned int num_streams
,
4630 const struct stream_struct
*streams
,
4632 unsigned int max_data_bytes
,
4633 unsigned int *data_size
)
4636 unsigned int ofs
= 0;
4638 if (max_data_bytes
< 32) {
4639 return NT_STATUS_INFO_LENGTH_MISMATCH
;
4642 for (i
= 0; i
< num_streams
; i
++) {
4643 unsigned int next_offset
;
4645 smb_ucs2_t
*namebuf
;
4647 if (!push_ucs2_talloc(talloc_tos(), &namebuf
,
4648 streams
[i
].name
, &namelen
) ||
4651 return NT_STATUS_INVALID_PARAMETER
;
4655 * name_buf is now null-terminated, we need to marshall as not
4662 * We cannot overflow ...
4664 if ((ofs
+ 24 + namelen
) > max_data_bytes
) {
4665 DEBUG(10, ("refusing to overflow reply at stream %u\n",
4667 TALLOC_FREE(namebuf
);
4668 return STATUS_BUFFER_OVERFLOW
;
4671 SIVAL(data
, ofs
+4, namelen
);
4672 SOFF_T(data
, ofs
+8, streams
[i
].size
);
4673 SOFF_T(data
, ofs
+16, streams
[i
].alloc_size
);
4674 memcpy(data
+ofs
+24, namebuf
, namelen
);
4675 TALLOC_FREE(namebuf
);
4677 next_offset
= ofs
+ 24 + namelen
;
4679 if (i
== num_streams
-1) {
4680 SIVAL(data
, ofs
, 0);
4683 unsigned int align
= ndr_align_size(next_offset
, 8);
4685 if ((next_offset
+ align
) > max_data_bytes
) {
4686 DEBUG(10, ("refusing to overflow align "
4687 "reply at stream %u\n",
4689 TALLOC_FREE(namebuf
);
4690 return STATUS_BUFFER_OVERFLOW
;
4693 memset(data
+next_offset
, 0, align
);
4694 next_offset
+= align
;
4696 SIVAL(data
, ofs
, next_offset
- ofs
);
4703 DEBUG(10, ("max_data: %u, data_size: %u\n", max_data_bytes
, ofs
));
4707 return NT_STATUS_OK
;
4710 /****************************************************************************
4711 Reply to a TRANSACT2_QFILEINFO on a PIPE !
4712 ****************************************************************************/
4714 static void call_trans2qpipeinfo(connection_struct
*conn
,
4715 struct smb_request
*req
,
4716 unsigned int tran_call
,
4717 char **pparams
, int total_params
,
4718 char **ppdata
, int total_data
,
4719 unsigned int max_data_bytes
)
4721 char *params
= *pparams
;
4722 char *pdata
= *ppdata
;
4723 unsigned int data_size
= 0;
4724 unsigned int param_size
= 2;
4725 uint16_t info_level
;
4729 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4733 if (total_params
< 4) {
4734 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4738 fsp
= file_fsp(req
, SVAL(params
,0));
4739 if (!fsp_is_np(fsp
)) {
4740 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
4744 info_level
= SVAL(params
,2);
4746 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
4747 if (*pparams
== NULL
) {
4748 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
4753 if (max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
< max_data_bytes
) {
4754 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4757 data_size
= max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
;
4758 *ppdata
= (char *)SMB_REALLOC(*ppdata
, data_size
);
4759 if (*ppdata
== NULL
) {
4760 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
4765 switch (info_level
) {
4766 case SMB_FILE_STANDARD_INFORMATION
:
4768 SOFF_T(pdata
,0,4096LL);
4775 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
4779 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, param_size
, *ppdata
, data_size
,
4785 NTSTATUS
smbd_do_qfilepathinfo(connection_struct
*conn
,
4786 TALLOC_CTX
*mem_ctx
,
4787 uint16_t info_level
,
4789 struct smb_filename
*smb_fname
,
4790 bool delete_pending
,
4791 struct timespec write_time_ts
,
4792 struct ea_list
*ea_list
,
4793 int lock_data_count
,
4796 unsigned int max_data_bytes
,
4797 size_t *fixed_portion
,
4799 unsigned int *pdata_size
)
4801 char *pdata
= *ppdata
;
4802 char *dstart
, *dend
;
4803 unsigned int data_size
;
4804 struct timespec create_time_ts
, mtime_ts
, atime_ts
, ctime_ts
;
4805 time_t create_time
, mtime
, atime
, c_time
;
4806 SMB_STRUCT_STAT
*psbuf
= &smb_fname
->st
;
4813 uint64_t file_size
= 0;
4815 uint64_t allocation_size
= 0;
4816 uint64_t file_index
= 0;
4817 uint32_t access_mask
= 0;
4820 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
4821 return NT_STATUS_INVALID_LEVEL
;
4824 DEBUG(5,("smbd_do_qfilepathinfo: %s (%s) level=%d max_data=%u\n",
4825 smb_fname_str_dbg(smb_fname
),
4827 info_level
, max_data_bytes
));
4829 mode
= dos_mode(conn
, smb_fname
);
4830 nlink
= psbuf
->st_ex_nlink
;
4832 if (nlink
&& (mode
&FILE_ATTRIBUTE_DIRECTORY
)) {
4836 if ((nlink
> 0) && delete_pending
) {
4840 if (max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
< max_data_bytes
) {
4841 return NT_STATUS_INVALID_PARAMETER
;
4844 data_size
= max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
;
4845 *ppdata
= (char *)SMB_REALLOC(*ppdata
, data_size
);
4846 if (*ppdata
== NULL
) {
4847 return NT_STATUS_NO_MEMORY
;
4851 dend
= dstart
+ data_size
- 1;
4853 if (!null_timespec(write_time_ts
) && !INFO_LEVEL_IS_UNIX(info_level
)) {
4854 update_stat_ex_mtime(psbuf
, write_time_ts
);
4857 create_time_ts
= get_create_timespec(conn
, fsp
, smb_fname
);
4858 mtime_ts
= psbuf
->st_ex_mtime
;
4859 atime_ts
= psbuf
->st_ex_atime
;
4860 ctime_ts
= get_change_timespec(conn
, fsp
, smb_fname
);
4862 if (lp_dos_filetime_resolution(SNUM(conn
))) {
4863 dos_filetime_timespec(&create_time_ts
);
4864 dos_filetime_timespec(&mtime_ts
);
4865 dos_filetime_timespec(&atime_ts
);
4866 dos_filetime_timespec(&ctime_ts
);
4869 create_time
= convert_timespec_to_time_t(create_time_ts
);
4870 mtime
= convert_timespec_to_time_t(mtime_ts
);
4871 atime
= convert_timespec_to_time_t(atime_ts
);
4872 c_time
= convert_timespec_to_time_t(ctime_ts
);
4874 p
= strrchr_m(smb_fname
->base_name
,'/');
4876 base_name
= smb_fname
->base_name
;
4880 /* NT expects the name to be in an exact form of the *full*
4881 filename. See the trans2 torture test */
4882 if (ISDOT(base_name
)) {
4883 dos_fname
= talloc_strdup(mem_ctx
, "\\");
4885 return NT_STATUS_NO_MEMORY
;
4888 dos_fname
= talloc_asprintf(mem_ctx
,
4890 smb_fname
->base_name
);
4892 return NT_STATUS_NO_MEMORY
;
4894 if (is_ntfs_stream_smb_fname(smb_fname
)) {
4895 dos_fname
= talloc_asprintf(dos_fname
, "%s",
4896 smb_fname
->stream_name
);
4898 return NT_STATUS_NO_MEMORY
;
4902 string_replace(dos_fname
, '/', '\\');
4905 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
, fsp
, psbuf
);
4908 /* Do we have this path open ? */
4910 struct file_id fileid
= vfs_file_id_from_sbuf(conn
, psbuf
);
4911 fsp1
= file_find_di_first(conn
->sconn
, fileid
);
4912 if (fsp1
&& fsp1
->initial_allocation_size
) {
4913 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
, fsp1
, psbuf
);
4917 if (!(mode
& FILE_ATTRIBUTE_DIRECTORY
)) {
4918 file_size
= get_file_size_stat(psbuf
);
4922 pos
= fsp
->fh
->position_information
;
4926 access_mask
= fsp
->access_mask
;
4928 /* GENERIC_EXECUTE mapping from Windows */
4929 access_mask
= 0x12019F;
4932 /* This should be an index number - looks like
4935 I think this causes us to fail the IFSKIT
4936 BasicFileInformationTest. -tpot */
4937 file_index
= get_FileIndex(conn
, psbuf
);
4941 switch (info_level
) {
4942 case SMB_INFO_STANDARD
:
4943 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4945 srv_put_dos_date2(pdata
,l1_fdateCreation
,create_time
);
4946 srv_put_dos_date2(pdata
,l1_fdateLastAccess
,atime
);
4947 srv_put_dos_date2(pdata
,l1_fdateLastWrite
,mtime
); /* write time */
4948 SIVAL(pdata
,l1_cbFile
,(uint32_t)file_size
);
4949 SIVAL(pdata
,l1_cbFileAlloc
,(uint32_t)allocation_size
);
4950 SSVAL(pdata
,l1_attrFile
,mode
);
4953 case SMB_INFO_QUERY_EA_SIZE
:
4955 unsigned int ea_size
=
4956 estimate_ea_size(conn
, fsp
,
4958 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4960 srv_put_dos_date2(pdata
,0,create_time
);
4961 srv_put_dos_date2(pdata
,4,atime
);
4962 srv_put_dos_date2(pdata
,8,mtime
); /* write time */
4963 SIVAL(pdata
,12,(uint32_t)file_size
);
4964 SIVAL(pdata
,16,(uint32_t)allocation_size
);
4965 SSVAL(pdata
,20,mode
);
4966 SIVAL(pdata
,22,ea_size
);
4970 case SMB_INFO_IS_NAME_VALID
:
4971 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4973 /* os/2 needs this ? really ?*/
4974 return NT_STATUS_DOS(ERRDOS
, ERRbadfunc
);
4976 /* This is only reached for qpathinfo */
4980 case SMB_INFO_QUERY_EAS_FROM_LIST
:
4982 size_t total_ea_len
= 0;
4983 struct ea_list
*ea_file_list
= NULL
;
4984 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4987 get_ea_list_from_file(mem_ctx
, conn
, fsp
,
4989 &total_ea_len
, &ea_file_list
);
4990 if (!NT_STATUS_IS_OK(status
)) {
4994 ea_list
= ea_list_union(ea_list
, ea_file_list
, &total_ea_len
);
4996 if (!ea_list
|| (total_ea_len
> data_size
)) {
4998 SIVAL(pdata
,0,4); /* EA List Length must be set to 4 if no EA's. */
5002 data_size
= fill_ea_buffer(mem_ctx
, pdata
, data_size
, conn
, ea_list
);
5006 case SMB_INFO_QUERY_ALL_EAS
:
5008 /* We have data_size bytes to put EA's into. */
5009 size_t total_ea_len
= 0;
5010 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
5012 status
= get_ea_list_from_file(mem_ctx
, conn
, fsp
,
5014 &total_ea_len
, &ea_list
);
5015 if (!NT_STATUS_IS_OK(status
)) {
5019 if (!ea_list
|| (total_ea_len
> data_size
)) {
5021 SIVAL(pdata
,0,4); /* EA List Length must be set to 4 if no EA's. */
5025 data_size
= fill_ea_buffer(mem_ctx
, pdata
, data_size
, conn
, ea_list
);
5029 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
5031 /* This is FileFullEaInformation - 0xF which maps to
5032 * 1015 (decimal) in smbd_do_setfilepathinfo. */
5034 /* We have data_size bytes to put EA's into. */
5035 size_t total_ea_len
= 0;
5036 struct ea_list
*ea_file_list
= NULL
;
5038 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
5040 /*TODO: add filtering and index handling */
5043 get_ea_list_from_file(mem_ctx
, conn
, fsp
,
5045 &total_ea_len
, &ea_file_list
);
5046 if (!NT_STATUS_IS_OK(status
)) {
5049 if (!ea_file_list
) {
5050 return NT_STATUS_NO_EAS_ON_FILE
;
5053 status
= fill_ea_chained_buffer(mem_ctx
,
5057 conn
, ea_file_list
);
5058 if (!NT_STATUS_IS_OK(status
)) {
5064 case SMB_FILE_BASIC_INFORMATION
:
5065 case SMB_QUERY_FILE_BASIC_INFO
:
5067 if (info_level
== SMB_QUERY_FILE_BASIC_INFO
) {
5068 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
5069 data_size
= 36; /* w95 returns 40 bytes not 36 - why ?. */
5071 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
5075 put_long_date_timespec(conn
->ts_res
,pdata
,create_time_ts
);
5076 put_long_date_timespec(conn
->ts_res
,pdata
+8,atime_ts
);
5077 put_long_date_timespec(conn
->ts_res
,pdata
+16,mtime_ts
); /* write time */
5078 put_long_date_timespec(conn
->ts_res
,pdata
+24,ctime_ts
); /* change time */
5079 SIVAL(pdata
,32,mode
);
5081 DEBUG(5,("SMB_QFBI - "));
5082 DEBUG(5,("create: %s ", ctime(&create_time
)));
5083 DEBUG(5,("access: %s ", ctime(&atime
)));
5084 DEBUG(5,("write: %s ", ctime(&mtime
)));
5085 DEBUG(5,("change: %s ", ctime(&c_time
)));
5086 DEBUG(5,("mode: %x\n", mode
));
5087 *fixed_portion
= data_size
;
5090 case SMB_FILE_STANDARD_INFORMATION
:
5091 case SMB_QUERY_FILE_STANDARD_INFO
:
5093 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
5095 SOFF_T(pdata
,0,allocation_size
);
5096 SOFF_T(pdata
,8,file_size
);
5097 SIVAL(pdata
,16,nlink
);
5098 SCVAL(pdata
,20,delete_pending
?1:0);
5099 SCVAL(pdata
,21,(mode
&FILE_ATTRIBUTE_DIRECTORY
)?1:0);
5100 SSVAL(pdata
,22,0); /* Padding. */
5101 *fixed_portion
= 24;
5104 case SMB_FILE_EA_INFORMATION
:
5105 case SMB_QUERY_FILE_EA_INFO
:
5107 unsigned int ea_size
=
5108 estimate_ea_size(conn
, fsp
, smb_fname
);
5109 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
5112 SIVAL(pdata
,0,ea_size
);
5116 /* Get the 8.3 name - used if NT SMB was negotiated. */
5117 case SMB_QUERY_FILE_ALT_NAME_INFO
:
5118 case SMB_FILE_ALTERNATE_NAME_INFORMATION
:
5120 char mangled_name
[13];
5121 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
5122 if (!name_to_8_3(base_name
,mangled_name
,
5123 True
,conn
->params
)) {
5124 return NT_STATUS_NO_MEMORY
;
5126 status
= srvstr_push(dstart
, flags2
,
5127 pdata
+4, mangled_name
,
5128 PTR_DIFF(dend
, pdata
+4),
5130 if (!NT_STATUS_IS_OK(status
)) {
5133 data_size
= 4 + len
;
5139 case SMB_QUERY_FILE_NAME_INFO
:
5142 this must be *exactly* right for ACLs on mapped drives to work
5144 status
= srvstr_push(dstart
, flags2
,
5146 PTR_DIFF(dend
, pdata
+4),
5148 if (!NT_STATUS_IS_OK(status
)) {
5151 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
5152 data_size
= 4 + len
;
5157 case SMB_FILE_ALLOCATION_INFORMATION
:
5158 case SMB_QUERY_FILE_ALLOCATION_INFO
:
5159 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
5161 SOFF_T(pdata
,0,allocation_size
);
5164 case SMB_FILE_END_OF_FILE_INFORMATION
:
5165 case SMB_QUERY_FILE_END_OF_FILEINFO
:
5166 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
5168 SOFF_T(pdata
,0,file_size
);
5171 case SMB_QUERY_FILE_ALL_INFO
:
5172 case SMB_FILE_ALL_INFORMATION
:
5174 unsigned int ea_size
=
5175 estimate_ea_size(conn
, fsp
, smb_fname
);
5176 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
5177 put_long_date_timespec(conn
->ts_res
,pdata
,create_time_ts
);
5178 put_long_date_timespec(conn
->ts_res
,pdata
+8,atime_ts
);
5179 put_long_date_timespec(conn
->ts_res
,pdata
+16,mtime_ts
); /* write time */
5180 put_long_date_timespec(conn
->ts_res
,pdata
+24,ctime_ts
); /* change time */
5181 SIVAL(pdata
,32,mode
);
5182 SIVAL(pdata
,36,0); /* padding. */
5184 SOFF_T(pdata
,0,allocation_size
);
5185 SOFF_T(pdata
,8,file_size
);
5186 SIVAL(pdata
,16,nlink
);
5187 SCVAL(pdata
,20,delete_pending
);
5188 SCVAL(pdata
,21,(mode
&FILE_ATTRIBUTE_DIRECTORY
)?1:0);
5191 SIVAL(pdata
,0,ea_size
);
5192 pdata
+= 4; /* EA info */
5193 status
= srvstr_push(dstart
, flags2
,
5195 PTR_DIFF(dend
, pdata
+4),
5197 if (!NT_STATUS_IS_OK(status
)) {
5202 data_size
= PTR_DIFF(pdata
,(*ppdata
));
5203 *fixed_portion
= 10;
5207 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
5209 unsigned int ea_size
=
5210 estimate_ea_size(conn
, fsp
, smb_fname
);
5211 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
5212 put_long_date_timespec(conn
->ts_res
,pdata
+0x00,create_time_ts
);
5213 put_long_date_timespec(conn
->ts_res
,pdata
+0x08,atime_ts
);
5214 put_long_date_timespec(conn
->ts_res
,pdata
+0x10,mtime_ts
); /* write time */
5215 put_long_date_timespec(conn
->ts_res
,pdata
+0x18,ctime_ts
); /* change time */
5216 SIVAL(pdata
, 0x20, mode
);
5217 SIVAL(pdata
, 0x24, 0); /* padding. */
5218 SBVAL(pdata
, 0x28, allocation_size
);
5219 SBVAL(pdata
, 0x30, file_size
);
5220 SIVAL(pdata
, 0x38, nlink
);
5221 SCVAL(pdata
, 0x3C, delete_pending
);
5222 SCVAL(pdata
, 0x3D, (mode
&FILE_ATTRIBUTE_DIRECTORY
)?1:0);
5223 SSVAL(pdata
, 0x3E, 0); /* padding */
5224 SBVAL(pdata
, 0x40, file_index
);
5225 SIVAL(pdata
, 0x48, ea_size
);
5226 SIVAL(pdata
, 0x4C, access_mask
);
5227 SBVAL(pdata
, 0x50, pos
);
5228 SIVAL(pdata
, 0x58, mode
); /*TODO: mode != mode fix this!!! */
5229 SIVAL(pdata
, 0x5C, 0); /* No alignment needed. */
5233 status
= srvstr_push(dstart
, flags2
,
5235 PTR_DIFF(dend
, pdata
+4),
5237 if (!NT_STATUS_IS_OK(status
)) {
5242 data_size
= PTR_DIFF(pdata
,(*ppdata
));
5243 *fixed_portion
= 104;
5246 case SMB_FILE_INTERNAL_INFORMATION
:
5248 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
5249 SBVAL(pdata
, 0, file_index
);
5254 case SMB_FILE_ACCESS_INFORMATION
:
5255 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
5256 SIVAL(pdata
, 0, access_mask
);
5261 case SMB_FILE_NAME_INFORMATION
:
5262 /* Pathname with leading '\'. */
5265 byte_len
= dos_PutUniCode(pdata
+4,dos_fname
,(size_t)max_data_bytes
,False
);
5266 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
5267 SIVAL(pdata
,0,byte_len
);
5268 data_size
= 4 + byte_len
;
5272 case SMB_FILE_DISPOSITION_INFORMATION
:
5273 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
5275 SCVAL(pdata
,0,delete_pending
);
5279 case SMB_FILE_POSITION_INFORMATION
:
5280 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
5282 SOFF_T(pdata
,0,pos
);
5286 case SMB_FILE_MODE_INFORMATION
:
5287 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
5288 SIVAL(pdata
,0,mode
);
5293 case SMB_FILE_ALIGNMENT_INFORMATION
:
5294 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
5295 SIVAL(pdata
,0,0); /* No alignment needed. */
5301 * NT4 server just returns "invalid query" to this - if we try
5302 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
5305 /* The first statement above is false - verified using Thursby
5306 * client against NT4 -- gcolley.
5308 case SMB_QUERY_FILE_STREAM_INFO
:
5309 case SMB_FILE_STREAM_INFORMATION
: {
5310 unsigned int num_streams
= 0;
5311 struct stream_struct
*streams
= NULL
;
5313 DEBUG(10,("smbd_do_qfilepathinfo: "
5314 "SMB_FILE_STREAM_INFORMATION\n"));
5316 if (is_ntfs_stream_smb_fname(smb_fname
)) {
5317 return NT_STATUS_INVALID_PARAMETER
;
5320 status
= vfs_streaminfo(conn
,
5327 if (!NT_STATUS_IS_OK(status
)) {
5328 DEBUG(10, ("could not get stream info: %s\n",
5329 nt_errstr(status
)));
5333 status
= marshall_stream_info(num_streams
, streams
,
5334 pdata
, max_data_bytes
,
5337 if (!NT_STATUS_IS_OK(status
)) {
5338 DEBUG(10, ("marshall_stream_info failed: %s\n",
5339 nt_errstr(status
)));
5340 TALLOC_FREE(streams
);
5344 TALLOC_FREE(streams
);
5346 *fixed_portion
= 32;
5350 case SMB_QUERY_COMPRESSION_INFO
:
5351 case SMB_FILE_COMPRESSION_INFORMATION
:
5352 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
5353 SOFF_T(pdata
,0,file_size
);
5354 SIVAL(pdata
,8,0); /* ??? */
5355 SIVAL(pdata
,12,0); /* ??? */
5357 *fixed_portion
= 16;
5360 case SMB_FILE_NETWORK_OPEN_INFORMATION
:
5361 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
5362 put_long_date_timespec(conn
->ts_res
,pdata
,create_time_ts
);
5363 put_long_date_timespec(conn
->ts_res
,pdata
+8,atime_ts
);
5364 put_long_date_timespec(conn
->ts_res
,pdata
+16,mtime_ts
); /* write time */
5365 put_long_date_timespec(conn
->ts_res
,pdata
+24,ctime_ts
); /* change time */
5366 SOFF_T(pdata
,32,allocation_size
);
5367 SOFF_T(pdata
,40,file_size
);
5368 SIVAL(pdata
,48,mode
);
5369 SIVAL(pdata
,52,0); /* ??? */
5371 *fixed_portion
= 56;
5374 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION
:
5375 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
5376 SIVAL(pdata
,0,mode
);
5383 * CIFS UNIX Extensions.
5386 case SMB_QUERY_FILE_UNIX_BASIC
:
5388 pdata
= store_file_unix_basic(conn
, pdata
, fsp
, psbuf
);
5389 data_size
= PTR_DIFF(pdata
,(*ppdata
));
5391 DEBUG(4,("smbd_do_qfilepathinfo: "
5392 "SMB_QUERY_FILE_UNIX_BASIC\n"));
5393 dump_data(4, (uint8_t *)(*ppdata
), data_size
);
5397 case SMB_QUERY_FILE_UNIX_INFO2
:
5399 pdata
= store_file_unix_basic_info2(conn
, pdata
, fsp
, psbuf
);
5400 data_size
= PTR_DIFF(pdata
,(*ppdata
));
5404 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
5406 for (i
=0; i
<100; i
++)
5407 DEBUG(4,("%d=%x, ",i
, (*ppdata
)[i
]));
5413 case SMB_QUERY_FILE_UNIX_LINK
:
5416 char *buffer
= talloc_array(mem_ctx
, char, PATH_MAX
+1);
5419 return NT_STATUS_NO_MEMORY
;
5422 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
5424 if(!S_ISLNK(psbuf
->st_ex_mode
)) {
5425 return NT_STATUS_DOS(ERRSRV
, ERRbadlink
);
5428 return NT_STATUS_DOS(ERRDOS
, ERRbadlink
);
5430 link_len
= SMB_VFS_READLINK(conn
,
5431 smb_fname
->base_name
,
5433 if (link_len
== -1) {
5434 return map_nt_error_from_unix(errno
);
5436 buffer
[link_len
] = 0;
5437 status
= srvstr_push(dstart
, flags2
,
5439 PTR_DIFF(dend
, pdata
),
5440 STR_TERMINATE
, &len
);
5441 if (!NT_STATUS_IS_OK(status
)) {
5445 data_size
= PTR_DIFF(pdata
,(*ppdata
));
5450 #if defined(HAVE_POSIX_ACLS)
5451 case SMB_QUERY_POSIX_ACL
:
5453 SMB_ACL_T file_acl
= NULL
;
5454 SMB_ACL_T def_acl
= NULL
;
5455 uint16_t num_file_acls
= 0;
5456 uint16_t num_def_acls
= 0;
5458 status
= refuse_symlink(conn
,
5461 if (!NT_STATUS_IS_OK(status
)) {
5465 if (fsp
&& fsp
->fh
->fd
!= -1) {
5466 file_acl
= SMB_VFS_SYS_ACL_GET_FD(fsp
,
5470 SMB_VFS_SYS_ACL_GET_FILE(conn
,
5471 smb_fname
->base_name
,
5472 SMB_ACL_TYPE_ACCESS
,
5476 if (file_acl
== NULL
&& no_acl_syscall_error(errno
)) {
5477 DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
5478 "not implemented on "
5479 "filesystem containing %s\n",
5480 smb_fname
->base_name
));
5481 return NT_STATUS_NOT_IMPLEMENTED
;
5484 if (S_ISDIR(psbuf
->st_ex_mode
)) {
5485 if (fsp
&& fsp
->is_directory
) {
5487 SMB_VFS_SYS_ACL_GET_FILE(
5489 fsp
->fsp_name
->base_name
,
5490 SMB_ACL_TYPE_DEFAULT
,
5494 SMB_VFS_SYS_ACL_GET_FILE(
5496 smb_fname
->base_name
,
5497 SMB_ACL_TYPE_DEFAULT
,
5500 def_acl
= free_empty_sys_acl(conn
, def_acl
);
5503 num_file_acls
= count_acl_entries(conn
, file_acl
);
5504 num_def_acls
= count_acl_entries(conn
, def_acl
);
5506 if ( data_size
< (num_file_acls
+ num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
+ SMB_POSIX_ACL_HEADER_SIZE
) {
5507 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
5509 (unsigned int)((num_file_acls
+ num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
+
5510 SMB_POSIX_ACL_HEADER_SIZE
) ));
5512 TALLOC_FREE(file_acl
);
5515 TALLOC_FREE(def_acl
);
5517 return NT_STATUS_BUFFER_TOO_SMALL
;
5520 SSVAL(pdata
,0,SMB_POSIX_ACL_VERSION
);
5521 SSVAL(pdata
,2,num_file_acls
);
5522 SSVAL(pdata
,4,num_def_acls
);
5523 if (!marshall_posix_acl(conn
, pdata
+ SMB_POSIX_ACL_HEADER_SIZE
, psbuf
, file_acl
)) {
5525 TALLOC_FREE(file_acl
);
5528 TALLOC_FREE(def_acl
);
5530 return NT_STATUS_INTERNAL_ERROR
;
5532 if (!marshall_posix_acl(conn
, pdata
+ SMB_POSIX_ACL_HEADER_SIZE
+ (num_file_acls
*SMB_POSIX_ACL_ENTRY_SIZE
), psbuf
, def_acl
)) {
5534 TALLOC_FREE(file_acl
);
5537 TALLOC_FREE(def_acl
);
5539 return NT_STATUS_INTERNAL_ERROR
;
5543 TALLOC_FREE(file_acl
);
5546 TALLOC_FREE(def_acl
);
5548 data_size
= (num_file_acls
+ num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
+ SMB_POSIX_ACL_HEADER_SIZE
;
5554 case SMB_QUERY_POSIX_LOCK
:
5559 enum brl_type lock_type
;
5561 /* We need an open file with a real fd for this. */
5562 if (!fsp
|| fsp
->fh
->fd
== -1) {
5563 return NT_STATUS_INVALID_LEVEL
;
5566 if (lock_data_count
!= POSIX_LOCK_DATA_SIZE
) {
5567 return NT_STATUS_INVALID_PARAMETER
;
5570 switch (SVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
)) {
5571 case POSIX_LOCK_TYPE_READ
:
5572 lock_type
= READ_LOCK
;
5574 case POSIX_LOCK_TYPE_WRITE
:
5575 lock_type
= WRITE_LOCK
;
5577 case POSIX_LOCK_TYPE_UNLOCK
:
5579 /* There's no point in asking for an unlock... */
5580 return NT_STATUS_INVALID_PARAMETER
;
5583 smblctx
= (uint64_t)IVAL(pdata
, POSIX_LOCK_PID_OFFSET
);
5584 offset
= BVAL(pdata
,POSIX_LOCK_START_OFFSET
);
5585 count
= BVAL(pdata
,POSIX_LOCK_LEN_OFFSET
);
5587 status
= query_lock(fsp
,
5594 if (ERROR_WAS_LOCK_DENIED(status
)) {
5595 /* Here we need to report who has it locked... */
5596 data_size
= POSIX_LOCK_DATA_SIZE
;
5598 SSVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
, lock_type
);
5599 SSVAL(pdata
, POSIX_LOCK_FLAGS_OFFSET
, 0);
5600 SIVAL(pdata
, POSIX_LOCK_PID_OFFSET
, (uint32_t)smblctx
);
5601 SBVAL(pdata
, POSIX_LOCK_START_OFFSET
, offset
);
5602 SBVAL(pdata
, POSIX_LOCK_LEN_OFFSET
, count
);
5604 } else if (NT_STATUS_IS_OK(status
)) {
5605 /* For success we just return a copy of what we sent
5606 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
5607 data_size
= POSIX_LOCK_DATA_SIZE
;
5608 memcpy(pdata
, lock_data
, POSIX_LOCK_DATA_SIZE
);
5609 SSVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
, POSIX_LOCK_TYPE_UNLOCK
);
5617 return NT_STATUS_INVALID_LEVEL
;
5620 *pdata_size
= data_size
;
5621 return NT_STATUS_OK
;
5624 /****************************************************************************
5625 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
5626 file name or file id).
5627 ****************************************************************************/
5629 static void call_trans2qfilepathinfo(connection_struct
*conn
,
5630 struct smb_request
*req
,
5631 unsigned int tran_call
,
5632 char **pparams
, int total_params
,
5633 char **ppdata
, int total_data
,
5634 unsigned int max_data_bytes
)
5636 char *params
= *pparams
;
5637 char *pdata
= *ppdata
;
5638 uint16_t info_level
;
5639 unsigned int data_size
= 0;
5640 unsigned int param_size
= 2;
5641 struct smb_filename
*smb_fname
= NULL
;
5642 bool delete_pending
= False
;
5643 struct timespec write_time_ts
;
5644 files_struct
*fsp
= NULL
;
5645 struct file_id fileid
;
5646 struct ea_list
*ea_list
= NULL
;
5647 int lock_data_count
= 0;
5648 char *lock_data
= NULL
;
5649 size_t fixed_portion
;
5650 NTSTATUS status
= NT_STATUS_OK
;
5653 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5657 ZERO_STRUCT(write_time_ts
);
5659 if (tran_call
== TRANSACT2_QFILEINFO
) {
5660 if (total_params
< 4) {
5661 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5666 call_trans2qpipeinfo(conn
, req
, tran_call
,
5667 pparams
, total_params
,
5673 fsp
= file_fsp(req
, SVAL(params
,0));
5674 info_level
= SVAL(params
,2);
5676 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level
));
5678 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
5679 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
5683 /* Initial check for valid fsp ptr. */
5684 if (!check_fsp_open(conn
, req
, fsp
)) {
5688 smb_fname
= cp_smb_filename(talloc_tos(), fsp
->fsp_name
);
5689 if (smb_fname
== NULL
) {
5690 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5694 if(fsp
->fake_file_handle
) {
5696 * This is actually for the QUOTA_FAKE_FILE --metze
5699 /* We know this name is ok, it's already passed the checks. */
5701 } else if(fsp
->fh
->fd
== -1) {
5703 * This is actually a QFILEINFO on a directory
5704 * handle (returned from an NT SMB). NT5.0 seems
5705 * to do this call. JRA.
5708 if (INFO_LEVEL_IS_UNIX(info_level
)) {
5709 /* Always do lstat for UNIX calls. */
5710 if (SMB_VFS_LSTAT(conn
, smb_fname
)) {
5711 DEBUG(3,("call_trans2qfilepathinfo: "
5712 "SMB_VFS_LSTAT of %s failed "
5714 smb_fname_str_dbg(smb_fname
),
5717 map_nt_error_from_unix(errno
));
5720 } else if (SMB_VFS_STAT(conn
, smb_fname
)) {
5721 DEBUG(3,("call_trans2qfilepathinfo: "
5722 "SMB_VFS_STAT of %s failed (%s)\n",
5723 smb_fname_str_dbg(smb_fname
),
5726 map_nt_error_from_unix(errno
));
5730 fileid
= vfs_file_id_from_sbuf(conn
, &smb_fname
->st
);
5731 get_file_infos(fileid
, fsp
->name_hash
, &delete_pending
, &write_time_ts
);
5734 * Original code - this is an open file.
5736 if (SMB_VFS_FSTAT(fsp
, &smb_fname
->st
) != 0) {
5737 DEBUG(3, ("fstat of %s failed (%s)\n",
5738 fsp_fnum_dbg(fsp
), strerror(errno
)));
5740 map_nt_error_from_unix(errno
));
5743 fileid
= vfs_file_id_from_sbuf(conn
, &smb_fname
->st
);
5744 get_file_infos(fileid
, fsp
->name_hash
, &delete_pending
, &write_time_ts
);
5750 uint32_t ucf_flags
= (req
->posix_pathnames
?
5751 UCF_POSIX_PATHNAMES
: 0);
5754 if (total_params
< 7) {
5755 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5759 info_level
= SVAL(params
,0);
5761 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level
));
5763 if (INFO_LEVEL_IS_UNIX(info_level
)) {
5764 if (!lp_unix_extensions()) {
5765 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
5768 if (info_level
== SMB_QUERY_FILE_UNIX_BASIC
||
5769 info_level
== SMB_QUERY_FILE_UNIX_INFO2
||
5770 info_level
== SMB_QUERY_FILE_UNIX_LINK
) {
5771 ucf_flags
|= UCF_UNIX_NAME_LOOKUP
;
5775 if (req
->posix_pathnames
) {
5776 srvstr_get_path_posix(req
,
5785 srvstr_get_path(req
,
5794 if (!NT_STATUS_IS_OK(status
)) {
5795 reply_nterror(req
, status
);
5799 status
= filename_convert(req
,
5801 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
5806 if (!NT_STATUS_IS_OK(status
)) {
5807 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
5808 reply_botherror(req
,
5809 NT_STATUS_PATH_NOT_COVERED
,
5810 ERRSRV
, ERRbadpath
);
5813 reply_nterror(req
, status
);
5817 /* If this is a stream, check if there is a delete_pending. */
5818 if ((conn
->fs_capabilities
& FILE_NAMED_STREAMS
)
5819 && is_ntfs_stream_smb_fname(smb_fname
)) {
5820 struct smb_filename
*smb_fname_base
;
5822 /* Create an smb_filename with stream_name == NULL. */
5823 smb_fname_base
= synthetic_smb_fname(
5825 smb_fname
->base_name
,
5829 if (smb_fname_base
== NULL
) {
5830 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5834 if (INFO_LEVEL_IS_UNIX(info_level
)) {
5835 /* Always do lstat for UNIX calls. */
5836 if (SMB_VFS_LSTAT(conn
, smb_fname_base
) != 0) {
5837 DEBUG(3,("call_trans2qfilepathinfo: "
5838 "SMB_VFS_LSTAT of %s failed "
5840 smb_fname_str_dbg(smb_fname_base
),
5842 TALLOC_FREE(smb_fname_base
);
5844 map_nt_error_from_unix(errno
));
5848 if (SMB_VFS_STAT(conn
, smb_fname_base
) != 0) {
5849 DEBUG(3,("call_trans2qfilepathinfo: "
5850 "fileinfo of %s failed "
5852 smb_fname_str_dbg(smb_fname_base
),
5854 TALLOC_FREE(smb_fname_base
);
5856 map_nt_error_from_unix(errno
));
5861 status
= file_name_hash(conn
,
5862 smb_fname_str_dbg(smb_fname_base
),
5864 if (!NT_STATUS_IS_OK(status
)) {
5865 TALLOC_FREE(smb_fname_base
);
5866 reply_nterror(req
, status
);
5870 fileid
= vfs_file_id_from_sbuf(conn
,
5871 &smb_fname_base
->st
);
5872 TALLOC_FREE(smb_fname_base
);
5873 get_file_infos(fileid
, name_hash
, &delete_pending
, NULL
);
5874 if (delete_pending
) {
5875 reply_nterror(req
, NT_STATUS_DELETE_PENDING
);
5880 if (INFO_LEVEL_IS_UNIX(info_level
)) {
5881 /* Always do lstat for UNIX calls. */
5882 if (SMB_VFS_LSTAT(conn
, smb_fname
)) {
5883 DEBUG(3,("call_trans2qfilepathinfo: "
5884 "SMB_VFS_LSTAT of %s failed (%s)\n",
5885 smb_fname_str_dbg(smb_fname
),
5888 map_nt_error_from_unix(errno
));
5893 if (SMB_VFS_STAT(conn
, smb_fname
) != 0) {
5894 DEBUG(3,("call_trans2qfilepathinfo: "
5895 "SMB_VFS_STAT of %s failed (%s)\n",
5896 smb_fname_str_dbg(smb_fname
),
5899 map_nt_error_from_unix(errno
));
5904 status
= file_name_hash(conn
,
5905 smb_fname_str_dbg(smb_fname
),
5907 if (!NT_STATUS_IS_OK(status
)) {
5908 reply_nterror(req
, status
);
5912 fileid
= vfs_file_id_from_sbuf(conn
, &smb_fname
->st
);
5913 get_file_infos(fileid
, name_hash
, &delete_pending
, &write_time_ts
);
5914 if (delete_pending
) {
5915 reply_nterror(req
, NT_STATUS_DELETE_PENDING
);
5920 DEBUG(3,("call_trans2qfilepathinfo %s (%s) level=%d call=%d "
5921 "total_data=%d\n", smb_fname_str_dbg(smb_fname
),
5923 info_level
,tran_call
,total_data
));
5925 /* Pull out any data sent here before we realloc. */
5926 switch (info_level
) {
5927 case SMB_INFO_QUERY_EAS_FROM_LIST
:
5929 /* Pull any EA list from the data portion. */
5932 if (total_data
< 4) {
5934 req
, NT_STATUS_INVALID_PARAMETER
);
5937 ea_size
= IVAL(pdata
,0);
5939 if (total_data
> 0 && ea_size
!= total_data
) {
5940 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5941 total_data=%u (should be %u)\n", (unsigned int)total_data
, (unsigned int)IVAL(pdata
,0) ));
5943 req
, NT_STATUS_INVALID_PARAMETER
);
5947 if (!lp_ea_support(SNUM(conn
))) {
5948 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
5952 /* Pull out the list of names. */
5953 ea_list
= read_ea_name_list(req
, pdata
+ 4, ea_size
- 4);
5956 req
, NT_STATUS_INVALID_PARAMETER
);
5962 case SMB_QUERY_POSIX_LOCK
:
5964 if (fsp
== NULL
|| fsp
->fh
->fd
== -1) {
5965 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
5969 if (total_data
!= POSIX_LOCK_DATA_SIZE
) {
5971 req
, NT_STATUS_INVALID_PARAMETER
);
5975 /* Copy the lock range data. */
5976 lock_data
= (char *)talloc_memdup(
5977 req
, pdata
, total_data
);
5979 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5982 lock_data_count
= total_data
;
5988 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
5989 if (*pparams
== NULL
) {
5990 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5997 * draft-leach-cifs-v1-spec-02.txt
5998 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
6001 * The requested information is placed in the Data portion of the
6002 * transaction response. For the information levels greater than 0x100,
6003 * the transaction response has 1 parameter word which should be
6004 * ignored by the client.
6006 * However Windows only follows this rule for the IS_NAME_VALID call.
6008 switch (info_level
) {
6009 case SMB_INFO_IS_NAME_VALID
:
6014 if ((info_level
& 0xFF00) == 0xFF00) {
6016 * We use levels that start with 0xFF00
6017 * internally to represent SMB2 specific levels
6019 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
6023 status
= smbd_do_qfilepathinfo(conn
, req
, info_level
,
6025 delete_pending
, write_time_ts
,
6027 lock_data_count
, lock_data
,
6028 req
->flags2
, max_data_bytes
,
6030 ppdata
, &data_size
);
6031 if (!NT_STATUS_IS_OK(status
)) {
6032 reply_nterror(req
, status
);
6035 if (fixed_portion
> max_data_bytes
) {
6036 reply_nterror(req
, NT_STATUS_INFO_LENGTH_MISMATCH
);
6040 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, param_size
, *ppdata
, data_size
,
6046 /****************************************************************************
6047 Set a hard link (called by UNIX extensions and by NT rename with HARD link
6049 ****************************************************************************/
6051 NTSTATUS
hardlink_internals(TALLOC_CTX
*ctx
,
6052 connection_struct
*conn
,
6053 struct smb_request
*req
,
6054 bool overwrite_if_exists
,
6055 const struct smb_filename
*smb_fname_old
,
6056 struct smb_filename
*smb_fname_new
)
6058 NTSTATUS status
= NT_STATUS_OK
;
6060 /* source must already exist. */
6061 if (!VALID_STAT(smb_fname_old
->st
)) {
6062 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
6065 if (VALID_STAT(smb_fname_new
->st
)) {
6066 if (overwrite_if_exists
) {
6067 if (S_ISDIR(smb_fname_new
->st
.st_ex_mode
)) {
6068 return NT_STATUS_FILE_IS_A_DIRECTORY
;
6070 status
= unlink_internals(conn
,
6072 FILE_ATTRIBUTE_NORMAL
,
6075 if (!NT_STATUS_IS_OK(status
)) {
6079 /* Disallow if newname already exists. */
6080 return NT_STATUS_OBJECT_NAME_COLLISION
;
6084 /* No links from a directory. */
6085 if (S_ISDIR(smb_fname_old
->st
.st_ex_mode
)) {
6086 return NT_STATUS_FILE_IS_A_DIRECTORY
;
6089 /* Setting a hardlink to/from a stream isn't currently supported. */
6090 if (is_ntfs_stream_smb_fname(smb_fname_old
) ||
6091 is_ntfs_stream_smb_fname(smb_fname_new
)) {
6092 return NT_STATUS_INVALID_PARAMETER
;
6095 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
6096 smb_fname_old
->base_name
, smb_fname_new
->base_name
));
6098 if (SMB_VFS_LINK(conn
, smb_fname_old
->base_name
,
6099 smb_fname_new
->base_name
) != 0) {
6100 status
= map_nt_error_from_unix(errno
);
6101 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
6102 nt_errstr(status
), smb_fname_old
->base_name
,
6103 smb_fname_new
->base_name
));
6108 /****************************************************************************
6109 Deal with setting the time from any of the setfilepathinfo functions.
6110 NOTE !!!! The check for FILE_WRITE_ATTRIBUTES access must be done *before*
6111 calling this function.
6112 ****************************************************************************/
6114 NTSTATUS
smb_set_file_time(connection_struct
*conn
,
6116 const struct smb_filename
*smb_fname
,
6117 struct smb_file_time
*ft
,
6118 bool setting_write_time
)
6120 struct smb_filename smb_fname_base
;
6122 FILE_NOTIFY_CHANGE_LAST_ACCESS
6123 |FILE_NOTIFY_CHANGE_LAST_WRITE
6124 |FILE_NOTIFY_CHANGE_CREATION
;
6126 if (!VALID_STAT(smb_fname
->st
)) {
6127 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
6130 /* get some defaults (no modifications) if any info is zero or -1. */
6131 if (null_timespec(ft
->create_time
)) {
6132 action
&= ~FILE_NOTIFY_CHANGE_CREATION
;
6135 if (null_timespec(ft
->atime
)) {
6136 action
&= ~FILE_NOTIFY_CHANGE_LAST_ACCESS
;
6139 if (null_timespec(ft
->mtime
)) {
6140 action
&= ~FILE_NOTIFY_CHANGE_LAST_WRITE
;
6143 if (!setting_write_time
) {
6144 /* ft->mtime comes from change time, not write time. */
6145 action
&= ~FILE_NOTIFY_CHANGE_LAST_WRITE
;
6148 /* Ensure the resolution is the correct for
6149 * what we can store on this filesystem. */
6151 round_timespec(conn
->ts_res
, &ft
->create_time
);
6152 round_timespec(conn
->ts_res
, &ft
->ctime
);
6153 round_timespec(conn
->ts_res
, &ft
->atime
);
6154 round_timespec(conn
->ts_res
, &ft
->mtime
);
6156 DEBUG(5,("smb_set_filetime: actime: %s\n ",
6157 time_to_asc(convert_timespec_to_time_t(ft
->atime
))));
6158 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
6159 time_to_asc(convert_timespec_to_time_t(ft
->mtime
))));
6160 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
6161 time_to_asc(convert_timespec_to_time_t(ft
->ctime
))));
6162 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
6163 time_to_asc(convert_timespec_to_time_t(ft
->create_time
))));
6165 if (setting_write_time
) {
6167 * This was a Windows setfileinfo on an open file.
6168 * NT does this a lot. We also need to
6169 * set the time here, as it can be read by
6170 * FindFirst/FindNext and with the patch for bug #2045
6171 * in smbd/fileio.c it ensures that this timestamp is
6172 * kept sticky even after a write. We save the request
6173 * away and will set it on file close and after a write. JRA.
6176 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
6177 time_to_asc(convert_timespec_to_time_t(ft
->mtime
))));
6180 if (fsp
->base_fsp
) {
6181 set_sticky_write_time_fsp(fsp
->base_fsp
,
6184 set_sticky_write_time_fsp(fsp
, ft
->mtime
);
6187 set_sticky_write_time_path(
6188 vfs_file_id_from_sbuf(conn
, &smb_fname
->st
),
6193 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
6195 /* Always call ntimes on the base, even if a stream was passed in. */
6196 smb_fname_base
= *smb_fname
;
6197 smb_fname_base
.stream_name
= NULL
;
6199 if(file_ntimes(conn
, &smb_fname_base
, ft
)!=0) {
6200 return map_nt_error_from_unix(errno
);
6203 notify_fname(conn
, NOTIFY_ACTION_MODIFIED
, action
,
6204 smb_fname
->base_name
);
6205 return NT_STATUS_OK
;
6208 /****************************************************************************
6209 Deal with setting the dosmode from any of the setfilepathinfo functions.
6210 NB. The check for FILE_WRITE_ATTRIBUTES access on this path must have been
6211 done before calling this function.
6212 ****************************************************************************/
6214 static NTSTATUS
smb_set_file_dosmode(connection_struct
*conn
,
6215 const struct smb_filename
*smb_fname
,
6218 struct smb_filename
*smb_fname_base
;
6221 if (!VALID_STAT(smb_fname
->st
)) {
6222 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
6225 /* Always operate on the base_name, even if a stream was passed in. */
6226 smb_fname_base
= synthetic_smb_fname(talloc_tos(),
6227 smb_fname
->base_name
,
6231 if (smb_fname_base
== NULL
) {
6232 return NT_STATUS_NO_MEMORY
;
6236 if (S_ISDIR(smb_fname_base
->st
.st_ex_mode
)) {
6237 dosmode
|= FILE_ATTRIBUTE_DIRECTORY
;
6239 dosmode
&= ~FILE_ATTRIBUTE_DIRECTORY
;
6243 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode
));
6245 /* check the mode isn't different, before changing it */
6246 if ((dosmode
!= 0) && (dosmode
!= dos_mode(conn
, smb_fname_base
))) {
6247 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
6248 "0x%x\n", smb_fname_str_dbg(smb_fname_base
),
6249 (unsigned int)dosmode
));
6251 if(file_set_dosmode(conn
, smb_fname_base
, dosmode
, NULL
,
6253 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
6255 smb_fname_str_dbg(smb_fname_base
),
6257 status
= map_nt_error_from_unix(errno
);
6261 status
= NT_STATUS_OK
;
6263 TALLOC_FREE(smb_fname_base
);
6267 /****************************************************************************
6268 Deal with setting the size from any of the setfilepathinfo functions.
6269 ****************************************************************************/
6271 static NTSTATUS
smb_set_file_size(connection_struct
*conn
,
6272 struct smb_request
*req
,
6274 const struct smb_filename
*smb_fname
,
6275 const SMB_STRUCT_STAT
*psbuf
,
6277 bool fail_after_createfile
)
6279 NTSTATUS status
= NT_STATUS_OK
;
6280 struct smb_filename
*smb_fname_tmp
= NULL
;
6281 files_struct
*new_fsp
= NULL
;
6283 if (!VALID_STAT(*psbuf
)) {
6284 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
6287 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size
));
6289 if (size
== get_file_size_stat(psbuf
)) {
6290 return NT_STATUS_OK
;
6293 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
6294 smb_fname_str_dbg(smb_fname
), (double)size
));
6296 if (fsp
&& fsp
->fh
->fd
!= -1) {
6297 /* Handle based call. */
6298 if (!(fsp
->access_mask
& FILE_WRITE_DATA
)) {
6299 return NT_STATUS_ACCESS_DENIED
;
6302 if (vfs_set_filelen(fsp
, size
) == -1) {
6303 return map_nt_error_from_unix(errno
);
6305 trigger_write_time_update_immediate(fsp
);
6306 return NT_STATUS_OK
;
6309 smb_fname_tmp
= cp_smb_filename(talloc_tos(), smb_fname
);
6310 if (smb_fname_tmp
== NULL
) {
6311 return NT_STATUS_NO_MEMORY
;
6314 smb_fname_tmp
->st
= *psbuf
;
6316 status
= SMB_VFS_CREATE_FILE(
6319 0, /* root_dir_fid */
6320 smb_fname_tmp
, /* fname */
6321 FILE_WRITE_DATA
, /* access_mask */
6322 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
6324 FILE_OPEN
, /* create_disposition*/
6325 0, /* create_options */
6326 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
6327 0, /* oplock_request */
6329 0, /* allocation_size */
6330 0, /* private_flags */
6333 &new_fsp
, /* result */
6335 NULL
, NULL
); /* create context */
6337 TALLOC_FREE(smb_fname_tmp
);
6339 if (!NT_STATUS_IS_OK(status
)) {
6340 /* NB. We check for open_was_deferred in the caller. */
6344 /* See RAW-SFILEINFO-END-OF-FILE */
6345 if (fail_after_createfile
) {
6346 close_file(req
, new_fsp
,NORMAL_CLOSE
);
6347 return NT_STATUS_INVALID_LEVEL
;
6350 if (vfs_set_filelen(new_fsp
, size
) == -1) {
6351 status
= map_nt_error_from_unix(errno
);
6352 close_file(req
, new_fsp
,NORMAL_CLOSE
);
6356 trigger_write_time_update_immediate(new_fsp
);
6357 close_file(req
, new_fsp
,NORMAL_CLOSE
);
6358 return NT_STATUS_OK
;
6361 /****************************************************************************
6362 Deal with SMB_INFO_SET_EA.
6363 ****************************************************************************/
6365 static NTSTATUS
smb_info_set_ea(connection_struct
*conn
,
6369 const struct smb_filename
*smb_fname
)
6371 struct ea_list
*ea_list
= NULL
;
6372 TALLOC_CTX
*ctx
= NULL
;
6373 NTSTATUS status
= NT_STATUS_OK
;
6375 if (total_data
< 10) {
6377 /* OS/2 workplace shell seems to send SET_EA requests of "null"
6378 length. They seem to have no effect. Bug #3212. JRA */
6380 if ((total_data
== 4) && (IVAL(pdata
,0) == 4)) {
6381 /* We're done. We only get EA info in this call. */
6382 return NT_STATUS_OK
;
6385 return NT_STATUS_INVALID_PARAMETER
;
6388 if (IVAL(pdata
,0) > total_data
) {
6389 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
6390 IVAL(pdata
,0), (unsigned int)total_data
));
6391 return NT_STATUS_INVALID_PARAMETER
;
6395 ea_list
= read_ea_list(ctx
, pdata
+ 4, total_data
- 4);
6397 return NT_STATUS_INVALID_PARAMETER
;
6400 status
= set_ea(conn
, fsp
, smb_fname
, ea_list
);
6405 /****************************************************************************
6406 Deal with SMB_FILE_FULL_EA_INFORMATION set.
6407 ****************************************************************************/
6409 static NTSTATUS
smb_set_file_full_ea_info(connection_struct
*conn
,
6414 struct ea_list
*ea_list
= NULL
;
6418 return NT_STATUS_INVALID_HANDLE
;
6421 if (!lp_ea_support(SNUM(conn
))) {
6422 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
6423 "EA's not supported.\n",
6424 (unsigned int)total_data
));
6425 return NT_STATUS_EAS_NOT_SUPPORTED
;
6428 if (total_data
< 10) {
6429 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
6431 (unsigned int)total_data
));
6432 return NT_STATUS_INVALID_PARAMETER
;
6435 ea_list
= read_nttrans_ea_list(talloc_tos(),
6440 return NT_STATUS_INVALID_PARAMETER
;
6443 status
= set_ea(conn
, fsp
, fsp
->fsp_name
, ea_list
);
6445 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
6446 smb_fname_str_dbg(fsp
->fsp_name
),
6447 nt_errstr(status
) ));
6453 /****************************************************************************
6454 Deal with SMB_SET_FILE_DISPOSITION_INFO.
6455 ****************************************************************************/
6457 static NTSTATUS
smb_set_file_disposition_info(connection_struct
*conn
,
6461 struct smb_filename
*smb_fname
)
6463 NTSTATUS status
= NT_STATUS_OK
;
6464 bool delete_on_close
;
6465 uint32_t dosmode
= 0;
6467 if (total_data
< 1) {
6468 return NT_STATUS_INVALID_PARAMETER
;
6472 return NT_STATUS_INVALID_HANDLE
;
6475 delete_on_close
= (CVAL(pdata
,0) ? True
: False
);
6476 dosmode
= dos_mode(conn
, smb_fname
);
6478 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
6479 "delete_on_close = %u\n",
6480 smb_fname_str_dbg(smb_fname
),
6481 (unsigned int)dosmode
,
6482 (unsigned int)delete_on_close
));
6484 if (delete_on_close
) {
6485 status
= can_set_delete_on_close(fsp
, dosmode
);
6486 if (!NT_STATUS_IS_OK(status
)) {
6491 /* The set is across all open files on this dev/inode pair. */
6492 if (!set_delete_on_close(fsp
, delete_on_close
,
6493 conn
->session_info
->security_token
,
6494 conn
->session_info
->unix_token
)) {
6495 return NT_STATUS_ACCESS_DENIED
;
6497 return NT_STATUS_OK
;
6500 /****************************************************************************
6501 Deal with SMB_FILE_POSITION_INFORMATION.
6502 ****************************************************************************/
6504 static NTSTATUS
smb_file_position_information(connection_struct
*conn
,
6509 uint64_t position_information
;
6511 if (total_data
< 8) {
6512 return NT_STATUS_INVALID_PARAMETER
;
6516 /* Ignore on pathname based set. */
6517 return NT_STATUS_OK
;
6520 position_information
= (uint64_t)IVAL(pdata
,0);
6521 position_information
|= (((uint64_t)IVAL(pdata
,4)) << 32);
6523 DEBUG(10,("smb_file_position_information: Set file position "
6524 "information for file %s to %.0f\n", fsp_str_dbg(fsp
),
6525 (double)position_information
));
6526 fsp
->fh
->position_information
= position_information
;
6527 return NT_STATUS_OK
;
6530 /****************************************************************************
6531 Deal with SMB_FILE_MODE_INFORMATION.
6532 ****************************************************************************/
6534 static NTSTATUS
smb_file_mode_information(connection_struct
*conn
,
6540 if (total_data
< 4) {
6541 return NT_STATUS_INVALID_PARAMETER
;
6543 mode
= IVAL(pdata
,0);
6544 if (mode
!= 0 && mode
!= 2 && mode
!= 4 && mode
!= 6) {
6545 return NT_STATUS_INVALID_PARAMETER
;
6547 return NT_STATUS_OK
;
6550 /****************************************************************************
6551 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
6552 ****************************************************************************/
6554 static NTSTATUS
smb_set_file_unix_link(connection_struct
*conn
,
6555 struct smb_request
*req
,
6558 const struct smb_filename
*smb_fname
)
6560 char *link_target
= NULL
;
6561 const char *newname
= smb_fname
->base_name
;
6562 TALLOC_CTX
*ctx
= talloc_tos();
6564 /* Set a symbolic link. */
6565 /* Don't allow this if follow links is false. */
6567 if (total_data
== 0) {
6568 return NT_STATUS_INVALID_PARAMETER
;
6571 if (!lp_follow_symlinks(SNUM(conn
))) {
6572 return NT_STATUS_ACCESS_DENIED
;
6575 srvstr_pull_talloc(ctx
, pdata
, req
->flags2
, &link_target
, pdata
,
6576 total_data
, STR_TERMINATE
);
6579 return NT_STATUS_INVALID_PARAMETER
;
6582 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
6583 newname
, link_target
));
6585 if (SMB_VFS_SYMLINK(conn
,link_target
,newname
) != 0) {
6586 return map_nt_error_from_unix(errno
);
6589 return NT_STATUS_OK
;
6592 /****************************************************************************
6593 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
6594 ****************************************************************************/
6596 static NTSTATUS
smb_set_file_unix_hlink(connection_struct
*conn
,
6597 struct smb_request
*req
,
6598 const char *pdata
, int total_data
,
6599 struct smb_filename
*smb_fname_new
)
6601 char *oldname
= NULL
;
6602 struct smb_filename
*smb_fname_old
= NULL
;
6603 uint32_t ucf_flags
= (req
->posix_pathnames
? UCF_POSIX_PATHNAMES
: 0);
6604 TALLOC_CTX
*ctx
= talloc_tos();
6605 NTSTATUS status
= NT_STATUS_OK
;
6607 /* Set a hard link. */
6608 if (total_data
== 0) {
6609 return NT_STATUS_INVALID_PARAMETER
;
6612 if (req
->posix_pathnames
) {
6613 srvstr_get_path_posix(ctx
,
6622 srvstr_get_path(ctx
,
6631 if (!NT_STATUS_IS_OK(status
)) {
6635 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
6636 smb_fname_str_dbg(smb_fname_new
), oldname
));
6638 status
= filename_convert(ctx
,
6640 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6645 if (!NT_STATUS_IS_OK(status
)) {
6649 return hardlink_internals(ctx
, conn
, req
, false,
6650 smb_fname_old
, smb_fname_new
);
6653 /****************************************************************************
6654 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
6655 ****************************************************************************/
6657 static NTSTATUS
smb2_file_rename_information(connection_struct
*conn
,
6658 struct smb_request
*req
,
6662 struct smb_filename
*smb_fname_src
)
6666 char *newname
= NULL
;
6667 struct smb_filename
*smb_fname_dst
= NULL
;
6668 uint32_t ucf_flags
= UCF_SAVE_LCOMP
|
6669 (req
->posix_pathnames
? UCF_POSIX_PATHNAMES
: 0);
6670 NTSTATUS status
= NT_STATUS_OK
;
6671 TALLOC_CTX
*ctx
= talloc_tos();
6674 return NT_STATUS_INVALID_HANDLE
;
6677 if (total_data
< 20) {
6678 return NT_STATUS_INVALID_PARAMETER
;
6681 overwrite
= (CVAL(pdata
,0) ? True
: False
);
6682 len
= IVAL(pdata
,16);
6684 if (len
> (total_data
- 20) || (len
== 0)) {
6685 return NT_STATUS_INVALID_PARAMETER
;
6688 if (req
->posix_pathnames
) {
6689 srvstr_get_path_posix(ctx
,
6698 srvstr_get_path(ctx
,
6707 if (!NT_STATUS_IS_OK(status
)) {
6711 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
6714 status
= filename_convert(ctx
,
6716 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6721 if (!NT_STATUS_IS_OK(status
)) {
6725 if (fsp
->base_fsp
) {
6726 /* newname must be a stream name. */
6727 if (newname
[0] != ':') {
6728 return NT_STATUS_NOT_SUPPORTED
;
6731 /* Create an smb_fname to call rename_internals_fsp() with. */
6732 smb_fname_dst
= synthetic_smb_fname(talloc_tos(),
6733 fsp
->base_fsp
->fsp_name
->base_name
,
6736 fsp
->base_fsp
->fsp_name
->flags
);
6737 if (smb_fname_dst
== NULL
) {
6738 status
= NT_STATUS_NO_MEMORY
;
6743 * Set the original last component, since
6744 * rename_internals_fsp() requires it.
6746 smb_fname_dst
->original_lcomp
= talloc_strdup(smb_fname_dst
,
6748 if (smb_fname_dst
->original_lcomp
== NULL
) {
6749 status
= NT_STATUS_NO_MEMORY
;
6755 DEBUG(10,("smb2_file_rename_information: "
6756 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
6757 fsp_fnum_dbg(fsp
), fsp_str_dbg(fsp
),
6758 smb_fname_str_dbg(smb_fname_dst
)));
6759 status
= rename_internals_fsp(conn
, fsp
, smb_fname_dst
,
6760 (FILE_ATTRIBUTE_HIDDEN
|FILE_ATTRIBUTE_SYSTEM
),
6764 TALLOC_FREE(smb_fname_dst
);
6768 static NTSTATUS
smb_file_link_information(connection_struct
*conn
,
6769 struct smb_request
*req
,
6773 struct smb_filename
*smb_fname_src
)
6777 char *newname
= NULL
;
6778 struct smb_filename
*smb_fname_dst
= NULL
;
6779 NTSTATUS status
= NT_STATUS_OK
;
6780 uint32_t ucf_flags
= UCF_SAVE_LCOMP
|
6781 (req
->posix_pathnames
? UCF_POSIX_PATHNAMES
: 0);
6782 TALLOC_CTX
*ctx
= talloc_tos();
6785 return NT_STATUS_INVALID_HANDLE
;
6788 if (total_data
< 20) {
6789 return NT_STATUS_INVALID_PARAMETER
;
6792 overwrite
= (CVAL(pdata
,0) ? true : false);
6793 len
= IVAL(pdata
,16);
6795 if (len
> (total_data
- 20) || (len
== 0)) {
6796 return NT_STATUS_INVALID_PARAMETER
;
6799 if (req
->posix_pathnames
) {
6800 srvstr_get_path_posix(ctx
,
6809 srvstr_get_path(ctx
,
6818 if (!NT_STATUS_IS_OK(status
)) {
6822 DEBUG(10,("smb_file_link_information: got name |%s|\n",
6825 status
= filename_convert(ctx
,
6827 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6832 if (!NT_STATUS_IS_OK(status
)) {
6836 if (fsp
->base_fsp
) {
6837 /* No stream names. */
6838 return NT_STATUS_NOT_SUPPORTED
;
6841 DEBUG(10,("smb_file_link_information: "
6842 "SMB_FILE_LINK_INFORMATION (%s) %s -> %s\n",
6843 fsp_fnum_dbg(fsp
), fsp_str_dbg(fsp
),
6844 smb_fname_str_dbg(smb_fname_dst
)));
6845 status
= hardlink_internals(ctx
,
6852 TALLOC_FREE(smb_fname_dst
);
6856 /****************************************************************************
6857 Deal with SMB_FILE_RENAME_INFORMATION.
6858 ****************************************************************************/
6860 static NTSTATUS
smb_file_rename_information(connection_struct
*conn
,
6861 struct smb_request
*req
,
6865 struct smb_filename
*smb_fname_src
)
6870 char *newname
= NULL
;
6871 struct smb_filename
*smb_fname_dst
= NULL
;
6872 bool dest_has_wcard
= False
;
6873 NTSTATUS status
= NT_STATUS_OK
;
6875 TALLOC_CTX
*ctx
= talloc_tos();
6877 if (total_data
< 13) {
6878 return NT_STATUS_INVALID_PARAMETER
;
6881 overwrite
= (CVAL(pdata
,0) ? True
: False
);
6882 root_fid
= IVAL(pdata
,4);
6883 len
= IVAL(pdata
,8);
6885 if (len
> (total_data
- 12) || (len
== 0) || (root_fid
!= 0)) {
6886 return NT_STATUS_INVALID_PARAMETER
;
6889 if (req
->posix_pathnames
) {
6890 srvstr_get_path_wcard_posix(ctx
,
6900 srvstr_get_path_wcard(ctx
,
6910 if (!NT_STATUS_IS_OK(status
)) {
6914 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
6917 status
= resolve_dfspath_wcard(ctx
, conn
,
6918 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6920 UCF_COND_ALLOW_WCARD_LCOMP
,
6921 !conn
->sconn
->using_smb2
,
6924 if (!NT_STATUS_IS_OK(status
)) {
6928 /* Check the new name has no '/' characters. */
6929 if (strchr_m(newname
, '/')) {
6930 return NT_STATUS_NOT_SUPPORTED
;
6933 if (fsp
&& fsp
->base_fsp
) {
6934 /* newname must be a stream name. */
6935 if (newname
[0] != ':') {
6936 return NT_STATUS_NOT_SUPPORTED
;
6939 /* Create an smb_fname to call rename_internals_fsp() with. */
6940 smb_fname_dst
= synthetic_smb_fname(talloc_tos(),
6941 fsp
->base_fsp
->fsp_name
->base_name
,
6944 fsp
->base_fsp
->fsp_name
->flags
);
6945 if (smb_fname_dst
== NULL
) {
6946 status
= NT_STATUS_NO_MEMORY
;
6951 * Set the original last component, since
6952 * rename_internals_fsp() requires it.
6954 smb_fname_dst
->original_lcomp
= talloc_strdup(smb_fname_dst
,
6956 if (smb_fname_dst
->original_lcomp
== NULL
) {
6957 status
= NT_STATUS_NO_MEMORY
;
6963 * Build up an smb_fname_dst based on the filename passed in.
6964 * We basically just strip off the last component, and put on
6965 * the newname instead.
6967 char *base_name
= NULL
;
6969 /* newname must *not* be a stream name. */
6970 if (newname
[0] == ':') {
6971 return NT_STATUS_NOT_SUPPORTED
;
6975 * Strip off the last component (filename) of the path passed
6978 base_name
= talloc_strdup(ctx
, smb_fname_src
->base_name
);
6980 return NT_STATUS_NO_MEMORY
;
6982 p
= strrchr_m(base_name
, '/');
6986 base_name
= talloc_strdup(ctx
, "");
6988 return NT_STATUS_NO_MEMORY
;
6991 /* Append the new name. */
6992 base_name
= talloc_asprintf_append(base_name
,
6996 return NT_STATUS_NO_MEMORY
;
6999 status
= unix_convert(ctx
, conn
, base_name
, &smb_fname_dst
,
7002 UCF_ALWAYS_ALLOW_WCARD_LCOMP
:
7005 /* If an error we expect this to be
7006 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
7008 if (!NT_STATUS_IS_OK(status
)) {
7009 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND
,
7013 /* Create an smb_fname to call rename_internals_fsp() */
7014 smb_fname_dst
= synthetic_smb_fname(ctx
,
7018 smb_fname_src
->flags
);
7019 if (smb_fname_dst
== NULL
) {
7020 status
= NT_STATUS_NO_MEMORY
;
7027 DEBUG(10,("smb_file_rename_information: "
7028 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
7029 fsp_fnum_dbg(fsp
), fsp_str_dbg(fsp
),
7030 smb_fname_str_dbg(smb_fname_dst
)));
7031 status
= rename_internals_fsp(conn
, fsp
, smb_fname_dst
, 0,
7034 DEBUG(10,("smb_file_rename_information: "
7035 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
7036 smb_fname_str_dbg(smb_fname_src
),
7037 smb_fname_str_dbg(smb_fname_dst
)));
7038 status
= rename_internals(ctx
, conn
, req
, smb_fname_src
,
7039 smb_fname_dst
, 0, overwrite
, false,
7041 FILE_WRITE_ATTRIBUTES
);
7044 TALLOC_FREE(smb_fname_dst
);
7048 /****************************************************************************
7049 Deal with SMB_SET_POSIX_ACL.
7050 ****************************************************************************/
7052 #if defined(HAVE_POSIX_ACLS)
7053 static NTSTATUS
smb_set_posix_acl(connection_struct
*conn
,
7057 const struct smb_filename
*smb_fname
)
7059 uint16_t posix_acl_version
;
7060 uint16_t num_file_acls
;
7061 uint16_t num_def_acls
;
7062 bool valid_file_acls
= True
;
7063 bool valid_def_acls
= True
;
7066 if (total_data
< SMB_POSIX_ACL_HEADER_SIZE
) {
7067 return NT_STATUS_INVALID_PARAMETER
;
7069 posix_acl_version
= SVAL(pdata
,0);
7070 num_file_acls
= SVAL(pdata
,2);
7071 num_def_acls
= SVAL(pdata
,4);
7073 if (num_file_acls
== SMB_POSIX_IGNORE_ACE_ENTRIES
) {
7074 valid_file_acls
= False
;
7078 if (num_def_acls
== SMB_POSIX_IGNORE_ACE_ENTRIES
) {
7079 valid_def_acls
= False
;
7083 if (posix_acl_version
!= SMB_POSIX_ACL_VERSION
) {
7084 return NT_STATUS_INVALID_PARAMETER
;
7087 if (total_data
< SMB_POSIX_ACL_HEADER_SIZE
+
7088 (num_file_acls
+num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
) {
7089 return NT_STATUS_INVALID_PARAMETER
;
7092 status
= refuse_symlink(conn
, fsp
, smb_fname
);
7093 if (!NT_STATUS_IS_OK(status
)) {
7097 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
7098 smb_fname
? smb_fname_str_dbg(smb_fname
) : fsp_str_dbg(fsp
),
7099 (unsigned int)num_file_acls
,
7100 (unsigned int)num_def_acls
));
7102 if (valid_file_acls
&& !set_unix_posix_acl(conn
, fsp
,
7103 smb_fname
->base_name
, num_file_acls
,
7104 pdata
+ SMB_POSIX_ACL_HEADER_SIZE
)) {
7105 return map_nt_error_from_unix(errno
);
7108 if (valid_def_acls
&& !set_unix_posix_default_acl(conn
,
7109 smb_fname
->base_name
, &smb_fname
->st
, num_def_acls
,
7110 pdata
+ SMB_POSIX_ACL_HEADER_SIZE
+
7111 (num_file_acls
*SMB_POSIX_ACL_ENTRY_SIZE
))) {
7112 return map_nt_error_from_unix(errno
);
7114 return NT_STATUS_OK
;
7118 /****************************************************************************
7119 Deal with SMB_SET_POSIX_LOCK.
7120 ****************************************************************************/
7122 static NTSTATUS
smb_set_posix_lock(connection_struct
*conn
,
7123 struct smb_request
*req
,
7131 bool blocking_lock
= False
;
7132 enum brl_type lock_type
;
7134 NTSTATUS status
= NT_STATUS_OK
;
7136 if (fsp
== NULL
|| fsp
->fh
->fd
== -1) {
7137 return NT_STATUS_INVALID_HANDLE
;
7140 if (total_data
!= POSIX_LOCK_DATA_SIZE
) {
7141 return NT_STATUS_INVALID_PARAMETER
;
7144 switch (SVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
)) {
7145 case POSIX_LOCK_TYPE_READ
:
7146 lock_type
= READ_LOCK
;
7148 case POSIX_LOCK_TYPE_WRITE
:
7149 /* Return the right POSIX-mappable error code for files opened read-only. */
7150 if (!fsp
->can_write
) {
7151 return NT_STATUS_INVALID_HANDLE
;
7153 lock_type
= WRITE_LOCK
;
7155 case POSIX_LOCK_TYPE_UNLOCK
:
7156 lock_type
= UNLOCK_LOCK
;
7159 return NT_STATUS_INVALID_PARAMETER
;
7162 if (SVAL(pdata
,POSIX_LOCK_FLAGS_OFFSET
) == POSIX_LOCK_FLAG_NOWAIT
) {
7163 blocking_lock
= False
;
7164 } else if (SVAL(pdata
,POSIX_LOCK_FLAGS_OFFSET
) == POSIX_LOCK_FLAG_WAIT
) {
7165 blocking_lock
= True
;
7167 return NT_STATUS_INVALID_PARAMETER
;
7170 if (!lp_blocking_locks(SNUM(conn
))) {
7171 blocking_lock
= False
;
7174 smblctx
= (uint64_t)IVAL(pdata
, POSIX_LOCK_PID_OFFSET
);
7175 offset
= (((uint64_t) IVAL(pdata
,(POSIX_LOCK_START_OFFSET
+4))) << 32) |
7176 ((uint64_t) IVAL(pdata
,POSIX_LOCK_START_OFFSET
));
7177 count
= (((uint64_t) IVAL(pdata
,(POSIX_LOCK_LEN_OFFSET
+4))) << 32) |
7178 ((uint64_t) IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
));
7180 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
7181 "smblctx = %llu, count = %.0f, offset = %.0f\n",
7183 (unsigned int)lock_type
,
7184 (unsigned long long)smblctx
,
7188 if (lock_type
== UNLOCK_LOCK
) {
7189 status
= do_unlock(req
->sconn
->msg_ctx
,
7196 uint64_t block_smblctx
;
7198 struct byte_range_lock
*br_lck
= do_lock(req
->sconn
->msg_ctx
,
7209 if (br_lck
&& blocking_lock
&& ERROR_WAS_LOCK_DENIED(status
)) {
7211 * A blocking lock was requested. Package up
7212 * this smb into a queued request and push it
7213 * onto the blocking lock queue.
7215 if(push_blocking_lock_request(br_lck
,
7218 -1, /* infinite timeout. */
7226 TALLOC_FREE(br_lck
);
7230 TALLOC_FREE(br_lck
);
7236 /****************************************************************************
7237 Deal with SMB_SET_FILE_BASIC_INFO.
7238 ****************************************************************************/
7240 static NTSTATUS
smb_set_file_basic_info(connection_struct
*conn
,
7244 const struct smb_filename
*smb_fname
)
7246 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
7247 struct smb_file_time ft
;
7248 uint32_t dosmode
= 0;
7249 NTSTATUS status
= NT_STATUS_OK
;
7253 if (total_data
< 36) {
7254 return NT_STATUS_INVALID_PARAMETER
;
7257 status
= check_access(conn
, fsp
, smb_fname
, FILE_WRITE_ATTRIBUTES
);
7258 if (!NT_STATUS_IS_OK(status
)) {
7262 /* Set the attributes */
7263 dosmode
= IVAL(pdata
,32);
7264 status
= smb_set_file_dosmode(conn
, smb_fname
, dosmode
);
7265 if (!NT_STATUS_IS_OK(status
)) {
7270 ft
.create_time
= interpret_long_date(pdata
);
7273 ft
.atime
= interpret_long_date(pdata
+8);
7276 ft
.mtime
= interpret_long_date(pdata
+16);
7279 ft
.ctime
= interpret_long_date(pdata
+24);
7281 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
7282 smb_fname_str_dbg(smb_fname
)));
7284 return smb_set_file_time(conn
, fsp
, smb_fname
, &ft
,
7288 /****************************************************************************
7289 Deal with SMB_INFO_STANDARD.
7290 ****************************************************************************/
7292 static NTSTATUS
smb_set_info_standard(connection_struct
*conn
,
7296 const struct smb_filename
*smb_fname
)
7299 struct smb_file_time ft
;
7303 if (total_data
< 12) {
7304 return NT_STATUS_INVALID_PARAMETER
;
7308 ft
.create_time
= convert_time_t_to_timespec(srv_make_unix_date2(pdata
));
7310 ft
.atime
= convert_time_t_to_timespec(srv_make_unix_date2(pdata
+4));
7312 ft
.mtime
= convert_time_t_to_timespec(srv_make_unix_date2(pdata
+8));
7314 DEBUG(10,("smb_set_info_standard: file %s\n",
7315 smb_fname_str_dbg(smb_fname
)));
7317 status
= check_access(conn
, fsp
, smb_fname
, FILE_WRITE_ATTRIBUTES
);
7318 if (!NT_STATUS_IS_OK(status
)) {
7322 return smb_set_file_time(conn
,
7329 /****************************************************************************
7330 Deal with SMB_SET_FILE_ALLOCATION_INFO.
7331 ****************************************************************************/
7333 static NTSTATUS
smb_set_file_allocation_info(connection_struct
*conn
,
7334 struct smb_request
*req
,
7338 struct smb_filename
*smb_fname
)
7340 uint64_t allocation_size
= 0;
7341 NTSTATUS status
= NT_STATUS_OK
;
7342 files_struct
*new_fsp
= NULL
;
7344 if (!VALID_STAT(smb_fname
->st
)) {
7345 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
7348 if (total_data
< 8) {
7349 return NT_STATUS_INVALID_PARAMETER
;
7352 allocation_size
= (uint64_t)IVAL(pdata
,0);
7353 allocation_size
|= (((uint64_t)IVAL(pdata
,4)) << 32);
7354 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
7355 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname
),
7356 (double)allocation_size
));
7358 if (allocation_size
) {
7359 allocation_size
= smb_roundup(conn
, allocation_size
);
7362 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
7363 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname
),
7364 (double)allocation_size
));
7366 if (fsp
&& fsp
->fh
->fd
!= -1) {
7367 /* Open file handle. */
7368 if (!(fsp
->access_mask
& FILE_WRITE_DATA
)) {
7369 return NT_STATUS_ACCESS_DENIED
;
7372 /* Only change if needed. */
7373 if (allocation_size
!= get_file_size_stat(&smb_fname
->st
)) {
7374 if (vfs_allocate_file_space(fsp
, allocation_size
) == -1) {
7375 return map_nt_error_from_unix(errno
);
7378 /* But always update the time. */
7380 * This is equivalent to a write. Ensure it's seen immediately
7381 * if there are no pending writes.
7383 trigger_write_time_update_immediate(fsp
);
7384 return NT_STATUS_OK
;
7387 /* Pathname or stat or directory file. */
7388 status
= SMB_VFS_CREATE_FILE(
7391 0, /* root_dir_fid */
7392 smb_fname
, /* fname */
7393 FILE_WRITE_DATA
, /* access_mask */
7394 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
7396 FILE_OPEN
, /* create_disposition*/
7397 0, /* create_options */
7398 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
7399 0, /* oplock_request */
7401 0, /* allocation_size */
7402 0, /* private_flags */
7405 &new_fsp
, /* result */
7407 NULL
, NULL
); /* create context */
7409 if (!NT_STATUS_IS_OK(status
)) {
7410 /* NB. We check for open_was_deferred in the caller. */
7414 /* Only change if needed. */
7415 if (allocation_size
!= get_file_size_stat(&smb_fname
->st
)) {
7416 if (vfs_allocate_file_space(new_fsp
, allocation_size
) == -1) {
7417 status
= map_nt_error_from_unix(errno
);
7418 close_file(req
, new_fsp
, NORMAL_CLOSE
);
7423 /* Changing the allocation size should set the last mod time. */
7425 * This is equivalent to a write. Ensure it's seen immediately
7426 * if there are no pending writes.
7428 trigger_write_time_update_immediate(new_fsp
);
7429 close_file(req
, new_fsp
, NORMAL_CLOSE
);
7430 return NT_STATUS_OK
;
7433 /****************************************************************************
7434 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
7435 ****************************************************************************/
7437 static NTSTATUS
smb_set_file_end_of_file_info(connection_struct
*conn
,
7438 struct smb_request
*req
,
7442 const struct smb_filename
*smb_fname
,
7443 bool fail_after_createfile
)
7447 if (total_data
< 8) {
7448 return NT_STATUS_INVALID_PARAMETER
;
7451 size
= IVAL(pdata
,0);
7452 size
|= (((off_t
)IVAL(pdata
,4)) << 32);
7453 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
7454 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname
),
7457 return smb_set_file_size(conn
, req
,
7462 fail_after_createfile
);
7465 /****************************************************************************
7466 Allow a UNIX info mknod.
7467 ****************************************************************************/
7469 static NTSTATUS
smb_unix_mknod(connection_struct
*conn
,
7472 const struct smb_filename
*smb_fname
)
7474 uint32_t file_type
= IVAL(pdata
,56);
7475 #if defined(HAVE_MAKEDEV)
7476 uint32_t dev_major
= IVAL(pdata
,60);
7477 uint32_t dev_minor
= IVAL(pdata
,68);
7479 SMB_DEV_T dev
= (SMB_DEV_T
)0;
7480 uint32_t raw_unixmode
= IVAL(pdata
,84);
7484 if (total_data
< 100) {
7485 return NT_STATUS_INVALID_PARAMETER
;
7488 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
7489 PERM_NEW_FILE
, &unixmode
);
7490 if (!NT_STATUS_IS_OK(status
)) {
7494 #if defined(HAVE_MAKEDEV)
7495 dev
= makedev(dev_major
, dev_minor
);
7498 switch (file_type
) {
7499 #if defined(S_IFIFO)
7500 case UNIX_TYPE_FIFO
:
7501 unixmode
|= S_IFIFO
;
7504 #if defined(S_IFSOCK)
7505 case UNIX_TYPE_SOCKET
:
7506 unixmode
|= S_IFSOCK
;
7509 #if defined(S_IFCHR)
7510 case UNIX_TYPE_CHARDEV
:
7511 unixmode
|= S_IFCHR
;
7514 #if defined(S_IFBLK)
7515 case UNIX_TYPE_BLKDEV
:
7516 unixmode
|= S_IFBLK
;
7520 return NT_STATUS_INVALID_PARAMETER
;
7523 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
7524 "%.0f mode 0%o for file %s\n", (double)dev
,
7525 (unsigned int)unixmode
, smb_fname_str_dbg(smb_fname
)));
7527 /* Ok - do the mknod. */
7528 if (SMB_VFS_MKNOD(conn
, smb_fname
->base_name
, unixmode
, dev
) != 0) {
7529 return map_nt_error_from_unix(errno
);
7532 /* If any of the other "set" calls fail we
7533 * don't want to end up with a half-constructed mknod.
7536 if (lp_inherit_permissions(SNUM(conn
))) {
7538 if (!parent_dirname(talloc_tos(), smb_fname
->base_name
,
7540 return NT_STATUS_NO_MEMORY
;
7542 inherit_access_posix_acl(conn
, parent
, smb_fname
->base_name
,
7544 TALLOC_FREE(parent
);
7547 return NT_STATUS_OK
;
7550 /****************************************************************************
7551 Deal with SMB_SET_FILE_UNIX_BASIC.
7552 ****************************************************************************/
7554 static NTSTATUS
smb_set_file_unix_basic(connection_struct
*conn
,
7555 struct smb_request
*req
,
7559 const struct smb_filename
*smb_fname
)
7561 struct smb_file_time ft
;
7562 uint32_t raw_unixmode
;
7565 uid_t set_owner
= (uid_t
)SMB_UID_NO_CHANGE
;
7566 gid_t set_grp
= (uid_t
)SMB_GID_NO_CHANGE
;
7567 NTSTATUS status
= NT_STATUS_OK
;
7568 bool delete_on_fail
= False
;
7569 enum perm_type ptype
;
7570 files_struct
*all_fsps
= NULL
;
7571 bool modify_mtime
= true;
7573 struct smb_filename
*smb_fname_tmp
= NULL
;
7574 SMB_STRUCT_STAT sbuf
;
7578 if (total_data
< 100) {
7579 return NT_STATUS_INVALID_PARAMETER
;
7582 if(IVAL(pdata
, 0) != SMB_SIZE_NO_CHANGE_LO
&&
7583 IVAL(pdata
, 4) != SMB_SIZE_NO_CHANGE_HI
) {
7584 size
=IVAL(pdata
,0); /* first 8 Bytes are size */
7585 size
|= (((off_t
)IVAL(pdata
,4)) << 32);
7588 ft
.atime
= interpret_long_date(pdata
+24); /* access_time */
7589 ft
.mtime
= interpret_long_date(pdata
+32); /* modification_time */
7590 set_owner
= (uid_t
)IVAL(pdata
,40);
7591 set_grp
= (gid_t
)IVAL(pdata
,48);
7592 raw_unixmode
= IVAL(pdata
,84);
7594 if (VALID_STAT(smb_fname
->st
)) {
7595 if (S_ISDIR(smb_fname
->st
.st_ex_mode
)) {
7596 ptype
= PERM_EXISTING_DIR
;
7598 ptype
= PERM_EXISTING_FILE
;
7601 ptype
= PERM_NEW_FILE
;
7604 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
7606 if (!NT_STATUS_IS_OK(status
)) {
7610 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
7611 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
7612 smb_fname_str_dbg(smb_fname
), (double)size
,
7613 (unsigned int)set_owner
, (unsigned int)set_grp
,
7614 (int)raw_unixmode
));
7616 sbuf
= smb_fname
->st
;
7618 if (!VALID_STAT(sbuf
)) {
7620 * The only valid use of this is to create character and block
7621 * devices, and named pipes. This is deprecated (IMHO) and
7622 * a new info level should be used for mknod. JRA.
7625 status
= smb_unix_mknod(conn
,
7629 if (!NT_STATUS_IS_OK(status
)) {
7633 smb_fname_tmp
= cp_smb_filename(talloc_tos(), smb_fname
);
7634 if (smb_fname_tmp
== NULL
) {
7635 return NT_STATUS_NO_MEMORY
;
7638 if (SMB_VFS_STAT(conn
, smb_fname_tmp
) != 0) {
7639 status
= map_nt_error_from_unix(errno
);
7640 TALLOC_FREE(smb_fname_tmp
);
7641 SMB_VFS_UNLINK(conn
, smb_fname
);
7645 sbuf
= smb_fname_tmp
->st
;
7646 smb_fname
= smb_fname_tmp
;
7648 /* Ensure we don't try and change anything else. */
7649 raw_unixmode
= SMB_MODE_NO_CHANGE
;
7650 size
= get_file_size_stat(&sbuf
);
7651 ft
.atime
= sbuf
.st_ex_atime
;
7652 ft
.mtime
= sbuf
.st_ex_mtime
;
7654 * We continue here as we might want to change the
7657 delete_on_fail
= True
;
7661 /* Horrible backwards compatibility hack as an old server bug
7662 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
7666 size
= get_file_size_stat(&sbuf
);
7671 * Deal with the UNIX specific mode set.
7674 if (raw_unixmode
!= SMB_MODE_NO_CHANGE
) {
7677 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7678 "setting mode 0%o for file %s\n",
7679 (unsigned int)unixmode
,
7680 smb_fname_str_dbg(smb_fname
)));
7681 if (fsp
&& fsp
->fh
->fd
!= -1) {
7682 ret
= SMB_VFS_FCHMOD(fsp
, unixmode
);
7684 ret
= SMB_VFS_CHMOD(conn
, smb_fname
, unixmode
);
7687 return map_nt_error_from_unix(errno
);
7692 * Deal with the UNIX specific uid set.
7695 if ((set_owner
!= (uid_t
)SMB_UID_NO_CHANGE
) &&
7696 (sbuf
.st_ex_uid
!= set_owner
)) {
7699 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7700 "changing owner %u for path %s\n",
7701 (unsigned int)set_owner
,
7702 smb_fname_str_dbg(smb_fname
)));
7704 if (fsp
&& fsp
->fh
->fd
!= -1) {
7705 ret
= SMB_VFS_FCHOWN(fsp
, set_owner
, (gid_t
)-1);
7708 * UNIX extensions calls must always operate
7711 ret
= SMB_VFS_LCHOWN(conn
, smb_fname
,
7712 set_owner
, (gid_t
)-1);
7716 status
= map_nt_error_from_unix(errno
);
7717 if (delete_on_fail
) {
7718 SMB_VFS_UNLINK(conn
, smb_fname
);
7725 * Deal with the UNIX specific gid set.
7728 if ((set_grp
!= (uid_t
)SMB_GID_NO_CHANGE
) &&
7729 (sbuf
.st_ex_gid
!= set_grp
)) {
7732 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7733 "changing group %u for file %s\n",
7734 (unsigned int)set_owner
,
7735 smb_fname_str_dbg(smb_fname
)));
7736 if (fsp
&& fsp
->fh
->fd
!= -1) {
7737 ret
= SMB_VFS_FCHOWN(fsp
, set_owner
, (gid_t
)-1);
7740 * UNIX extensions calls must always operate
7743 ret
= SMB_VFS_LCHOWN(conn
, smb_fname
, (uid_t
)-1,
7747 status
= map_nt_error_from_unix(errno
);
7748 if (delete_on_fail
) {
7749 SMB_VFS_UNLINK(conn
, smb_fname
);
7755 /* Deal with any size changes. */
7757 status
= smb_set_file_size(conn
, req
,
7763 if (!NT_STATUS_IS_OK(status
)) {
7767 /* Deal with any time changes. */
7768 if (null_timespec(ft
.mtime
) && null_timespec(ft
.atime
)) {
7769 /* No change, don't cancel anything. */
7773 id
= vfs_file_id_from_sbuf(conn
, &sbuf
);
7774 for(all_fsps
= file_find_di_first(conn
->sconn
, id
); all_fsps
;
7775 all_fsps
= file_find_di_next(all_fsps
)) {
7777 * We're setting the time explicitly for UNIX.
7778 * Cancel any pending changes over all handles.
7780 all_fsps
->update_write_time_on_close
= false;
7781 TALLOC_FREE(all_fsps
->update_write_time_event
);
7785 * Override the "setting_write_time"
7786 * parameter here as it almost does what
7787 * we need. Just remember if we modified
7788 * mtime and send the notify ourselves.
7790 if (null_timespec(ft
.mtime
)) {
7791 modify_mtime
= false;
7794 status
= smb_set_file_time(conn
,
7800 notify_fname(conn
, NOTIFY_ACTION_MODIFIED
,
7801 FILE_NOTIFY_CHANGE_LAST_WRITE
, smb_fname
->base_name
);
7806 /****************************************************************************
7807 Deal with SMB_SET_FILE_UNIX_INFO2.
7808 ****************************************************************************/
7810 static NTSTATUS
smb_set_file_unix_info2(connection_struct
*conn
,
7811 struct smb_request
*req
,
7815 const struct smb_filename
*smb_fname
)
7818 uint32_t smb_fflags
;
7821 if (total_data
< 116) {
7822 return NT_STATUS_INVALID_PARAMETER
;
7825 /* Start by setting all the fields that are common between UNIX_BASIC
7828 status
= smb_set_file_unix_basic(conn
, req
, pdata
, total_data
,
7830 if (!NT_STATUS_IS_OK(status
)) {
7834 smb_fflags
= IVAL(pdata
, 108);
7835 smb_fmask
= IVAL(pdata
, 112);
7837 /* NB: We should only attempt to alter the file flags if the client
7838 * sends a non-zero mask.
7840 if (smb_fmask
!= 0) {
7841 int stat_fflags
= 0;
7843 if (!map_info2_flags_to_sbuf(&smb_fname
->st
, smb_fflags
,
7844 smb_fmask
, &stat_fflags
)) {
7845 /* Client asked to alter a flag we don't understand. */
7846 return NT_STATUS_INVALID_PARAMETER
;
7849 if (fsp
&& fsp
->fh
->fd
!= -1) {
7850 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
7851 return NT_STATUS_NOT_SUPPORTED
;
7853 if (SMB_VFS_CHFLAGS(conn
, smb_fname
->base_name
,
7854 stat_fflags
) != 0) {
7855 return map_nt_error_from_unix(errno
);
7860 /* XXX: need to add support for changing the create_time here. You
7861 * can do this for paths on Darwin with setattrlist(2). The right way
7862 * to hook this up is probably by extending the VFS utimes interface.
7865 return NT_STATUS_OK
;
7868 /****************************************************************************
7869 Create a directory with POSIX semantics.
7870 ****************************************************************************/
7872 static NTSTATUS
smb_posix_mkdir(connection_struct
*conn
,
7873 struct smb_request
*req
,
7876 struct smb_filename
*smb_fname
,
7877 int *pdata_return_size
)
7879 NTSTATUS status
= NT_STATUS_OK
;
7880 uint32_t raw_unixmode
= 0;
7881 uint32_t mod_unixmode
= 0;
7882 mode_t unixmode
= (mode_t
)0;
7883 files_struct
*fsp
= NULL
;
7884 uint16_t info_level_return
= 0;
7886 char *pdata
= *ppdata
;
7888 if (total_data
< 18) {
7889 return NT_STATUS_INVALID_PARAMETER
;
7892 raw_unixmode
= IVAL(pdata
,8);
7893 /* Next 4 bytes are not yet defined. */
7895 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
7896 PERM_NEW_DIR
, &unixmode
);
7897 if (!NT_STATUS_IS_OK(status
)) {
7901 mod_unixmode
= (uint32_t)unixmode
| FILE_FLAG_POSIX_SEMANTICS
;
7903 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
7904 smb_fname_str_dbg(smb_fname
), (unsigned int)unixmode
));
7906 status
= SMB_VFS_CREATE_FILE(
7909 0, /* root_dir_fid */
7910 smb_fname
, /* fname */
7911 FILE_READ_ATTRIBUTES
, /* access_mask */
7912 FILE_SHARE_NONE
, /* share_access */
7913 FILE_CREATE
, /* create_disposition*/
7914 FILE_DIRECTORY_FILE
, /* create_options */
7915 mod_unixmode
, /* file_attributes */
7916 0, /* oplock_request */
7918 0, /* allocation_size */
7919 0, /* private_flags */
7924 NULL
, NULL
); /* create context */
7926 if (NT_STATUS_IS_OK(status
)) {
7927 close_file(req
, fsp
, NORMAL_CLOSE
);
7930 info_level_return
= SVAL(pdata
,16);
7932 if (info_level_return
== SMB_QUERY_FILE_UNIX_BASIC
) {
7933 *pdata_return_size
= 12 + SMB_FILE_UNIX_BASIC_SIZE
;
7934 } else if (info_level_return
== SMB_QUERY_FILE_UNIX_INFO2
) {
7935 *pdata_return_size
= 12 + SMB_FILE_UNIX_INFO2_SIZE
;
7937 *pdata_return_size
= 12;
7940 /* Realloc the data size */
7941 *ppdata
= (char *)SMB_REALLOC(*ppdata
,*pdata_return_size
);
7942 if (*ppdata
== NULL
) {
7943 *pdata_return_size
= 0;
7944 return NT_STATUS_NO_MEMORY
;
7948 SSVAL(pdata
,0,NO_OPLOCK_RETURN
);
7949 SSVAL(pdata
,2,0); /* No fnum. */
7950 SIVAL(pdata
,4,info
); /* Was directory created. */
7952 switch (info_level_return
) {
7953 case SMB_QUERY_FILE_UNIX_BASIC
:
7954 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_BASIC
);
7955 SSVAL(pdata
,10,0); /* Padding. */
7956 store_file_unix_basic(conn
, pdata
+ 12, fsp
,
7959 case SMB_QUERY_FILE_UNIX_INFO2
:
7960 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_INFO2
);
7961 SSVAL(pdata
,10,0); /* Padding. */
7962 store_file_unix_basic_info2(conn
, pdata
+ 12, fsp
,
7966 SSVAL(pdata
,8,SMB_NO_INFO_LEVEL_RETURNED
);
7967 SSVAL(pdata
,10,0); /* Padding. */
7974 /****************************************************************************
7975 Open/Create a file with POSIX semantics.
7976 ****************************************************************************/
7978 #define SMB_O_RDONLY_MAPPING (FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA)
7979 #define SMB_O_WRONLY_MAPPING (FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA)
7981 static NTSTATUS
smb_posix_open(connection_struct
*conn
,
7982 struct smb_request
*req
,
7985 struct smb_filename
*smb_fname
,
7986 int *pdata_return_size
)
7988 bool extended_oplock_granted
= False
;
7989 char *pdata
= *ppdata
;
7991 uint32_t wire_open_mode
= 0;
7992 uint32_t raw_unixmode
= 0;
7993 uint32_t mod_unixmode
= 0;
7994 uint32_t create_disp
= 0;
7995 uint32_t access_mask
= 0;
7996 uint32_t create_options
= FILE_NON_DIRECTORY_FILE
;
7997 NTSTATUS status
= NT_STATUS_OK
;
7998 mode_t unixmode
= (mode_t
)0;
7999 files_struct
*fsp
= NULL
;
8000 int oplock_request
= 0;
8002 uint16_t info_level_return
= 0;
8004 if (total_data
< 18) {
8005 return NT_STATUS_INVALID_PARAMETER
;
8008 flags
= IVAL(pdata
,0);
8009 oplock_request
= (flags
& REQUEST_OPLOCK
) ? EXCLUSIVE_OPLOCK
: 0;
8010 if (oplock_request
) {
8011 oplock_request
|= (flags
& REQUEST_BATCH_OPLOCK
) ? BATCH_OPLOCK
: 0;
8014 wire_open_mode
= IVAL(pdata
,4);
8016 if (wire_open_mode
== (SMB_O_CREAT
|SMB_O_DIRECTORY
)) {
8017 return smb_posix_mkdir(conn
, req
,
8024 switch (wire_open_mode
& SMB_ACCMODE
) {
8026 access_mask
= SMB_O_RDONLY_MAPPING
;
8029 access_mask
= SMB_O_WRONLY_MAPPING
;
8032 access_mask
= (SMB_O_RDONLY_MAPPING
|
8033 SMB_O_WRONLY_MAPPING
);
8036 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
8037 (unsigned int)wire_open_mode
));
8038 return NT_STATUS_INVALID_PARAMETER
;
8041 wire_open_mode
&= ~SMB_ACCMODE
;
8043 /* First take care of O_CREAT|O_EXCL interactions. */
8044 switch (wire_open_mode
& (SMB_O_CREAT
| SMB_O_EXCL
)) {
8045 case (SMB_O_CREAT
| SMB_O_EXCL
):
8046 /* File exists fail. File not exist create. */
8047 create_disp
= FILE_CREATE
;
8050 /* File exists open. File not exist create. */
8051 create_disp
= FILE_OPEN_IF
;
8054 /* O_EXCL on its own without O_CREAT is undefined.
8055 We deliberately ignore it as some versions of
8056 Linux CIFSFS can send a bare O_EXCL on the
8057 wire which other filesystems in the kernel
8058 ignore. See bug 9519 for details. */
8063 /* File exists open. File not exist fail. */
8064 create_disp
= FILE_OPEN
;
8067 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
8068 (unsigned int)wire_open_mode
));
8069 return NT_STATUS_INVALID_PARAMETER
;
8072 /* Next factor in the effects of O_TRUNC. */
8073 wire_open_mode
&= ~(SMB_O_CREAT
| SMB_O_EXCL
);
8075 if (wire_open_mode
& SMB_O_TRUNC
) {
8076 switch (create_disp
) {
8078 /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
8079 /* Leave create_disp alone as
8080 (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
8082 /* File exists fail. File not exist create. */
8085 /* SMB_O_CREAT | SMB_O_TRUNC */
8086 /* File exists overwrite. File not exist create. */
8087 create_disp
= FILE_OVERWRITE_IF
;
8091 /* File exists overwrite. File not exist fail. */
8092 create_disp
= FILE_OVERWRITE
;
8095 /* Cannot get here. */
8096 smb_panic("smb_posix_open: logic error");
8097 return NT_STATUS_INVALID_PARAMETER
;
8101 raw_unixmode
= IVAL(pdata
,8);
8102 /* Next 4 bytes are not yet defined. */
8104 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
8105 (VALID_STAT(smb_fname
->st
) ?
8106 PERM_EXISTING_FILE
: PERM_NEW_FILE
),
8109 if (!NT_STATUS_IS_OK(status
)) {
8113 mod_unixmode
= (uint32_t)unixmode
| FILE_FLAG_POSIX_SEMANTICS
;
8115 if (wire_open_mode
& SMB_O_SYNC
) {
8116 create_options
|= FILE_WRITE_THROUGH
;
8118 if (wire_open_mode
& SMB_O_APPEND
) {
8119 access_mask
|= FILE_APPEND_DATA
;
8121 if (wire_open_mode
& SMB_O_DIRECT
) {
8122 mod_unixmode
|= FILE_FLAG_NO_BUFFERING
;
8125 if ((wire_open_mode
& SMB_O_DIRECTORY
) ||
8126 VALID_STAT_OF_DIR(smb_fname
->st
)) {
8127 if (access_mask
!= SMB_O_RDONLY_MAPPING
) {
8128 return NT_STATUS_FILE_IS_A_DIRECTORY
;
8130 create_options
&= ~FILE_NON_DIRECTORY_FILE
;
8131 create_options
|= FILE_DIRECTORY_FILE
;
8134 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
8135 smb_fname_str_dbg(smb_fname
),
8136 (unsigned int)wire_open_mode
,
8137 (unsigned int)unixmode
));
8139 status
= SMB_VFS_CREATE_FILE(
8142 0, /* root_dir_fid */
8143 smb_fname
, /* fname */
8144 access_mask
, /* access_mask */
8145 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
8147 create_disp
, /* create_disposition*/
8148 create_options
, /* create_options */
8149 mod_unixmode
, /* file_attributes */
8150 oplock_request
, /* oplock_request */
8152 0, /* allocation_size */
8153 0, /* private_flags */
8158 NULL
, NULL
); /* create context */
8160 if (!NT_STATUS_IS_OK(status
)) {
8164 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
8165 extended_oplock_granted
= True
;
8168 if(oplock_request
&& EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
8169 extended_oplock_granted
= True
;
8172 info_level_return
= SVAL(pdata
,16);
8174 /* Allocate the correct return size. */
8176 if (info_level_return
== SMB_QUERY_FILE_UNIX_BASIC
) {
8177 *pdata_return_size
= 12 + SMB_FILE_UNIX_BASIC_SIZE
;
8178 } else if (info_level_return
== SMB_QUERY_FILE_UNIX_INFO2
) {
8179 *pdata_return_size
= 12 + SMB_FILE_UNIX_INFO2_SIZE
;
8181 *pdata_return_size
= 12;
8184 /* Realloc the data size */
8185 *ppdata
= (char *)SMB_REALLOC(*ppdata
,*pdata_return_size
);
8186 if (*ppdata
== NULL
) {
8187 close_file(req
, fsp
, ERROR_CLOSE
);
8188 *pdata_return_size
= 0;
8189 return NT_STATUS_NO_MEMORY
;
8193 if (extended_oplock_granted
) {
8194 if (flags
& REQUEST_BATCH_OPLOCK
) {
8195 SSVAL(pdata
,0, BATCH_OPLOCK_RETURN
);
8197 SSVAL(pdata
,0, EXCLUSIVE_OPLOCK_RETURN
);
8199 } else if (fsp
->oplock_type
== LEVEL_II_OPLOCK
) {
8200 SSVAL(pdata
,0, LEVEL_II_OPLOCK_RETURN
);
8202 SSVAL(pdata
,0,NO_OPLOCK_RETURN
);
8205 SSVAL(pdata
,2,fsp
->fnum
);
8206 SIVAL(pdata
,4,info
); /* Was file created etc. */
8208 switch (info_level_return
) {
8209 case SMB_QUERY_FILE_UNIX_BASIC
:
8210 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_BASIC
);
8211 SSVAL(pdata
,10,0); /* padding. */
8212 store_file_unix_basic(conn
, pdata
+ 12, fsp
,
8215 case SMB_QUERY_FILE_UNIX_INFO2
:
8216 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_INFO2
);
8217 SSVAL(pdata
,10,0); /* padding. */
8218 store_file_unix_basic_info2(conn
, pdata
+ 12, fsp
,
8222 SSVAL(pdata
,8,SMB_NO_INFO_LEVEL_RETURNED
);
8223 SSVAL(pdata
,10,0); /* padding. */
8226 return NT_STATUS_OK
;
8229 /****************************************************************************
8230 Delete a file with POSIX semantics.
8231 ****************************************************************************/
8233 static NTSTATUS
smb_posix_unlink(connection_struct
*conn
,
8234 struct smb_request
*req
,
8237 struct smb_filename
*smb_fname
)
8239 NTSTATUS status
= NT_STATUS_OK
;
8240 files_struct
*fsp
= NULL
;
8244 int create_options
= 0;
8246 struct share_mode_lock
*lck
= NULL
;
8248 if (total_data
< 2) {
8249 return NT_STATUS_INVALID_PARAMETER
;
8252 flags
= SVAL(pdata
,0);
8254 if (!VALID_STAT(smb_fname
->st
)) {
8255 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
8258 if ((flags
== SMB_POSIX_UNLINK_DIRECTORY_TARGET
) &&
8259 !VALID_STAT_OF_DIR(smb_fname
->st
)) {
8260 return NT_STATUS_NOT_A_DIRECTORY
;
8263 DEBUG(10,("smb_posix_unlink: %s %s\n",
8264 (flags
== SMB_POSIX_UNLINK_DIRECTORY_TARGET
) ? "directory" : "file",
8265 smb_fname_str_dbg(smb_fname
)));
8267 if (VALID_STAT_OF_DIR(smb_fname
->st
)) {
8268 create_options
|= FILE_DIRECTORY_FILE
;
8271 status
= SMB_VFS_CREATE_FILE(
8274 0, /* root_dir_fid */
8275 smb_fname
, /* fname */
8276 DELETE_ACCESS
, /* access_mask */
8277 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
8279 FILE_OPEN
, /* create_disposition*/
8280 create_options
, /* create_options */
8281 FILE_FLAG_POSIX_SEMANTICS
|0777, /* file_attributes */
8282 0, /* oplock_request */
8284 0, /* allocation_size */
8285 0, /* private_flags */
8290 NULL
, NULL
); /* create context */
8292 if (!NT_STATUS_IS_OK(status
)) {
8297 * Don't lie to client. If we can't really delete due to
8298 * non-POSIX opens return SHARING_VIOLATION.
8301 lck
= get_existing_share_mode_lock(talloc_tos(), fsp
->file_id
);
8303 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
8304 "lock for file %s\n", fsp_str_dbg(fsp
)));
8305 close_file(req
, fsp
, NORMAL_CLOSE
);
8306 return NT_STATUS_INVALID_PARAMETER
;
8310 * See if others still have the file open. If this is the case, then
8311 * don't delete. If all opens are POSIX delete we can set the delete
8312 * on close disposition.
8314 for (i
=0; i
<lck
->data
->num_share_modes
; i
++) {
8315 struct share_mode_entry
*e
= &lck
->data
->share_modes
[i
];
8316 if (is_valid_share_mode_entry(e
)) {
8317 if (e
->flags
& SHARE_MODE_FLAG_POSIX_OPEN
) {
8320 if (share_mode_stale_pid(lck
->data
, i
)) {
8323 /* Fail with sharing violation. */
8325 close_file(req
, fsp
, NORMAL_CLOSE
);
8326 return NT_STATUS_SHARING_VIOLATION
;
8331 * Set the delete on close.
8333 status
= smb_set_file_disposition_info(conn
,
8341 if (!NT_STATUS_IS_OK(status
)) {
8342 close_file(req
, fsp
, NORMAL_CLOSE
);
8345 return close_file(req
, fsp
, NORMAL_CLOSE
);
8348 NTSTATUS
smbd_do_setfilepathinfo(connection_struct
*conn
,
8349 struct smb_request
*req
,
8350 TALLOC_CTX
*mem_ctx
,
8351 uint16_t info_level
,
8353 struct smb_filename
*smb_fname
,
8354 char **ppdata
, int total_data
,
8357 char *pdata
= *ppdata
;
8358 NTSTATUS status
= NT_STATUS_OK
;
8359 int data_return_size
= 0;
8363 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
8364 return NT_STATUS_INVALID_LEVEL
;
8367 if (!CAN_WRITE(conn
)) {
8368 /* Allow POSIX opens. The open path will deny
8369 * any non-readonly opens. */
8370 if (info_level
!= SMB_POSIX_PATH_OPEN
) {
8371 return NT_STATUS_DOS(ERRSRV
, ERRaccess
);
8375 DEBUG(3,("smbd_do_setfilepathinfo: %s (%s) info_level=%d "
8376 "totdata=%d\n", smb_fname_str_dbg(smb_fname
),
8378 info_level
, total_data
));
8380 switch (info_level
) {
8382 case SMB_INFO_STANDARD
:
8384 status
= smb_set_info_standard(conn
,
8392 case SMB_INFO_SET_EA
:
8394 status
= smb_info_set_ea(conn
,
8402 case SMB_SET_FILE_BASIC_INFO
:
8403 case SMB_FILE_BASIC_INFORMATION
:
8405 status
= smb_set_file_basic_info(conn
,
8413 case SMB_FILE_ALLOCATION_INFORMATION
:
8414 case SMB_SET_FILE_ALLOCATION_INFO
:
8416 status
= smb_set_file_allocation_info(conn
, req
,
8424 case SMB_FILE_END_OF_FILE_INFORMATION
:
8425 case SMB_SET_FILE_END_OF_FILE_INFO
:
8428 * XP/Win7 both fail after the createfile with
8429 * SMB_SET_FILE_END_OF_FILE_INFO but not
8430 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
8431 * The level is known here, so pass it down
8435 (info_level
== SMB_SET_FILE_END_OF_FILE_INFO
);
8437 status
= smb_set_file_end_of_file_info(conn
, req
,
8446 case SMB_FILE_DISPOSITION_INFORMATION
:
8447 case SMB_SET_FILE_DISPOSITION_INFO
: /* Set delete on close for open file. */
8450 /* JRA - We used to just ignore this on a path ?
8451 * Shouldn't this be invalid level on a pathname
8454 if (tran_call
!= TRANSACT2_SETFILEINFO
) {
8455 return ERROR_NT(NT_STATUS_INVALID_LEVEL
);
8458 status
= smb_set_file_disposition_info(conn
,
8466 case SMB_FILE_POSITION_INFORMATION
:
8468 status
= smb_file_position_information(conn
,
8475 case SMB_FILE_FULL_EA_INFORMATION
:
8477 status
= smb_set_file_full_ea_info(conn
,
8484 /* From tridge Samba4 :
8485 * MODE_INFORMATION in setfileinfo (I have no
8486 * idea what "mode information" on a file is - it takes a value of 0,
8487 * 2, 4 or 6. What could it be?).
8490 case SMB_FILE_MODE_INFORMATION
:
8492 status
= smb_file_mode_information(conn
,
8499 * CIFS UNIX extensions.
8502 case SMB_SET_FILE_UNIX_BASIC
:
8504 status
= smb_set_file_unix_basic(conn
, req
,
8512 case SMB_SET_FILE_UNIX_INFO2
:
8514 status
= smb_set_file_unix_info2(conn
, req
,
8522 case SMB_SET_FILE_UNIX_LINK
:
8525 /* We must have a pathname for this. */
8526 return NT_STATUS_INVALID_LEVEL
;
8528 status
= smb_set_file_unix_link(conn
, req
, pdata
,
8529 total_data
, smb_fname
);
8533 case SMB_SET_FILE_UNIX_HLINK
:
8536 /* We must have a pathname for this. */
8537 return NT_STATUS_INVALID_LEVEL
;
8539 status
= smb_set_file_unix_hlink(conn
, req
,
8545 case SMB_FILE_RENAME_INFORMATION
:
8547 status
= smb_file_rename_information(conn
, req
,
8553 case SMB2_FILE_RENAME_INFORMATION_INTERNAL
:
8555 /* SMB2 rename information. */
8556 status
= smb2_file_rename_information(conn
, req
,
8562 case SMB_FILE_LINK_INFORMATION
:
8564 status
= smb_file_link_information(conn
, req
,
8570 #if defined(HAVE_POSIX_ACLS)
8571 case SMB_SET_POSIX_ACL
:
8573 status
= smb_set_posix_acl(conn
,
8582 case SMB_SET_POSIX_LOCK
:
8585 return NT_STATUS_INVALID_LEVEL
;
8587 status
= smb_set_posix_lock(conn
, req
,
8588 pdata
, total_data
, fsp
);
8592 case SMB_POSIX_PATH_OPEN
:
8595 /* We must have a pathname for this. */
8596 return NT_STATUS_INVALID_LEVEL
;
8599 status
= smb_posix_open(conn
, req
,
8607 case SMB_POSIX_PATH_UNLINK
:
8610 /* We must have a pathname for this. */
8611 return NT_STATUS_INVALID_LEVEL
;
8614 status
= smb_posix_unlink(conn
, req
,
8622 return NT_STATUS_INVALID_LEVEL
;
8625 if (!NT_STATUS_IS_OK(status
)) {
8629 *ret_data_size
= data_return_size
;
8630 return NT_STATUS_OK
;
8633 /****************************************************************************
8634 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
8635 ****************************************************************************/
8637 static void call_trans2setfilepathinfo(connection_struct
*conn
,
8638 struct smb_request
*req
,
8639 unsigned int tran_call
,
8640 char **pparams
, int total_params
,
8641 char **ppdata
, int total_data
,
8642 unsigned int max_data_bytes
)
8644 char *params
= *pparams
;
8645 char *pdata
= *ppdata
;
8646 uint16_t info_level
;
8647 struct smb_filename
*smb_fname
= NULL
;
8648 files_struct
*fsp
= NULL
;
8649 NTSTATUS status
= NT_STATUS_OK
;
8650 int data_return_size
= 0;
8653 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8657 if (tran_call
== TRANSACT2_SETFILEINFO
) {
8658 if (total_params
< 4) {
8659 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8663 fsp
= file_fsp(req
, SVAL(params
,0));
8664 /* Basic check for non-null fsp. */
8665 if (!check_fsp_open(conn
, req
, fsp
)) {
8668 info_level
= SVAL(params
,2);
8670 smb_fname
= cp_smb_filename(talloc_tos(), fsp
->fsp_name
);
8671 if (smb_fname
== NULL
) {
8672 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8676 if(fsp
->fh
->fd
== -1) {
8678 * This is actually a SETFILEINFO on a directory
8679 * handle (returned from an NT SMB). NT5.0 seems
8680 * to do this call. JRA.
8682 if (INFO_LEVEL_IS_UNIX(info_level
)) {
8683 /* Always do lstat for UNIX calls. */
8684 if (SMB_VFS_LSTAT(conn
, smb_fname
)) {
8685 DEBUG(3,("call_trans2setfilepathinfo: "
8686 "SMB_VFS_LSTAT of %s failed "
8688 smb_fname_str_dbg(smb_fname
),
8690 reply_nterror(req
, map_nt_error_from_unix(errno
));
8694 if (SMB_VFS_STAT(conn
, smb_fname
) != 0) {
8695 DEBUG(3,("call_trans2setfilepathinfo: "
8696 "fileinfo of %s failed (%s)\n",
8697 smb_fname_str_dbg(smb_fname
),
8699 reply_nterror(req
, map_nt_error_from_unix(errno
));
8703 } else if (fsp
->print_file
) {
8705 * Doing a DELETE_ON_CLOSE should cancel a print job.
8707 if ((info_level
== SMB_SET_FILE_DISPOSITION_INFO
) && CVAL(pdata
,0)) {
8708 fsp
->fh
->private_options
|= NTCREATEX_OPTIONS_PRIVATE_DELETE_ON_CLOSE
;
8710 DEBUG(3,("call_trans2setfilepathinfo: "
8711 "Cancelling print job (%s)\n",
8715 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 2,
8721 NT_STATUS_OBJECT_PATH_NOT_FOUND
);
8726 * Original code - this is an open file.
8728 if (SMB_VFS_FSTAT(fsp
, &smb_fname
->st
) != 0) {
8729 DEBUG(3,("call_trans2setfilepathinfo: fstat "
8730 "of %s failed (%s)\n", fsp_fnum_dbg(fsp
),
8732 reply_nterror(req
, map_nt_error_from_unix(errno
));
8738 uint32_t ucf_flags
= (req
->posix_pathnames
?
8739 UCF_POSIX_PATHNAMES
: 0);
8742 if (total_params
< 7) {
8743 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8747 info_level
= SVAL(params
,0);
8748 if (req
->posix_pathnames
) {
8749 srvstr_get_path_posix(req
,
8758 srvstr_get_path(req
,
8767 if (!NT_STATUS_IS_OK(status
)) {
8768 reply_nterror(req
, status
);
8772 if (info_level
== SMB_SET_FILE_UNIX_BASIC
||
8773 info_level
== SMB_SET_FILE_UNIX_INFO2
||
8774 info_level
== SMB_FILE_RENAME_INFORMATION
||
8775 info_level
== SMB_POSIX_PATH_UNLINK
) {
8776 ucf_flags
|= UCF_UNIX_NAME_LOOKUP
;
8779 status
= filename_convert(req
, conn
,
8780 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
8785 if (!NT_STATUS_IS_OK(status
)) {
8786 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
8787 reply_botherror(req
,
8788 NT_STATUS_PATH_NOT_COVERED
,
8789 ERRSRV
, ERRbadpath
);
8792 reply_nterror(req
, status
);
8796 if (INFO_LEVEL_IS_UNIX(info_level
)) {
8798 * For CIFS UNIX extensions the target name may not exist.
8801 /* Always do lstat for UNIX calls. */
8802 SMB_VFS_LSTAT(conn
, smb_fname
);
8804 } else if (!VALID_STAT(smb_fname
->st
) &&
8805 SMB_VFS_STAT(conn
, smb_fname
)) {
8806 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
8808 smb_fname_str_dbg(smb_fname
),
8810 reply_nterror(req
, map_nt_error_from_unix(errno
));
8815 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (%s) info_level=%d "
8816 "totdata=%d\n", tran_call
, smb_fname_str_dbg(smb_fname
),
8818 info_level
,total_data
));
8820 /* Realloc the parameter size */
8821 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
8822 if (*pparams
== NULL
) {
8823 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8830 status
= smbd_do_setfilepathinfo(conn
, req
, req
,
8836 if (!NT_STATUS_IS_OK(status
)) {
8837 if (open_was_deferred(req
->xconn
, req
->mid
)) {
8838 /* We have re-scheduled this call. */
8841 if (blocking_lock_was_deferred_smb1(req
->sconn
, req
->mid
)) {
8842 /* We have re-scheduled this call. */
8845 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
8846 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
8847 ERRSRV
, ERRbadpath
);
8850 if (info_level
== SMB_POSIX_PATH_OPEN
) {
8851 reply_openerror(req
, status
);
8856 * Invalid EA name needs to return 2 param bytes,
8857 * not a zero-length error packet.
8859 if (NT_STATUS_EQUAL(status
, STATUS_INVALID_EA_NAME
)) {
8860 send_trans2_replies(conn
, req
, status
, params
, 2, NULL
, 0,
8863 reply_nterror(req
, status
);
8868 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 2, *ppdata
, data_return_size
,
8874 /****************************************************************************
8875 Reply to a TRANS2_MKDIR (make directory with extended attributes).
8876 ****************************************************************************/
8878 static void call_trans2mkdir(connection_struct
*conn
, struct smb_request
*req
,
8879 char **pparams
, int total_params
,
8880 char **ppdata
, int total_data
,
8881 unsigned int max_data_bytes
)
8883 struct smb_filename
*smb_dname
= NULL
;
8884 char *params
= *pparams
;
8885 char *pdata
= *ppdata
;
8886 char *directory
= NULL
;
8887 NTSTATUS status
= NT_STATUS_OK
;
8888 struct ea_list
*ea_list
= NULL
;
8889 uint32_t ucf_flags
= (req
->posix_pathnames
? UCF_POSIX_PATHNAMES
: 0);
8890 TALLOC_CTX
*ctx
= talloc_tos();
8892 if (!CAN_WRITE(conn
)) {
8893 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
8897 if (total_params
< 5) {
8898 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8902 if (req
->posix_pathnames
) {
8903 srvstr_get_path_posix(ctx
,
8912 srvstr_get_path(ctx
,
8921 if (!NT_STATUS_IS_OK(status
)) {
8922 reply_nterror(req
, status
);
8926 DEBUG(3,("call_trans2mkdir : name = %s\n", directory
));
8928 status
= filename_convert(ctx
,
8930 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
8936 if (!NT_STATUS_IS_OK(status
)) {
8937 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
8938 reply_botherror(req
,
8939 NT_STATUS_PATH_NOT_COVERED
,
8940 ERRSRV
, ERRbadpath
);
8943 reply_nterror(req
, status
);
8948 * OS/2 workplace shell seems to send SET_EA requests of "null"
8949 * length (4 bytes containing IVAL 4).
8950 * They seem to have no effect. Bug #3212. JRA.
8953 if (total_data
&& (total_data
!= 4)) {
8954 /* Any data in this call is an EA list. */
8955 if (total_data
< 10) {
8956 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8960 if (IVAL(pdata
,0) > total_data
) {
8961 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
8962 IVAL(pdata
,0), (unsigned int)total_data
));
8963 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8967 ea_list
= read_ea_list(talloc_tos(), pdata
+ 4,
8970 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8974 if (!lp_ea_support(SNUM(conn
))) {
8975 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
8979 /* If total_data == 4 Windows doesn't care what values
8980 * are placed in that field, it just ignores them.
8981 * The System i QNTC IBM SMB client puts bad values here,
8982 * so ignore them. */
8984 status
= create_directory(conn
, req
, smb_dname
);
8986 if (!NT_STATUS_IS_OK(status
)) {
8987 reply_nterror(req
, status
);
8991 /* Try and set any given EA. */
8993 status
= set_ea(conn
, NULL
, smb_dname
, ea_list
);
8994 if (!NT_STATUS_IS_OK(status
)) {
8995 reply_nterror(req
, status
);
9000 /* Realloc the parameter and data sizes */
9001 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
9002 if(*pparams
== NULL
) {
9003 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
9010 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 2, *ppdata
, 0, max_data_bytes
);
9013 TALLOC_FREE(smb_dname
);
9017 /****************************************************************************
9018 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
9019 We don't actually do this - we just send a null response.
9020 ****************************************************************************/
9022 static void call_trans2findnotifyfirst(connection_struct
*conn
,
9023 struct smb_request
*req
,
9024 char **pparams
, int total_params
,
9025 char **ppdata
, int total_data
,
9026 unsigned int max_data_bytes
)
9028 char *params
= *pparams
;
9029 uint16_t info_level
;
9031 if (total_params
< 6) {
9032 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
9036 info_level
= SVAL(params
,4);
9037 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level
));
9039 switch (info_level
) {
9044 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
9048 /* Realloc the parameter and data sizes */
9049 *pparams
= (char *)SMB_REALLOC(*pparams
,6);
9050 if (*pparams
== NULL
) {
9051 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
9056 SSVAL(params
,0,fnf_handle
);
9057 SSVAL(params
,2,0); /* No changes */
9058 SSVAL(params
,4,0); /* No EA errors */
9065 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 6, *ppdata
, 0, max_data_bytes
);
9070 /****************************************************************************
9071 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
9072 changes). Currently this does nothing.
9073 ****************************************************************************/
9075 static void call_trans2findnotifynext(connection_struct
*conn
,
9076 struct smb_request
*req
,
9077 char **pparams
, int total_params
,
9078 char **ppdata
, int total_data
,
9079 unsigned int max_data_bytes
)
9081 char *params
= *pparams
;
9083 DEBUG(3,("call_trans2findnotifynext\n"));
9085 /* Realloc the parameter and data sizes */
9086 *pparams
= (char *)SMB_REALLOC(*pparams
,4);
9087 if (*pparams
== NULL
) {
9088 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
9093 SSVAL(params
,0,0); /* No changes */
9094 SSVAL(params
,2,0); /* No EA errors */
9096 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 4, *ppdata
, 0, max_data_bytes
);
9101 /****************************************************************************
9102 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
9103 ****************************************************************************/
9105 static void call_trans2getdfsreferral(connection_struct
*conn
,
9106 struct smb_request
*req
,
9107 char **pparams
, int total_params
,
9108 char **ppdata
, int total_data
,
9109 unsigned int max_data_bytes
)
9111 char *params
= *pparams
;
9112 char *pathname
= NULL
;
9114 int max_referral_level
;
9115 NTSTATUS status
= NT_STATUS_OK
;
9116 TALLOC_CTX
*ctx
= talloc_tos();
9118 DEBUG(10,("call_trans2getdfsreferral\n"));
9120 if (total_params
< 3) {
9121 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
9125 max_referral_level
= SVAL(params
,0);
9127 if(!lp_host_msdfs()) {
9128 reply_nterror(req
, NT_STATUS_NOT_IMPLEMENTED
);
9132 srvstr_pull_talloc(ctx
, params
, req
->flags2
, &pathname
, ¶ms
[2],
9133 total_params
- 2, STR_TERMINATE
);
9135 reply_nterror(req
, NT_STATUS_NOT_FOUND
);
9138 if((reply_size
= setup_dfs_referral(conn
, pathname
, max_referral_level
,
9139 ppdata
,&status
)) < 0) {
9140 reply_nterror(req
, status
);
9144 SSVAL((discard_const_p(uint8_t, req
->inbuf
)), smb_flg2
,
9145 SVAL(req
->inbuf
,smb_flg2
) | FLAGS2_DFS_PATHNAMES
);
9146 send_trans2_replies(conn
, req
, NT_STATUS_OK
, 0,0,*ppdata
,reply_size
, max_data_bytes
);
9151 #define LMCAT_SPL 0x53
9152 #define LMFUNC_GETJOBID 0x60
9154 /****************************************************************************
9155 Reply to a TRANS2_IOCTL - used for OS/2 printing.
9156 ****************************************************************************/
9158 static void call_trans2ioctl(connection_struct
*conn
,
9159 struct smb_request
*req
,
9160 char **pparams
, int total_params
,
9161 char **ppdata
, int total_data
,
9162 unsigned int max_data_bytes
)
9164 char *pdata
= *ppdata
;
9165 files_struct
*fsp
= file_fsp(req
, SVAL(req
->vwv
+15, 0));
9169 /* check for an invalid fid before proceeding */
9172 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
9176 if ((SVAL(req
->vwv
+16, 0) == LMCAT_SPL
)
9177 && (SVAL(req
->vwv
+17, 0) == LMFUNC_GETJOBID
)) {
9178 *ppdata
= (char *)SMB_REALLOC(*ppdata
, 32);
9179 if (*ppdata
== NULL
) {
9180 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
9185 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
9186 CAN ACCEPT THIS IN UNICODE. JRA. */
9189 SSVAL(pdata
, 0, print_spool_rap_jobid(fsp
->print_file
));
9191 status
= srvstr_push(pdata
, req
->flags2
, pdata
+ 2,
9192 lp_netbios_name(), 15,
9193 STR_ASCII
|STR_TERMINATE
, &len
); /* Our NetBIOS name */
9194 if (!NT_STATUS_IS_OK(status
)) {
9195 reply_nterror(req
, status
);
9198 status
= srvstr_push(pdata
, req
->flags2
, pdata
+18,
9199 lp_servicename(talloc_tos(), SNUM(conn
)), 13,
9200 STR_ASCII
|STR_TERMINATE
, &len
); /* Service name */
9201 if (!NT_STATUS_IS_OK(status
)) {
9202 reply_nterror(req
, status
);
9205 send_trans2_replies(conn
, req
, NT_STATUS_OK
, *pparams
, 0, *ppdata
, 32,
9210 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
9211 reply_nterror(req
, NT_STATUS_NOT_IMPLEMENTED
);
9214 /****************************************************************************
9215 Reply to a SMBfindclose (stop trans2 directory search).
9216 ****************************************************************************/
9218 void reply_findclose(struct smb_request
*req
)
9221 struct smbd_server_connection
*sconn
= req
->sconn
;
9223 START_PROFILE(SMBfindclose
);
9226 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
9227 END_PROFILE(SMBfindclose
);
9231 dptr_num
= SVALS(req
->vwv
+0, 0);
9233 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num
));
9235 dptr_close(sconn
, &dptr_num
);
9237 reply_outbuf(req
, 0, 0);
9239 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num
));
9241 END_PROFILE(SMBfindclose
);
9245 /****************************************************************************
9246 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
9247 ****************************************************************************/
9249 void reply_findnclose(struct smb_request
*req
)
9253 START_PROFILE(SMBfindnclose
);
9256 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
9257 END_PROFILE(SMBfindnclose
);
9261 dptr_num
= SVAL(req
->vwv
+0, 0);
9263 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num
));
9265 /* We never give out valid handles for a
9266 findnotifyfirst - so any dptr_num is ok here.
9269 reply_outbuf(req
, 0, 0);
9271 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num
));
9273 END_PROFILE(SMBfindnclose
);
9277 static void handle_trans2(connection_struct
*conn
, struct smb_request
*req
,
9278 struct trans_state
*state
)
9280 if (get_Protocol() >= PROTOCOL_NT1
) {
9281 req
->flags2
|= 0x40; /* IS_LONG_NAME */
9282 SSVAL((discard_const_p(uint8_t, req
->inbuf
)),smb_flg2
,req
->flags2
);
9285 if (ENCRYPTION_REQUIRED(conn
) && !req
->encrypted
) {
9286 if (state
->call
!= TRANSACT2_QFSINFO
&&
9287 state
->call
!= TRANSACT2_SETFSINFO
) {
9288 DEBUG(0,("handle_trans2: encryption required "
9290 (unsigned int)state
->call
));
9291 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
9296 SMB_PERFCOUNT_SET_SUBOP(&req
->pcd
, state
->call
);
9298 /* Now we must call the relevant TRANS2 function */
9299 switch(state
->call
) {
9300 case TRANSACT2_OPEN
:
9302 START_PROFILE(Trans2_open
);
9303 call_trans2open(conn
, req
,
9304 &state
->param
, state
->total_param
,
9305 &state
->data
, state
->total_data
,
9306 state
->max_data_return
);
9307 END_PROFILE(Trans2_open
);
9311 case TRANSACT2_FINDFIRST
:
9313 START_PROFILE(Trans2_findfirst
);
9314 call_trans2findfirst(conn
, req
,
9315 &state
->param
, state
->total_param
,
9316 &state
->data
, state
->total_data
,
9317 state
->max_data_return
);
9318 END_PROFILE(Trans2_findfirst
);
9322 case TRANSACT2_FINDNEXT
:
9324 START_PROFILE(Trans2_findnext
);
9325 call_trans2findnext(conn
, req
,
9326 &state
->param
, state
->total_param
,
9327 &state
->data
, state
->total_data
,
9328 state
->max_data_return
);
9329 END_PROFILE(Trans2_findnext
);
9333 case TRANSACT2_QFSINFO
:
9335 START_PROFILE(Trans2_qfsinfo
);
9336 call_trans2qfsinfo(conn
, req
,
9337 &state
->param
, state
->total_param
,
9338 &state
->data
, state
->total_data
,
9339 state
->max_data_return
);
9340 END_PROFILE(Trans2_qfsinfo
);
9344 case TRANSACT2_SETFSINFO
:
9346 START_PROFILE(Trans2_setfsinfo
);
9347 call_trans2setfsinfo(conn
, req
,
9348 &state
->param
, state
->total_param
,
9349 &state
->data
, state
->total_data
,
9350 state
->max_data_return
);
9351 END_PROFILE(Trans2_setfsinfo
);
9355 case TRANSACT2_QPATHINFO
:
9356 case TRANSACT2_QFILEINFO
:
9358 START_PROFILE(Trans2_qpathinfo
);
9359 call_trans2qfilepathinfo(conn
, req
, state
->call
,
9360 &state
->param
, state
->total_param
,
9361 &state
->data
, state
->total_data
,
9362 state
->max_data_return
);
9363 END_PROFILE(Trans2_qpathinfo
);
9367 case TRANSACT2_SETPATHINFO
:
9368 case TRANSACT2_SETFILEINFO
:
9370 START_PROFILE(Trans2_setpathinfo
);
9371 call_trans2setfilepathinfo(conn
, req
, state
->call
,
9372 &state
->param
, state
->total_param
,
9373 &state
->data
, state
->total_data
,
9374 state
->max_data_return
);
9375 END_PROFILE(Trans2_setpathinfo
);
9379 case TRANSACT2_FINDNOTIFYFIRST
:
9381 START_PROFILE(Trans2_findnotifyfirst
);
9382 call_trans2findnotifyfirst(conn
, req
,
9383 &state
->param
, state
->total_param
,
9384 &state
->data
, state
->total_data
,
9385 state
->max_data_return
);
9386 END_PROFILE(Trans2_findnotifyfirst
);
9390 case TRANSACT2_FINDNOTIFYNEXT
:
9392 START_PROFILE(Trans2_findnotifynext
);
9393 call_trans2findnotifynext(conn
, req
,
9394 &state
->param
, state
->total_param
,
9395 &state
->data
, state
->total_data
,
9396 state
->max_data_return
);
9397 END_PROFILE(Trans2_findnotifynext
);
9401 case TRANSACT2_MKDIR
:
9403 START_PROFILE(Trans2_mkdir
);
9404 call_trans2mkdir(conn
, req
,
9405 &state
->param
, state
->total_param
,
9406 &state
->data
, state
->total_data
,
9407 state
->max_data_return
);
9408 END_PROFILE(Trans2_mkdir
);
9412 case TRANSACT2_GET_DFS_REFERRAL
:
9414 START_PROFILE(Trans2_get_dfs_referral
);
9415 call_trans2getdfsreferral(conn
, req
,
9416 &state
->param
, state
->total_param
,
9417 &state
->data
, state
->total_data
,
9418 state
->max_data_return
);
9419 END_PROFILE(Trans2_get_dfs_referral
);
9423 case TRANSACT2_IOCTL
:
9425 START_PROFILE(Trans2_ioctl
);
9426 call_trans2ioctl(conn
, req
,
9427 &state
->param
, state
->total_param
,
9428 &state
->data
, state
->total_data
,
9429 state
->max_data_return
);
9430 END_PROFILE(Trans2_ioctl
);
9435 /* Error in request */
9436 DEBUG(2,("Unknown request %d in trans2 call\n", state
->call
));
9437 reply_nterror(req
, NT_STATUS_NOT_IMPLEMENTED
);
9441 /****************************************************************************
9442 Reply to a SMBtrans2.
9443 ****************************************************************************/
9445 void reply_trans2(struct smb_request
*req
)
9447 connection_struct
*conn
= req
->conn
;
9452 unsigned int tran_call
;
9453 struct trans_state
*state
;
9456 START_PROFILE(SMBtrans2
);
9458 if (req
->wct
< 14) {
9459 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
9460 END_PROFILE(SMBtrans2
);
9464 dsoff
= SVAL(req
->vwv
+12, 0);
9465 dscnt
= SVAL(req
->vwv
+11, 0);
9466 psoff
= SVAL(req
->vwv
+10, 0);
9467 pscnt
= SVAL(req
->vwv
+9, 0);
9468 tran_call
= SVAL(req
->vwv
+14, 0);
9470 result
= allow_new_trans(conn
->pending_trans
, req
->mid
);
9471 if (!NT_STATUS_IS_OK(result
)) {
9472 DEBUG(2, ("Got invalid trans2 request: %s\n",
9473 nt_errstr(result
)));
9474 reply_nterror(req
, result
);
9475 END_PROFILE(SMBtrans2
);
9480 switch (tran_call
) {
9481 /* List the allowed trans2 calls on IPC$ */
9482 case TRANSACT2_OPEN
:
9483 case TRANSACT2_GET_DFS_REFERRAL
:
9484 case TRANSACT2_QFILEINFO
:
9485 case TRANSACT2_QFSINFO
:
9486 case TRANSACT2_SETFSINFO
:
9489 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
9490 END_PROFILE(SMBtrans2
);
9495 if ((state
= talloc(conn
, struct trans_state
)) == NULL
) {
9496 DEBUG(0, ("talloc failed\n"));
9497 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
9498 END_PROFILE(SMBtrans2
);
9502 state
->cmd
= SMBtrans2
;
9504 state
->mid
= req
->mid
;
9505 state
->vuid
= req
->vuid
;
9506 state
->setup_count
= SVAL(req
->vwv
+13, 0);
9507 state
->setup
= NULL
;
9508 state
->total_param
= SVAL(req
->vwv
+0, 0);
9509 state
->param
= NULL
;
9510 state
->total_data
= SVAL(req
->vwv
+1, 0);
9512 state
->max_param_return
= SVAL(req
->vwv
+2, 0);
9513 state
->max_data_return
= SVAL(req
->vwv
+3, 0);
9514 state
->max_setup_return
= SVAL(req
->vwv
+4, 0);
9515 state
->close_on_completion
= BITSETW(req
->vwv
+5, 0);
9516 state
->one_way
= BITSETW(req
->vwv
+5, 1);
9518 state
->call
= tran_call
;
9520 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
9521 is so as a sanity check */
9522 if (state
->setup_count
!= 1) {
9524 * Need to have rc=0 for ioctl to get job id for OS/2.
9525 * Network printing will fail if function is not successful.
9526 * Similar function in reply.c will be used if protocol
9527 * is LANMAN1.0 instead of LM1.2X002.
9528 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
9529 * outbuf doesn't have to be set(only job id is used).
9531 if ( (state
->setup_count
== 4)
9532 && (tran_call
== TRANSACT2_IOCTL
)
9533 && (SVAL(req
->vwv
+16, 0) == LMCAT_SPL
)
9534 && (SVAL(req
->vwv
+17, 0) == LMFUNC_GETJOBID
)) {
9535 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
9537 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state
->setup_count
));
9538 DEBUG(2,("Transaction is %d\n",tran_call
));
9540 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
9541 END_PROFILE(SMBtrans2
);
9546 if ((dscnt
> state
->total_data
) || (pscnt
> state
->total_param
))
9549 if (state
->total_data
) {
9551 if (trans_oob(state
->total_data
, 0, dscnt
)
9552 || trans_oob(smb_len(req
->inbuf
), dsoff
, dscnt
)) {
9556 /* Can't use talloc here, the core routines do realloc on the
9557 * params and data. */
9558 state
->data
= (char *)SMB_MALLOC(state
->total_data
);
9559 if (state
->data
== NULL
) {
9560 DEBUG(0,("reply_trans2: data malloc fail for %u "
9561 "bytes !\n", (unsigned int)state
->total_data
));
9563 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
9564 END_PROFILE(SMBtrans2
);
9568 memcpy(state
->data
,smb_base(req
->inbuf
)+dsoff
,dscnt
);
9571 if (state
->total_param
) {
9573 if (trans_oob(state
->total_param
, 0, pscnt
)
9574 || trans_oob(smb_len(req
->inbuf
), psoff
, pscnt
)) {
9578 /* Can't use talloc here, the core routines do realloc on the
9579 * params and data. */
9580 state
->param
= (char *)SMB_MALLOC(state
->total_param
);
9581 if (state
->param
== NULL
) {
9582 DEBUG(0,("reply_trans: param malloc fail for %u "
9583 "bytes !\n", (unsigned int)state
->total_param
));
9584 SAFE_FREE(state
->data
);
9586 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
9587 END_PROFILE(SMBtrans2
);
9591 memcpy(state
->param
,smb_base(req
->inbuf
)+psoff
,pscnt
);
9594 state
->received_data
= dscnt
;
9595 state
->received_param
= pscnt
;
9597 if ((state
->received_param
== state
->total_param
) &&
9598 (state
->received_data
== state
->total_data
)) {
9600 handle_trans2(conn
, req
, state
);
9602 SAFE_FREE(state
->data
);
9603 SAFE_FREE(state
->param
);
9605 END_PROFILE(SMBtrans2
);
9609 DLIST_ADD(conn
->pending_trans
, state
);
9611 /* We need to send an interim response then receive the rest
9612 of the parameter/data bytes */
9613 reply_outbuf(req
, 0, 0);
9614 show_msg((char *)req
->outbuf
);
9615 END_PROFILE(SMBtrans2
);
9620 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
9621 SAFE_FREE(state
->data
);
9622 SAFE_FREE(state
->param
);
9624 END_PROFILE(SMBtrans2
);
9625 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
9629 /****************************************************************************
9630 Reply to a SMBtranss2
9631 ****************************************************************************/
9633 void reply_transs2(struct smb_request
*req
)
9635 connection_struct
*conn
= req
->conn
;
9636 unsigned int pcnt
,poff
,dcnt
,doff
,pdisp
,ddisp
;
9637 struct trans_state
*state
;
9639 START_PROFILE(SMBtranss2
);
9641 show_msg((const char *)req
->inbuf
);
9643 /* Windows clients expect all replies to
9644 a transact secondary (SMBtranss2 0x33)
9645 to have a command code of transact
9646 (SMBtrans2 0x32). See bug #8989
9647 and also [MS-CIFS] section 2.2.4.47.2
9650 req
->cmd
= SMBtrans2
;
9653 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
9654 END_PROFILE(SMBtranss2
);
9658 for (state
= conn
->pending_trans
; state
!= NULL
;
9659 state
= state
->next
) {
9660 if (state
->mid
== req
->mid
) {
9665 if ((state
== NULL
) || (state
->cmd
!= SMBtrans2
)) {
9666 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
9667 END_PROFILE(SMBtranss2
);
9671 /* Revise state->total_param and state->total_data in case they have
9672 changed downwards */
9674 if (SVAL(req
->vwv
+0, 0) < state
->total_param
)
9675 state
->total_param
= SVAL(req
->vwv
+0, 0);
9676 if (SVAL(req
->vwv
+1, 0) < state
->total_data
)
9677 state
->total_data
= SVAL(req
->vwv
+1, 0);
9679 pcnt
= SVAL(req
->vwv
+2, 0);
9680 poff
= SVAL(req
->vwv
+3, 0);
9681 pdisp
= SVAL(req
->vwv
+4, 0);
9683 dcnt
= SVAL(req
->vwv
+5, 0);
9684 doff
= SVAL(req
->vwv
+6, 0);
9685 ddisp
= SVAL(req
->vwv
+7, 0);
9687 state
->received_param
+= pcnt
;
9688 state
->received_data
+= dcnt
;
9690 if ((state
->received_data
> state
->total_data
) ||
9691 (state
->received_param
> state
->total_param
))
9695 if (trans_oob(state
->total_param
, pdisp
, pcnt
)
9696 || trans_oob(smb_len(req
->inbuf
), poff
, pcnt
)) {
9699 memcpy(state
->param
+pdisp
,smb_base(req
->inbuf
)+poff
,pcnt
);
9703 if (trans_oob(state
->total_data
, ddisp
, dcnt
)
9704 || trans_oob(smb_len(req
->inbuf
), doff
, dcnt
)) {
9707 memcpy(state
->data
+ddisp
, smb_base(req
->inbuf
)+doff
,dcnt
);
9710 if ((state
->received_param
< state
->total_param
) ||
9711 (state
->received_data
< state
->total_data
)) {
9712 END_PROFILE(SMBtranss2
);
9716 handle_trans2(conn
, req
, state
);
9718 DLIST_REMOVE(conn
->pending_trans
, state
);
9719 SAFE_FREE(state
->data
);
9720 SAFE_FREE(state
->param
);
9723 END_PROFILE(SMBtranss2
);
9728 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
9729 DLIST_REMOVE(conn
->pending_trans
, state
);
9730 SAFE_FREE(state
->data
);
9731 SAFE_FREE(state
->param
);
9733 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
9734 END_PROFILE(SMBtranss2
);