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/>.
27 #include "system/filesys.h"
29 #include "smbd/smbd.h"
30 #include "smbd/globals.h"
31 #include "../libcli/auth/libcli_auth.h"
32 #include "../librpc/gen_ndr/xattr.h"
33 #include "../librpc/gen_ndr/ndr_security.h"
34 #include "../librpc/gen_ndr/open_files.h"
35 #include "libcli/security/security.h"
38 #include "smbprofile.h"
39 #include "rpc_server/srv_pipe_hnd.h"
42 #define DIR_ENTRY_SAFETY_MARGIN 4096
44 static char *store_file_unix_basic(connection_struct
*conn
,
47 const SMB_STRUCT_STAT
*psbuf
);
49 static char *store_file_unix_basic_info2(connection_struct
*conn
,
52 const SMB_STRUCT_STAT
*psbuf
);
54 /********************************************************************
55 The canonical "check access" based on object handle or path function.
56 ********************************************************************/
58 NTSTATUS
check_access(connection_struct
*conn
,
60 const struct smb_filename
*smb_fname
,
64 if (!(fsp
->access_mask
& access_mask
)) {
65 return NT_STATUS_ACCESS_DENIED
;
68 NTSTATUS status
= smbd_check_access_rights(conn
,
72 if (!NT_STATUS_IS_OK(status
)) {
79 /********************************************************************
80 Roundup a value to the nearest allocation roundup size boundary.
81 Only do this for Windows clients.
82 ********************************************************************/
84 uint64_t smb_roundup(connection_struct
*conn
, uint64_t val
)
86 uint64_t rval
= lp_allocation_roundup_size(SNUM(conn
));
88 /* Only roundup for Windows clients. */
89 enum remote_arch_types ra_type
= get_remote_arch();
90 if (rval
&& (ra_type
!= RA_SAMBA
) && (ra_type
!= RA_CIFSFS
)) {
91 val
= SMB_ROUNDUP(val
,rval
);
96 /********************************************************************
97 Create a 64 bit FileIndex. If the file is on the same device as
98 the root of the share, just return the 64-bit inode. If it isn't,
99 mangle as we used to do.
100 ********************************************************************/
102 uint64_t get_FileIndex(connection_struct
*conn
, const SMB_STRUCT_STAT
*psbuf
)
105 if (conn
->base_share_dev
== psbuf
->st_ex_dev
) {
106 return (uint64_t)psbuf
->st_ex_ino
;
108 file_index
= ((psbuf
->st_ex_ino
) & UINT32_MAX
); /* FileIndexLow */
109 file_index
|= ((uint64_t)((psbuf
->st_ex_dev
) & UINT32_MAX
)) << 32; /* FileIndexHigh */
113 /****************************************************************************
114 Utility functions for dealing with extended attributes.
115 ****************************************************************************/
117 /****************************************************************************
118 Refuse to allow clients to overwrite our private xattrs.
119 ****************************************************************************/
121 static bool samba_private_attr_name(const char *unix_ea_name
)
123 static const char * const prohibited_ea_names
[] = {
124 SAMBA_POSIX_INHERITANCE_EA_NAME
,
125 SAMBA_XATTR_DOS_ATTRIB
,
133 for (i
= 0; prohibited_ea_names
[i
]; i
++) {
134 if (strequal( prohibited_ea_names
[i
], unix_ea_name
))
137 if (strncasecmp_m(unix_ea_name
, SAMBA_XATTR_DOSSTREAM_PREFIX
,
138 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX
)) == 0) {
144 /****************************************************************************
145 Get one EA value. Fill in a struct ea_struct.
146 ****************************************************************************/
148 NTSTATUS
get_ea_value(TALLOC_CTX
*mem_ctx
, connection_struct
*conn
,
149 files_struct
*fsp
, const char *fname
,
150 const char *ea_name
, struct ea_struct
*pea
)
152 /* Get the value of this xattr. Max size is 64k. */
153 size_t attr_size
= 256;
159 val
= talloc_realloc(mem_ctx
, val
, char, attr_size
);
161 return NT_STATUS_NO_MEMORY
;
164 if (fsp
&& fsp
->fh
->fd
!= -1) {
165 sizeret
= SMB_VFS_FGETXATTR(fsp
, ea_name
, val
, attr_size
);
167 sizeret
= SMB_VFS_GETXATTR(conn
, fname
, ea_name
, val
, attr_size
);
170 if (sizeret
== -1 && errno
== ERANGE
&& attr_size
!= 65536) {
176 return map_nt_error_from_unix(errno
);
179 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name
, (unsigned int)sizeret
));
180 dump_data(10, (uint8
*)val
, sizeret
);
183 if (strnequal(ea_name
, "user.", 5)) {
184 pea
->name
= talloc_strdup(mem_ctx
, &ea_name
[5]);
186 pea
->name
= talloc_strdup(mem_ctx
, ea_name
);
188 if (pea
->name
== NULL
) {
190 return NT_STATUS_NO_MEMORY
;
192 pea
->value
.data
= (unsigned char *)val
;
193 pea
->value
.length
= (size_t)sizeret
;
197 NTSTATUS
get_ea_names_from_file(TALLOC_CTX
*mem_ctx
, connection_struct
*conn
,
198 files_struct
*fsp
, const char *fname
,
199 char ***pnames
, size_t *pnum_names
)
201 /* Get a list of all xattrs. Max namesize is 64k. */
202 size_t ea_namelist_size
= 1024;
203 char *ea_namelist
= NULL
;
208 ssize_t sizeret
= -1;
210 if (!lp_ea_support(SNUM(conn
))) {
219 * TALLOC the result early to get the talloc hierarchy right.
222 names
= talloc_array(mem_ctx
, char *, 1);
224 DEBUG(0, ("talloc failed\n"));
225 return NT_STATUS_NO_MEMORY
;
228 while (ea_namelist_size
<= 65536) {
230 ea_namelist
= talloc_realloc(
231 names
, ea_namelist
, char, ea_namelist_size
);
232 if (ea_namelist
== NULL
) {
233 DEBUG(0, ("talloc failed\n"));
235 return NT_STATUS_NO_MEMORY
;
238 if (fsp
&& fsp
->fh
->fd
!= -1) {
239 sizeret
= SMB_VFS_FLISTXATTR(fsp
, ea_namelist
,
242 sizeret
= SMB_VFS_LISTXATTR(conn
, fname
, ea_namelist
,
246 if ((sizeret
== -1) && (errno
== ERANGE
)) {
247 ea_namelist_size
*= 2;
256 return map_nt_error_from_unix(errno
);
259 DEBUG(10, ("get_ea_list_from_file: ea_namelist size = %u\n",
260 (unsigned int)sizeret
));
272 * Ensure the result is 0-terminated
275 if (ea_namelist
[sizeret
-1] != '\0') {
277 return NT_STATUS_INTERNAL_ERROR
;
285 for (p
= ea_namelist
; p
- ea_namelist
< sizeret
; p
+= strlen(p
)+1) {
289 tmp
= talloc_realloc(mem_ctx
, names
, char *, num_names
);
291 DEBUG(0, ("talloc failed\n"));
293 return NT_STATUS_NO_MEMORY
;
299 for (p
= ea_namelist
; p
- ea_namelist
< sizeret
; p
+= strlen(p
)+1) {
300 names
[num_names
++] = p
;
308 *pnum_names
= num_names
;
312 /****************************************************************************
313 Return a linked list of the total EA's. Plus the total size
314 ****************************************************************************/
316 static NTSTATUS
get_ea_list_from_file_path(TALLOC_CTX
*mem_ctx
, connection_struct
*conn
, files_struct
*fsp
,
317 const char *fname
, size_t *pea_total_len
, struct ea_list
**ea_list
)
319 /* Get a list of all xattrs. Max namesize is 64k. */
322 struct ea_list
*ea_list_head
= NULL
;
327 status
= get_ea_names_from_file(talloc_tos(), conn
, fsp
, fname
,
330 if (!NT_STATUS_IS_OK(status
)) {
334 if (num_names
== 0) {
339 for (i
=0; i
<num_names
; i
++) {
340 struct ea_list
*listp
;
343 if (strnequal(names
[i
], "system.", 7)
344 || samba_private_attr_name(names
[i
]))
347 listp
= talloc(mem_ctx
, struct ea_list
);
349 return NT_STATUS_NO_MEMORY
;
352 status
= get_ea_value(mem_ctx
, conn
, fsp
,
356 if (!NT_STATUS_IS_OK(status
)) {
360 push_ascii_fstring(dos_ea_name
, listp
->ea
.name
);
363 4 + strlen(dos_ea_name
) + 1 + listp
->ea
.value
.length
;
365 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
366 "= %u\n", (unsigned int)*pea_total_len
, dos_ea_name
,
367 (unsigned int)listp
->ea
.value
.length
));
369 DLIST_ADD_END(ea_list_head
, listp
, struct ea_list
*);
373 /* Add on 4 for total length. */
374 if (*pea_total_len
) {
378 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
379 (unsigned int)*pea_total_len
));
381 *ea_list
= ea_list_head
;
385 static NTSTATUS
get_ea_list_from_file(TALLOC_CTX
*mem_ctx
, connection_struct
*conn
, files_struct
*fsp
,
386 const struct smb_filename
*smb_fname
, size_t *pea_total_len
, struct ea_list
**ea_list
)
391 if (!lp_ea_support(SNUM(conn
))) {
395 if (is_ntfs_stream_smb_fname(smb_fname
)) {
396 return NT_STATUS_INVALID_PARAMETER
;
399 return get_ea_list_from_file_path(mem_ctx
, conn
, fsp
, smb_fname
->base_name
, pea_total_len
, ea_list
);
402 /****************************************************************************
403 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
405 ****************************************************************************/
407 static unsigned int fill_ea_buffer(TALLOC_CTX
*mem_ctx
, char *pdata
, unsigned int total_data_size
,
408 connection_struct
*conn
, struct ea_list
*ea_list
)
410 unsigned int ret_data_size
= 4;
413 SMB_ASSERT(total_data_size
>= 4);
415 if (!lp_ea_support(SNUM(conn
))) {
420 for (p
= pdata
+ 4; ea_list
; ea_list
= ea_list
->next
) {
423 push_ascii_fstring(dos_ea_name
, ea_list
->ea
.name
);
424 dos_namelen
= strlen(dos_ea_name
);
425 if (dos_namelen
> 255 || dos_namelen
== 0) {
428 if (ea_list
->ea
.value
.length
> 65535) {
431 if (4 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
> total_data_size
) {
435 /* We know we have room. */
436 SCVAL(p
,0,ea_list
->ea
.flags
);
437 SCVAL(p
,1,dos_namelen
);
438 SSVAL(p
,2,ea_list
->ea
.value
.length
);
439 strlcpy(p
+4, dos_ea_name
, dos_namelen
+1);
440 memcpy( p
+ 4 + dos_namelen
+ 1, ea_list
->ea
.value
.data
, ea_list
->ea
.value
.length
);
442 total_data_size
-= 4 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
;
443 p
+= 4 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
;
446 ret_data_size
= PTR_DIFF(p
, pdata
);
447 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size
));
448 SIVAL(pdata
,0,ret_data_size
);
449 return ret_data_size
;
452 static NTSTATUS
fill_ea_chained_buffer(TALLOC_CTX
*mem_ctx
,
454 unsigned int total_data_size
,
455 unsigned int *ret_data_size
,
456 connection_struct
*conn
,
457 struct ea_list
*ea_list
)
459 uint8_t *p
= (uint8_t *)pdata
;
460 uint8_t *last_start
= NULL
;
464 if (!lp_ea_support(SNUM(conn
))) {
465 return NT_STATUS_NO_EAS_ON_FILE
;
468 for (; ea_list
; ea_list
= ea_list
->next
) {
474 SIVAL(last_start
, 0, PTR_DIFF(p
, last_start
));
478 push_ascii_fstring(dos_ea_name
, ea_list
->ea
.name
);
479 dos_namelen
= strlen(dos_ea_name
);
480 if (dos_namelen
> 255 || dos_namelen
== 0) {
481 return NT_STATUS_INTERNAL_ERROR
;
483 if (ea_list
->ea
.value
.length
> 65535) {
484 return NT_STATUS_INTERNAL_ERROR
;
487 this_size
= 0x08 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
;
490 size_t pad
= 4 - (this_size
% 4);
494 if (this_size
> total_data_size
) {
495 return NT_STATUS_INFO_LENGTH_MISMATCH
;
498 /* We know we have room. */
499 SIVAL(p
, 0x00, 0); /* next offset */
500 SCVAL(p
, 0x04, ea_list
->ea
.flags
);
501 SCVAL(p
, 0x05, dos_namelen
);
502 SSVAL(p
, 0x06, ea_list
->ea
.value
.length
);
503 strlcpy((char *)(p
+0x08), dos_ea_name
, dos_namelen
+1);
504 memcpy(p
+ 0x08 + dos_namelen
+ 1, ea_list
->ea
.value
.data
, ea_list
->ea
.value
.length
);
506 total_data_size
-= this_size
;
510 *ret_data_size
= PTR_DIFF(p
, pdata
);
511 DEBUG(10,("fill_ea_chained_buffer: data_size = %u\n", *ret_data_size
));
515 static unsigned int estimate_ea_size(connection_struct
*conn
, files_struct
*fsp
, const struct smb_filename
*smb_fname
)
517 size_t total_ea_len
= 0;
519 struct ea_list
*ea_list
;
521 if (!lp_ea_support(SNUM(conn
))) {
524 mem_ctx
= talloc_stackframe();
526 /* If this is a stream fsp, then we need to instead find the
527 * estimated ea len from the main file, not the stream
528 * (streams cannot have EAs), but the estimate isn't just 0 in
530 if (is_ntfs_stream_smb_fname(smb_fname
)) {
533 (void)get_ea_list_from_file_path(mem_ctx
, conn
, fsp
, smb_fname
->base_name
, &total_ea_len
, &ea_list
);
534 TALLOC_FREE(mem_ctx
);
538 /****************************************************************************
539 Ensure the EA name is case insensitive by matching any existing EA name.
540 ****************************************************************************/
542 static void canonicalize_ea_name(connection_struct
*conn
, files_struct
*fsp
, const char *fname
, fstring unix_ea_name
)
545 TALLOC_CTX
*mem_ctx
= talloc_tos();
546 struct ea_list
*ea_list
;
547 NTSTATUS status
= get_ea_list_from_file_path(mem_ctx
, conn
, fsp
, fname
, &total_ea_len
, &ea_list
);
548 if (!NT_STATUS_IS_OK(status
)) {
552 for (; ea_list
; ea_list
= ea_list
->next
) {
553 if (strequal(&unix_ea_name
[5], ea_list
->ea
.name
)) {
554 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
555 &unix_ea_name
[5], ea_list
->ea
.name
));
556 strlcpy(&unix_ea_name
[5], ea_list
->ea
.name
, sizeof(fstring
)-5);
562 /****************************************************************************
563 Set or delete an extended attribute.
564 ****************************************************************************/
566 NTSTATUS
set_ea(connection_struct
*conn
, files_struct
*fsp
,
567 const struct smb_filename
*smb_fname
, struct ea_list
*ea_list
)
572 if (!lp_ea_support(SNUM(conn
))) {
573 return NT_STATUS_EAS_NOT_SUPPORTED
;
576 status
= check_access(conn
, fsp
, smb_fname
, FILE_WRITE_EA
);
577 if (!NT_STATUS_IS_OK(status
)) {
581 /* Setting EAs on streams isn't supported. */
582 if (is_ntfs_stream_smb_fname(smb_fname
)) {
583 return NT_STATUS_INVALID_PARAMETER
;
586 fname
= smb_fname
->base_name
;
588 for (;ea_list
; ea_list
= ea_list
->next
) {
590 fstring unix_ea_name
;
592 fstrcpy(unix_ea_name
, "user."); /* All EA's must start with user. */
593 fstrcat(unix_ea_name
, ea_list
->ea
.name
);
595 canonicalize_ea_name(conn
, fsp
, fname
, unix_ea_name
);
597 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name
, (unsigned int)ea_list
->ea
.value
.length
));
599 if (samba_private_attr_name(unix_ea_name
)) {
600 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name
));
601 return NT_STATUS_ACCESS_DENIED
;
604 if (ea_list
->ea
.value
.length
== 0) {
605 /* Remove the attribute. */
606 if (fsp
&& (fsp
->fh
->fd
!= -1)) {
607 DEBUG(10,("set_ea: deleting ea name %s on "
608 "file %s by file descriptor.\n",
609 unix_ea_name
, fsp_str_dbg(fsp
)));
610 ret
= SMB_VFS_FREMOVEXATTR(fsp
, unix_ea_name
);
612 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
613 unix_ea_name
, fname
));
614 ret
= SMB_VFS_REMOVEXATTR(conn
, fname
, unix_ea_name
);
617 /* Removing a non existent attribute always succeeds. */
618 if (ret
== -1 && errno
== ENOATTR
) {
619 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
625 if (fsp
&& (fsp
->fh
->fd
!= -1)) {
626 DEBUG(10,("set_ea: setting ea name %s on file "
627 "%s by file descriptor.\n",
628 unix_ea_name
, fsp_str_dbg(fsp
)));
629 ret
= SMB_VFS_FSETXATTR(fsp
, unix_ea_name
,
630 ea_list
->ea
.value
.data
, ea_list
->ea
.value
.length
, 0);
632 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
633 unix_ea_name
, fname
));
634 ret
= SMB_VFS_SETXATTR(conn
, fname
, unix_ea_name
,
635 ea_list
->ea
.value
.data
, ea_list
->ea
.value
.length
, 0);
641 if (errno
== ENOTSUP
) {
642 return NT_STATUS_EAS_NOT_SUPPORTED
;
645 return map_nt_error_from_unix(errno
);
651 /****************************************************************************
652 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
653 ****************************************************************************/
655 static struct ea_list
*read_ea_name_list(TALLOC_CTX
*ctx
, const char *pdata
, size_t data_size
)
657 struct ea_list
*ea_list_head
= NULL
;
658 size_t converted_size
, offset
= 0;
660 while (offset
+ 2 < data_size
) {
661 struct ea_list
*eal
= talloc_zero(ctx
, struct ea_list
);
662 unsigned int namelen
= CVAL(pdata
,offset
);
664 offset
++; /* Go past the namelen byte. */
666 /* integer wrap paranioa. */
667 if ((offset
+ namelen
< offset
) || (offset
+ namelen
< namelen
) ||
668 (offset
> data_size
) || (namelen
> data_size
) ||
669 (offset
+ namelen
>= data_size
)) {
672 /* Ensure the name is null terminated. */
673 if (pdata
[offset
+ namelen
] != '\0') {
676 if (!pull_ascii_talloc(ctx
, &eal
->ea
.name
, &pdata
[offset
],
678 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
679 "failed: %s", strerror(errno
)));
685 offset
+= (namelen
+ 1); /* Go past the name + terminating zero. */
686 DLIST_ADD_END(ea_list_head
, eal
, struct ea_list
*);
687 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal
->ea
.name
));
693 /****************************************************************************
694 Read one EA list entry from the buffer.
695 ****************************************************************************/
697 struct ea_list
*read_ea_list_entry(TALLOC_CTX
*ctx
, const char *pdata
, size_t data_size
, size_t *pbytes_used
)
699 struct ea_list
*eal
= talloc_zero(ctx
, struct ea_list
);
701 unsigned int namelen
;
702 size_t converted_size
;
712 eal
->ea
.flags
= CVAL(pdata
,0);
713 namelen
= CVAL(pdata
,1);
714 val_len
= SVAL(pdata
,2);
716 if (4 + namelen
+ 1 + val_len
> data_size
) {
720 /* Ensure the name is null terminated. */
721 if (pdata
[namelen
+ 4] != '\0') {
724 if (!pull_ascii_talloc(ctx
, &eal
->ea
.name
, pdata
+ 4, &converted_size
)) {
725 DEBUG(0,("read_ea_list_entry: pull_ascii_talloc failed: %s",
732 eal
->ea
.value
= data_blob_talloc(eal
, NULL
, (size_t)val_len
+ 1);
733 if (!eal
->ea
.value
.data
) {
737 memcpy(eal
->ea
.value
.data
, pdata
+ 4 + namelen
+ 1, val_len
);
739 /* Ensure we're null terminated just in case we print the value. */
740 eal
->ea
.value
.data
[val_len
] = '\0';
741 /* But don't count the null. */
742 eal
->ea
.value
.length
--;
745 *pbytes_used
= 4 + namelen
+ 1 + val_len
;
748 DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal
->ea
.name
));
749 dump_data(10, eal
->ea
.value
.data
, eal
->ea
.value
.length
);
754 /****************************************************************************
755 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
756 ****************************************************************************/
758 static struct ea_list
*read_ea_list(TALLOC_CTX
*ctx
, const char *pdata
, size_t data_size
)
760 struct ea_list
*ea_list_head
= NULL
;
762 size_t bytes_used
= 0;
764 while (offset
< data_size
) {
765 struct ea_list
*eal
= read_ea_list_entry(ctx
, pdata
+ offset
, data_size
- offset
, &bytes_used
);
771 DLIST_ADD_END(ea_list_head
, eal
, struct ea_list
*);
772 offset
+= bytes_used
;
778 /****************************************************************************
779 Count the total EA size needed.
780 ****************************************************************************/
782 static size_t ea_list_size(struct ea_list
*ealist
)
785 struct ea_list
*listp
;
788 for (listp
= ealist
; listp
; listp
= listp
->next
) {
789 push_ascii_fstring(dos_ea_name
, listp
->ea
.name
);
790 ret
+= 4 + strlen(dos_ea_name
) + 1 + listp
->ea
.value
.length
;
792 /* Add on 4 for total length. */
800 /****************************************************************************
801 Return a union of EA's from a file list and a list of names.
802 The TALLOC context for the two lists *MUST* be identical as we steal
803 memory from one list to add to another. JRA.
804 ****************************************************************************/
806 static struct ea_list
*ea_list_union(struct ea_list
*name_list
, struct ea_list
*file_list
, size_t *total_ea_len
)
808 struct ea_list
*nlistp
, *flistp
;
810 for (nlistp
= name_list
; nlistp
; nlistp
= nlistp
->next
) {
811 for (flistp
= file_list
; flistp
; flistp
= flistp
->next
) {
812 if (strequal(nlistp
->ea
.name
, flistp
->ea
.name
)) {
818 /* Copy the data from this entry. */
819 nlistp
->ea
.flags
= flistp
->ea
.flags
;
820 nlistp
->ea
.value
= flistp
->ea
.value
;
823 nlistp
->ea
.flags
= 0;
824 ZERO_STRUCT(nlistp
->ea
.value
);
828 *total_ea_len
= ea_list_size(name_list
);
832 /****************************************************************************
833 Send the required number of replies back.
834 We assume all fields other than the data fields are
835 set correctly for the type of call.
836 HACK ! Always assumes smb_setup field is zero.
837 ****************************************************************************/
839 void send_trans2_replies(connection_struct
*conn
,
840 struct smb_request
*req
,
847 /* As we are using a protocol > LANMAN1 then the max_send
848 variable must have been set in the sessetupX call.
849 This takes precedence over the max_xmit field in the
850 global struct. These different max_xmit variables should
851 be merged as this is now too confusing */
853 int data_to_send
= datasize
;
854 int params_to_send
= paramsize
;
856 const char *pp
= params
;
857 const char *pd
= pdata
;
858 int params_sent_thistime
, data_sent_thistime
, total_sent_thistime
;
859 int alignment_offset
= 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
860 int data_alignment_offset
= 0;
861 bool overflow
= False
;
862 struct smbd_server_connection
*sconn
= req
->sconn
;
863 int max_send
= sconn
->smb1
.sessions
.max_send
;
865 /* Modify the data_to_send and datasize and set the error if
866 we're trying to send more than max_data_bytes. We still send
867 the part of the packet(s) that fit. Strange, but needed
870 if (max_data_bytes
> 0 && datasize
> max_data_bytes
) {
871 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
872 max_data_bytes
, datasize
));
873 datasize
= data_to_send
= max_data_bytes
;
877 /* If there genuinely are no parameters or data to send just send the empty packet */
879 if(params_to_send
== 0 && data_to_send
== 0) {
880 reply_outbuf(req
, 10, 0);
881 show_msg((char *)req
->outbuf
);
882 if (!srv_send_smb(sconn
,
885 IS_CONN_ENCRYPTED(conn
),
887 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
889 TALLOC_FREE(req
->outbuf
);
893 /* When sending params and data ensure that both are nicely aligned */
894 /* Only do this alignment when there is also data to send - else
895 can cause NT redirector problems. */
897 if (((params_to_send
% 4) != 0) && (data_to_send
!= 0))
898 data_alignment_offset
= 4 - (params_to_send
% 4);
900 /* Space is bufsize minus Netbios over TCP header minus SMB header */
901 /* The alignment_offset is to align the param bytes on an even byte
902 boundary. NT 4.0 Beta needs this to work correctly. */
904 useable_space
= max_send
- (smb_size
907 + data_alignment_offset
);
909 if (useable_space
< 0) {
910 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
911 "= %d!!!", useable_space
));
912 exit_server_cleanly("send_trans2_replies: Not enough space");
915 while (params_to_send
|| data_to_send
) {
916 /* Calculate whether we will totally or partially fill this packet */
918 total_sent_thistime
= params_to_send
+ data_to_send
;
920 /* We can never send more than useable_space */
922 * Note that 'useable_space' does not include the alignment offsets,
923 * but we must include the alignment offsets in the calculation of
924 * the length of the data we send over the wire, as the alignment offsets
925 * are sent here. Fix from Marc_Jacobsen@hp.com.
928 total_sent_thistime
= MIN(total_sent_thistime
, useable_space
);
930 reply_outbuf(req
, 10, total_sent_thistime
+ alignment_offset
931 + data_alignment_offset
);
933 /* Set total params and data to be sent */
934 SSVAL(req
->outbuf
,smb_tprcnt
,paramsize
);
935 SSVAL(req
->outbuf
,smb_tdrcnt
,datasize
);
937 /* Calculate how many parameters and data we can fit into
938 * this packet. Parameters get precedence
941 params_sent_thistime
= MIN(params_to_send
,useable_space
);
942 data_sent_thistime
= useable_space
- params_sent_thistime
;
943 data_sent_thistime
= MIN(data_sent_thistime
,data_to_send
);
945 SSVAL(req
->outbuf
,smb_prcnt
, params_sent_thistime
);
947 /* smb_proff is the offset from the start of the SMB header to the
948 parameter bytes, however the first 4 bytes of outbuf are
949 the Netbios over TCP header. Thus use smb_base() to subtract
950 them from the calculation */
952 SSVAL(req
->outbuf
,smb_proff
,
953 ((smb_buf(req
->outbuf
)+alignment_offset
)
954 - smb_base(req
->outbuf
)));
956 if(params_sent_thistime
== 0)
957 SSVAL(req
->outbuf
,smb_prdisp
,0);
959 /* Absolute displacement of param bytes sent in this packet */
960 SSVAL(req
->outbuf
,smb_prdisp
,pp
- params
);
962 SSVAL(req
->outbuf
,smb_drcnt
, data_sent_thistime
);
963 if(data_sent_thistime
== 0) {
964 SSVAL(req
->outbuf
,smb_droff
,0);
965 SSVAL(req
->outbuf
,smb_drdisp
, 0);
967 /* The offset of the data bytes is the offset of the
968 parameter bytes plus the number of parameters being sent this time */
969 SSVAL(req
->outbuf
, smb_droff
,
970 ((smb_buf(req
->outbuf
)+alignment_offset
)
971 - smb_base(req
->outbuf
))
972 + params_sent_thistime
+ data_alignment_offset
);
973 SSVAL(req
->outbuf
,smb_drdisp
, pd
- pdata
);
976 /* Initialize the padding for alignment */
978 if (alignment_offset
!= 0) {
979 memset(smb_buf(req
->outbuf
), 0, alignment_offset
);
982 /* Copy the param bytes into the packet */
984 if(params_sent_thistime
) {
985 memcpy((smb_buf(req
->outbuf
)+alignment_offset
), pp
,
986 params_sent_thistime
);
989 /* Copy in the data bytes */
990 if(data_sent_thistime
) {
991 if (data_alignment_offset
!= 0) {
992 memset((smb_buf(req
->outbuf
)+alignment_offset
+
993 params_sent_thistime
), 0,
994 data_alignment_offset
);
996 memcpy(smb_buf(req
->outbuf
)+alignment_offset
997 +params_sent_thistime
+data_alignment_offset
,
998 pd
,data_sent_thistime
);
1001 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
1002 params_sent_thistime
, data_sent_thistime
, useable_space
));
1003 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
1004 params_to_send
, data_to_send
, paramsize
, datasize
));
1007 error_packet_set((char *)req
->outbuf
,
1008 ERRDOS
,ERRbufferoverflow
,
1009 STATUS_BUFFER_OVERFLOW
,
1013 /* Send the packet */
1014 show_msg((char *)req
->outbuf
);
1015 if (!srv_send_smb(sconn
,
1016 (char *)req
->outbuf
,
1017 true, req
->seqnum
+1,
1018 IS_CONN_ENCRYPTED(conn
),
1020 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
1022 TALLOC_FREE(req
->outbuf
);
1024 pp
+= params_sent_thistime
;
1025 pd
+= data_sent_thistime
;
1027 params_to_send
-= params_sent_thistime
;
1028 data_to_send
-= data_sent_thistime
;
1031 if(params_to_send
< 0 || data_to_send
< 0) {
1032 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
1033 params_to_send
, data_to_send
));
1041 /****************************************************************************
1042 Reply to a TRANSACT2_OPEN.
1043 ****************************************************************************/
1045 static void call_trans2open(connection_struct
*conn
,
1046 struct smb_request
*req
,
1047 char **pparams
, int total_params
,
1048 char **ppdata
, int total_data
,
1049 unsigned int max_data_bytes
)
1051 struct smb_filename
*smb_fname
= NULL
;
1052 char *params
= *pparams
;
1053 char *pdata
= *ppdata
;
1056 bool oplock_request
;
1058 bool return_additional_info
;
1067 int fattr
=0,mtime
=0;
1068 SMB_INO_T inode
= 0;
1071 struct ea_list
*ea_list
= NULL
;
1076 uint32 create_disposition
;
1077 uint32 create_options
= 0;
1078 uint32_t private_flags
= 0;
1079 TALLOC_CTX
*ctx
= talloc_tos();
1082 * Ensure we have enough parameters to perform the operation.
1085 if (total_params
< 29) {
1086 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1090 flags
= SVAL(params
, 0);
1091 deny_mode
= SVAL(params
, 2);
1092 open_attr
= SVAL(params
,6);
1093 oplock_request
= (flags
& REQUEST_OPLOCK
) ? EXCLUSIVE_OPLOCK
: 0;
1094 if (oplock_request
) {
1095 oplock_request
|= (flags
& REQUEST_BATCH_OPLOCK
) ? BATCH_OPLOCK
: 0;
1099 return_additional_info
= BITSETW(params
,0);
1100 open_sattr
= SVAL(params
, 4);
1101 open_time
= make_unix_date3(params
+8);
1103 open_ofun
= SVAL(params
,12);
1104 open_size
= IVAL(params
,14);
1105 pname
= ¶ms
[28];
1108 reply_nterror(req
, NT_STATUS_NETWORK_ACCESS_DENIED
);
1112 srvstr_get_path(ctx
, params
, req
->flags2
, &fname
, pname
,
1113 total_params
- 28, STR_TERMINATE
,
1115 if (!NT_STATUS_IS_OK(status
)) {
1116 reply_nterror(req
, status
);
1120 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
1121 fname
, (unsigned int)deny_mode
, (unsigned int)open_attr
,
1122 (unsigned int)open_ofun
, open_size
));
1124 status
= filename_convert(ctx
,
1126 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
1131 if (!NT_STATUS_IS_OK(status
)) {
1132 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
1133 reply_botherror(req
,
1134 NT_STATUS_PATH_NOT_COVERED
,
1135 ERRSRV
, ERRbadpath
);
1138 reply_nterror(req
, status
);
1142 if (open_ofun
== 0) {
1143 reply_nterror(req
, NT_STATUS_OBJECT_NAME_COLLISION
);
1147 if (!map_open_params_to_ntcreate(smb_fname
->base_name
, deny_mode
,
1149 &access_mask
, &share_mode
,
1150 &create_disposition
,
1153 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
1157 /* Any data in this call is an EA list. */
1158 if (total_data
&& (total_data
!= 4)) {
1159 if (total_data
< 10) {
1160 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1164 if (IVAL(pdata
,0) > total_data
) {
1165 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
1166 IVAL(pdata
,0), (unsigned int)total_data
));
1167 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1171 ea_list
= read_ea_list(talloc_tos(), pdata
+ 4,
1174 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1178 if (!lp_ea_support(SNUM(conn
))) {
1179 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
1184 status
= SMB_VFS_CREATE_FILE(
1187 0, /* root_dir_fid */
1188 smb_fname
, /* fname */
1189 access_mask
, /* access_mask */
1190 share_mode
, /* share_access */
1191 create_disposition
, /* create_disposition*/
1192 create_options
, /* create_options */
1193 open_attr
, /* file_attributes */
1194 oplock_request
, /* oplock_request */
1195 open_size
, /* allocation_size */
1198 ea_list
, /* ea_list */
1200 &smb_action
); /* psbuf */
1202 if (!NT_STATUS_IS_OK(status
)) {
1203 if (open_was_deferred(req
->sconn
, req
->mid
)) {
1204 /* We have re-scheduled this call. */
1207 reply_openerror(req
, status
);
1211 size
= get_file_size_stat(&smb_fname
->st
);
1212 fattr
= dos_mode(conn
, smb_fname
);
1213 mtime
= convert_timespec_to_time_t(smb_fname
->st
.st_ex_mtime
);
1214 inode
= smb_fname
->st
.st_ex_ino
;
1215 if (fattr
& FILE_ATTRIBUTE_DIRECTORY
) {
1216 close_file(req
, fsp
, ERROR_CLOSE
);
1217 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
1221 /* Realloc the size of parameters and data we will return */
1222 *pparams
= (char *)SMB_REALLOC(*pparams
, 30);
1223 if(*pparams
== NULL
) {
1224 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1229 SSVAL(params
,0,fsp
->fnum
);
1230 SSVAL(params
,2,fattr
);
1231 srv_put_dos_date2(params
,4, mtime
);
1232 SIVAL(params
,8, (uint32
)size
);
1233 SSVAL(params
,12,deny_mode
);
1234 SSVAL(params
,14,0); /* open_type - file or directory. */
1235 SSVAL(params
,16,0); /* open_state - only valid for IPC device. */
1237 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
1238 smb_action
|= EXTENDED_OPLOCK_GRANTED
;
1241 SSVAL(params
,18,smb_action
);
1244 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1246 SIVAL(params
,20,inode
);
1247 SSVAL(params
,24,0); /* Padding. */
1249 uint32 ea_size
= estimate_ea_size(conn
, fsp
,
1251 SIVAL(params
, 26, ea_size
);
1253 SIVAL(params
, 26, 0);
1256 /* Send the required number of replies */
1257 send_trans2_replies(conn
, req
, params
, 30, *ppdata
, 0, max_data_bytes
);
1259 TALLOC_FREE(smb_fname
);
1262 /*********************************************************
1263 Routine to check if a given string matches exactly.
1264 as a special case a mask of "." does NOT match. That
1265 is required for correct wildcard semantics
1266 Case can be significant or not.
1267 **********************************************************/
1269 static bool exact_match(bool has_wild
,
1270 bool case_sensitive
,
1274 if (mask
[0] == '.' && mask
[1] == 0) {
1282 if (case_sensitive
) {
1283 return strcmp(str
,mask
)==0;
1285 return strcasecmp_m(str
,mask
) == 0;
1289 /****************************************************************************
1290 Return the filetype for UNIX extensions.
1291 ****************************************************************************/
1293 static uint32
unix_filetype(mode_t mode
)
1296 return UNIX_TYPE_FILE
;
1297 else if(S_ISDIR(mode
))
1298 return UNIX_TYPE_DIR
;
1300 else if(S_ISLNK(mode
))
1301 return UNIX_TYPE_SYMLINK
;
1304 else if(S_ISCHR(mode
))
1305 return UNIX_TYPE_CHARDEV
;
1308 else if(S_ISBLK(mode
))
1309 return UNIX_TYPE_BLKDEV
;
1312 else if(S_ISFIFO(mode
))
1313 return UNIX_TYPE_FIFO
;
1316 else if(S_ISSOCK(mode
))
1317 return UNIX_TYPE_SOCKET
;
1320 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode
));
1321 return UNIX_TYPE_UNKNOWN
;
1324 /****************************************************************************
1325 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1326 ****************************************************************************/
1328 enum perm_type
{ PERM_NEW_FILE
, PERM_NEW_DIR
, PERM_EXISTING_FILE
, PERM_EXISTING_DIR
};
1330 static NTSTATUS
unix_perms_from_wire( connection_struct
*conn
,
1331 const SMB_STRUCT_STAT
*psbuf
,
1333 enum perm_type ptype
,
1338 if (perms
== SMB_MODE_NO_CHANGE
) {
1339 if (!VALID_STAT(*psbuf
)) {
1340 return NT_STATUS_INVALID_PARAMETER
;
1342 *ret_perms
= psbuf
->st_ex_mode
;
1343 return NT_STATUS_OK
;
1347 ret
|= ((perms
& UNIX_X_OTH
) ? S_IXOTH
: 0);
1348 ret
|= ((perms
& UNIX_W_OTH
) ? S_IWOTH
: 0);
1349 ret
|= ((perms
& UNIX_R_OTH
) ? S_IROTH
: 0);
1350 ret
|= ((perms
& UNIX_X_GRP
) ? S_IXGRP
: 0);
1351 ret
|= ((perms
& UNIX_W_GRP
) ? S_IWGRP
: 0);
1352 ret
|= ((perms
& UNIX_R_GRP
) ? S_IRGRP
: 0);
1353 ret
|= ((perms
& UNIX_X_USR
) ? S_IXUSR
: 0);
1354 ret
|= ((perms
& UNIX_W_USR
) ? S_IWUSR
: 0);
1355 ret
|= ((perms
& UNIX_R_USR
) ? S_IRUSR
: 0);
1357 ret
|= ((perms
& UNIX_STICKY
) ? S_ISVTX
: 0);
1360 ret
|= ((perms
& UNIX_SET_GID
) ? S_ISGID
: 0);
1363 ret
|= ((perms
& UNIX_SET_UID
) ? S_ISUID
: 0);
1368 case PERM_EXISTING_FILE
:
1369 /* Apply mode mask */
1370 ret
&= lp_create_mask(SNUM(conn
));
1371 /* Add in force bits */
1372 ret
|= lp_force_create_mode(SNUM(conn
));
1375 case PERM_EXISTING_DIR
:
1376 ret
&= lp_dir_mask(SNUM(conn
));
1377 /* Add in force bits */
1378 ret
|= lp_force_dir_mode(SNUM(conn
));
1383 return NT_STATUS_OK
;
1386 /****************************************************************************
1387 Needed to show the msdfs symlinks as directories. Modifies psbuf
1388 to be a directory if it's a msdfs link.
1389 ****************************************************************************/
1391 static bool check_msdfs_link(connection_struct
*conn
,
1392 const char *pathname
,
1393 SMB_STRUCT_STAT
*psbuf
)
1395 int saved_errno
= errno
;
1396 if(lp_host_msdfs() &&
1397 lp_msdfs_root(SNUM(conn
)) &&
1398 is_msdfs_link(conn
, pathname
, psbuf
)) {
1400 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1403 psbuf
->st_ex_mode
= (psbuf
->st_ex_mode
& 0xFFF) | S_IFDIR
;
1404 errno
= saved_errno
;
1407 errno
= saved_errno
;
1412 /****************************************************************************
1413 Get a level dependent lanman2 dir entry.
1414 ****************************************************************************/
1416 struct smbd_dirptr_lanman2_state
{
1417 connection_struct
*conn
;
1418 uint32_t info_level
;
1419 bool check_mangled_names
;
1421 bool got_exact_match
;
1424 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX
*ctx
,
1430 struct smbd_dirptr_lanman2_state
*state
=
1431 (struct smbd_dirptr_lanman2_state
*)private_data
;
1433 char mangled_name
[13]; /* mangled 8.3 name. */
1437 /* Mangle fname if it's an illegal name. */
1438 if (mangle_must_mangle(dname
, state
->conn
->params
)) {
1439 ok
= name_to_8_3(dname
, mangled_name
,
1440 true, state
->conn
->params
);
1444 fname
= mangled_name
;
1449 got_match
= exact_match(state
->has_wild
,
1450 state
->conn
->case_sensitive
,
1452 state
->got_exact_match
= got_match
;
1454 got_match
= mask_match(fname
, mask
,
1455 state
->conn
->case_sensitive
);
1458 if(!got_match
&& state
->check_mangled_names
&&
1459 !mangle_is_8_3(fname
, false, state
->conn
->params
)) {
1461 * It turns out that NT matches wildcards against
1462 * both long *and* short names. This may explain some
1463 * of the wildcard wierdness from old DOS clients
1464 * that some people have been seeing.... JRA.
1466 /* Force the mangling into 8.3. */
1467 ok
= name_to_8_3(fname
, mangled_name
,
1468 false, state
->conn
->params
);
1473 got_match
= exact_match(state
->has_wild
,
1474 state
->conn
->case_sensitive
,
1475 mangled_name
, mask
);
1476 state
->got_exact_match
= got_match
;
1478 got_match
= mask_match(mangled_name
, mask
,
1479 state
->conn
->case_sensitive
);
1487 *_fname
= talloc_strdup(ctx
, fname
);
1488 if (*_fname
== NULL
) {
1495 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX
*ctx
,
1497 struct smb_filename
*smb_fname
,
1500 struct smbd_dirptr_lanman2_state
*state
=
1501 (struct smbd_dirptr_lanman2_state
*)private_data
;
1502 bool ms_dfs_link
= false;
1505 if (INFO_LEVEL_IS_UNIX(state
->info_level
)) {
1506 if (SMB_VFS_LSTAT(state
->conn
, smb_fname
) != 0) {
1507 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1508 "Couldn't lstat [%s] (%s)\n",
1509 smb_fname_str_dbg(smb_fname
),
1513 } else if (!VALID_STAT(smb_fname
->st
) &&
1514 SMB_VFS_STAT(state
->conn
, smb_fname
) != 0) {
1515 /* Needed to show the msdfs symlinks as
1518 ms_dfs_link
= check_msdfs_link(state
->conn
,
1519 smb_fname
->base_name
,
1522 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1523 "Couldn't stat [%s] (%s)\n",
1524 smb_fname_str_dbg(smb_fname
),
1531 mode
= dos_mode_msdfs(state
->conn
, smb_fname
);
1533 mode
= dos_mode(state
->conn
, smb_fname
);
1540 static bool smbd_marshall_dir_entry(TALLOC_CTX
*ctx
,
1541 connection_struct
*conn
,
1543 uint32_t info_level
,
1544 struct ea_list
*name_list
,
1545 bool check_mangled_names
,
1546 bool requires_resume_key
,
1549 const struct smb_filename
*smb_fname
,
1550 int space_remaining
,
1557 uint64_t *last_entry_off
)
1559 char *p
, *q
, *pdata
= *ppdata
;
1561 uint64_t file_size
= 0;
1562 uint64_t allocation_size
= 0;
1563 uint64_t file_index
= 0;
1565 struct timespec mdate_ts
, adate_ts
, cdate_ts
, create_date_ts
;
1566 time_t mdate
= (time_t)0, adate
= (time_t)0, create_date
= (time_t)0;
1568 char *last_entry_ptr
;
1573 *out_of_space
= false;
1575 ZERO_STRUCT(mdate_ts
);
1576 ZERO_STRUCT(adate_ts
);
1577 ZERO_STRUCT(create_date_ts
);
1578 ZERO_STRUCT(cdate_ts
);
1580 if (!(mode
& FILE_ATTRIBUTE_DIRECTORY
)) {
1581 file_size
= get_file_size_stat(&smb_fname
->st
);
1583 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
, NULL
, &smb_fname
->st
);
1585 file_index
= get_FileIndex(conn
, &smb_fname
->st
);
1587 mdate_ts
= smb_fname
->st
.st_ex_mtime
;
1588 adate_ts
= smb_fname
->st
.st_ex_atime
;
1589 create_date_ts
= get_create_timespec(conn
, NULL
, smb_fname
);
1590 cdate_ts
= get_change_timespec(conn
, NULL
, smb_fname
);
1592 if (lp_dos_filetime_resolution(SNUM(conn
))) {
1593 dos_filetime_timespec(&create_date_ts
);
1594 dos_filetime_timespec(&mdate_ts
);
1595 dos_filetime_timespec(&adate_ts
);
1596 dos_filetime_timespec(&cdate_ts
);
1599 create_date
= convert_timespec_to_time_t(create_date_ts
);
1600 mdate
= convert_timespec_to_time_t(mdate_ts
);
1601 adate
= convert_timespec_to_time_t(adate_ts
);
1603 /* align the record */
1604 SMB_ASSERT(align
>= 1);
1606 off
= (int)PTR_DIFF(pdata
, base_data
);
1607 pad
= (off
+ (align
-1)) & ~(align
-1);
1610 if (pad
&& pad
> space_remaining
) {
1611 *out_of_space
= true;
1612 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1613 "for padding (wanted %u, had %d)\n",
1616 return false; /* Not finished - just out of space */
1620 /* initialize padding to 0 */
1622 memset(pdata
, 0, pad
);
1624 space_remaining
-= pad
;
1626 DEBUG(10,("smbd_marshall_dir_entry: space_remaining = %d\n",
1636 switch (info_level
) {
1637 case SMB_FIND_INFO_STANDARD
:
1638 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1639 if(requires_resume_key
) {
1643 srv_put_dos_date2(p
,0,create_date
);
1644 srv_put_dos_date2(p
,4,adate
);
1645 srv_put_dos_date2(p
,8,mdate
);
1646 SIVAL(p
,12,(uint32
)file_size
);
1647 SIVAL(p
,16,(uint32
)allocation_size
);
1651 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1652 p
+= ucs2_align(base_data
, p
, 0);
1654 len
= srvstr_push(base_data
, flags2
, p
,
1655 fname
, PTR_DIFF(end_data
, p
),
1657 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1659 SCVAL(nameptr
, -1, len
- 2);
1661 SCVAL(nameptr
, -1, 0);
1665 SCVAL(nameptr
, -1, len
- 1);
1667 SCVAL(nameptr
, -1, 0);
1673 case SMB_FIND_EA_SIZE
:
1674 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
1675 if (requires_resume_key
) {
1679 srv_put_dos_date2(p
,0,create_date
);
1680 srv_put_dos_date2(p
,4,adate
);
1681 srv_put_dos_date2(p
,8,mdate
);
1682 SIVAL(p
,12,(uint32
)file_size
);
1683 SIVAL(p
,16,(uint32
)allocation_size
);
1686 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
1688 SIVAL(p
,22,ea_size
); /* Extended attributes */
1692 len
= srvstr_push(base_data
, flags2
,
1693 p
, fname
, PTR_DIFF(end_data
, p
),
1694 STR_TERMINATE
| STR_NOALIGN
);
1695 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1708 SCVAL(nameptr
,0,len
);
1710 SCVAL(p
,0,0); p
+= 1; /* Extra zero byte ? - why.. */
1713 case SMB_FIND_EA_LIST
:
1715 struct ea_list
*file_list
= NULL
;
1719 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
1723 if (requires_resume_key
) {
1727 srv_put_dos_date2(p
,0,create_date
);
1728 srv_put_dos_date2(p
,4,adate
);
1729 srv_put_dos_date2(p
,8,mdate
);
1730 SIVAL(p
,12,(uint32
)file_size
);
1731 SIVAL(p
,16,(uint32
)allocation_size
);
1733 p
+= 22; /* p now points to the EA area. */
1735 status
= get_ea_list_from_file(ctx
, conn
, NULL
,
1737 &ea_len
, &file_list
);
1738 if (!NT_STATUS_IS_OK(status
)) {
1741 name_list
= ea_list_union(name_list
, file_list
, &ea_len
);
1743 /* We need to determine if this entry will fit in the space available. */
1744 /* Max string size is 255 bytes. */
1745 if (PTR_DIFF(p
+ 255 + ea_len
,pdata
) > space_remaining
) {
1746 *out_of_space
= true;
1747 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1748 "(wanted %u, had %d)\n",
1749 (unsigned int)PTR_DIFF(p
+ 255 + ea_len
,pdata
),
1751 return False
; /* Not finished - just out of space */
1754 /* Push the ea_data followed by the name. */
1755 p
+= fill_ea_buffer(ctx
, p
, space_remaining
, conn
, name_list
);
1757 len
= srvstr_push(base_data
, flags2
,
1758 p
+ 1, fname
, PTR_DIFF(end_data
, p
+1),
1759 STR_TERMINATE
| STR_NOALIGN
);
1760 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1773 SCVAL(nameptr
,0,len
);
1775 SCVAL(p
,0,0); p
+= 1; /* Extra zero byte ? - why.. */
1779 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
1780 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1781 was_8_3
= mangle_is_8_3(fname
, True
, conn
->params
);
1783 SIVAL(p
,0,reskey
); p
+= 4;
1784 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
1785 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
1786 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
1787 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
1788 SOFF_T(p
,0,file_size
); p
+= 8;
1789 SOFF_T(p
,0,allocation_size
); p
+= 8;
1790 SIVAL(p
,0,mode
); p
+= 4;
1791 q
= p
; p
+= 4; /* q is placeholder for name length. */
1793 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
1795 SIVAL(p
,0,ea_size
); /* Extended attributes */
1798 /* Clear the short name buffer. This is
1799 * IMPORTANT as not doing so will trigger
1800 * a Win2k client bug. JRA.
1802 if (!was_8_3
&& check_mangled_names
) {
1803 char mangled_name
[13]; /* mangled 8.3 name. */
1804 if (!name_to_8_3(fname
,mangled_name
,True
,
1806 /* Error - mangle failed ! */
1807 memset(mangled_name
,'\0',12);
1809 mangled_name
[12] = 0;
1810 len
= srvstr_push(base_data
, flags2
,
1811 p
+2, mangled_name
, 24,
1812 STR_UPPER
|STR_UNICODE
);
1814 memset(p
+ 2 + len
,'\0',24 - len
);
1821 len
= srvstr_push(base_data
, flags2
, p
,
1822 fname
, PTR_DIFF(end_data
, p
),
1823 STR_TERMINATE_ASCII
);
1827 len
= PTR_DIFF(p
, pdata
);
1828 pad
= (len
+ (align
-1)) & ~(align
-1);
1830 * offset to the next entry, the caller
1831 * will overwrite it for the last entry
1832 * that's why we always include the padding
1836 * set padding to zero
1839 memset(p
, 0, pad
- len
);
1846 case SMB_FIND_FILE_DIRECTORY_INFO
:
1847 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1849 SIVAL(p
,0,reskey
); p
+= 4;
1850 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
1851 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
1852 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
1853 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
1854 SOFF_T(p
,0,file_size
); p
+= 8;
1855 SOFF_T(p
,0,allocation_size
); p
+= 8;
1856 SIVAL(p
,0,mode
); p
+= 4;
1857 len
= srvstr_push(base_data
, flags2
,
1858 p
+ 4, fname
, PTR_DIFF(end_data
, p
+4),
1859 STR_TERMINATE_ASCII
);
1863 len
= PTR_DIFF(p
, pdata
);
1864 pad
= (len
+ (align
-1)) & ~(align
-1);
1866 * offset to the next entry, the caller
1867 * will overwrite it for the last entry
1868 * that's why we always include the padding
1872 * set padding to zero
1875 memset(p
, 0, pad
- len
);
1882 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
1883 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1885 SIVAL(p
,0,reskey
); p
+= 4;
1886 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
1887 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
1888 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
1889 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
1890 SOFF_T(p
,0,file_size
); p
+= 8;
1891 SOFF_T(p
,0,allocation_size
); p
+= 8;
1892 SIVAL(p
,0,mode
); p
+= 4;
1893 q
= p
; p
+= 4; /* q is placeholder for name length. */
1895 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
1897 SIVAL(p
,0,ea_size
); /* Extended attributes */
1900 len
= srvstr_push(base_data
, flags2
, p
,
1901 fname
, PTR_DIFF(end_data
, p
),
1902 STR_TERMINATE_ASCII
);
1906 len
= PTR_DIFF(p
, pdata
);
1907 pad
= (len
+ (align
-1)) & ~(align
-1);
1909 * offset to the next entry, the caller
1910 * will overwrite it for the last entry
1911 * that's why we always include the padding
1915 * set padding to zero
1918 memset(p
, 0, pad
- len
);
1925 case SMB_FIND_FILE_NAMES_INFO
:
1926 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1928 SIVAL(p
,0,reskey
); p
+= 4;
1930 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1931 acl on a dir (tridge) */
1932 len
= srvstr_push(base_data
, flags2
, p
,
1933 fname
, PTR_DIFF(end_data
, p
),
1934 STR_TERMINATE_ASCII
);
1938 len
= PTR_DIFF(p
, pdata
);
1939 pad
= (len
+ (align
-1)) & ~(align
-1);
1941 * offset to the next entry, the caller
1942 * will overwrite it for the last entry
1943 * that's why we always include the padding
1947 * set padding to zero
1950 memset(p
, 0, pad
- len
);
1957 case SMB_FIND_ID_FULL_DIRECTORY_INFO
:
1958 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1960 SIVAL(p
,0,reskey
); p
+= 4;
1961 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
1962 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
1963 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
1964 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
1965 SOFF_T(p
,0,file_size
); p
+= 8;
1966 SOFF_T(p
,0,allocation_size
); p
+= 8;
1967 SIVAL(p
,0,mode
); p
+= 4;
1968 q
= p
; p
+= 4; /* q is placeholder for name length. */
1970 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
1972 SIVAL(p
,0,ea_size
); /* Extended attributes */
1975 SIVAL(p
,0,0); p
+= 4; /* Unknown - reserved ? */
1976 SBVAL(p
,0,file_index
); p
+= 8;
1977 len
= srvstr_push(base_data
, flags2
, p
,
1978 fname
, PTR_DIFF(end_data
, p
),
1979 STR_TERMINATE_ASCII
);
1983 len
= PTR_DIFF(p
, pdata
);
1984 pad
= (len
+ (align
-1)) & ~(align
-1);
1986 * offset to the next entry, the caller
1987 * will overwrite it for the last entry
1988 * that's why we always include the padding
1992 * set padding to zero
1995 memset(p
, 0, pad
- len
);
2002 case SMB_FIND_ID_BOTH_DIRECTORY_INFO
:
2003 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
2004 was_8_3
= mangle_is_8_3(fname
, True
, conn
->params
);
2006 SIVAL(p
,0,reskey
); p
+= 4;
2007 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
2008 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
2009 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
2010 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
2011 SOFF_T(p
,0,file_size
); p
+= 8;
2012 SOFF_T(p
,0,allocation_size
); p
+= 8;
2013 SIVAL(p
,0,mode
); p
+= 4;
2014 q
= p
; p
+= 4; /* q is placeholder for name length */
2016 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
2018 SIVAL(p
,0,ea_size
); /* Extended attributes */
2021 /* Clear the short name buffer. This is
2022 * IMPORTANT as not doing so will trigger
2023 * a Win2k client bug. JRA.
2025 if (!was_8_3
&& check_mangled_names
) {
2026 char mangled_name
[13]; /* mangled 8.3 name. */
2027 if (!name_to_8_3(fname
,mangled_name
,True
,
2029 /* Error - mangle failed ! */
2030 memset(mangled_name
,'\0',12);
2032 mangled_name
[12] = 0;
2033 len
= srvstr_push(base_data
, flags2
,
2034 p
+2, mangled_name
, 24,
2035 STR_UPPER
|STR_UNICODE
);
2038 memset(p
+ 2 + len
,'\0',24 - len
);
2045 SSVAL(p
,0,0); p
+= 2; /* Reserved ? */
2046 SBVAL(p
,0,file_index
); p
+= 8;
2047 len
= srvstr_push(base_data
, flags2
, p
,
2048 fname
, PTR_DIFF(end_data
, p
),
2049 STR_TERMINATE_ASCII
);
2053 len
= PTR_DIFF(p
, pdata
);
2054 pad
= (len
+ (align
-1)) & ~(align
-1);
2056 * offset to the next entry, the caller
2057 * will overwrite it for the last entry
2058 * that's why we always include the padding
2062 * set padding to zero
2065 memset(p
, 0, pad
- len
);
2072 /* CIFS UNIX Extension. */
2074 case SMB_FIND_FILE_UNIX
:
2075 case SMB_FIND_FILE_UNIX_INFO2
:
2077 SIVAL(p
,0,reskey
); p
+= 4; /* Used for continuing search. */
2079 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
2081 if (info_level
== SMB_FIND_FILE_UNIX
) {
2082 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
2083 p
= store_file_unix_basic(conn
, p
,
2084 NULL
, &smb_fname
->st
);
2085 len
= srvstr_push(base_data
, flags2
, p
,
2086 fname
, PTR_DIFF(end_data
, p
),
2089 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
2090 p
= store_file_unix_basic_info2(conn
, p
,
2091 NULL
, &smb_fname
->st
);
2094 len
= srvstr_push(base_data
, flags2
, p
, fname
,
2095 PTR_DIFF(end_data
, p
), 0);
2096 SIVAL(nameptr
, 0, len
);
2101 len
= PTR_DIFF(p
, pdata
);
2102 pad
= (len
+ (align
-1)) & ~(align
-1);
2104 * offset to the next entry, the caller
2105 * will overwrite it for the last entry
2106 * that's why we always include the padding
2110 * set padding to zero
2113 memset(p
, 0, pad
- len
);
2118 /* End of SMB_QUERY_FILE_UNIX_BASIC */
2126 if (PTR_DIFF(p
,pdata
) > space_remaining
) {
2127 *out_of_space
= true;
2128 DEBUG(9,("smbd_marshall_dir_entry: out of space "
2129 "(wanted %u, had %d)\n",
2130 (unsigned int)PTR_DIFF(p
,pdata
),
2132 return false; /* Not finished - just out of space */
2135 /* Setup the last entry pointer, as an offset from base_data */
2136 *last_entry_off
= PTR_DIFF(last_entry_ptr
,base_data
);
2137 /* Advance the data pointer to the next slot */
2143 bool smbd_dirptr_lanman2_entry(TALLOC_CTX
*ctx
,
2144 connection_struct
*conn
,
2145 struct dptr_struct
*dirptr
,
2147 const char *path_mask
,
2150 int requires_resume_key
,
2158 int space_remaining
,
2160 bool *got_exact_match
,
2161 int *_last_entry_off
,
2162 struct ea_list
*name_list
)
2165 const char *mask
= NULL
;
2166 long prev_dirpos
= 0;
2169 struct smb_filename
*smb_fname
= NULL
;
2170 struct smbd_dirptr_lanman2_state state
;
2172 uint64_t last_entry_off
= 0;
2176 state
.info_level
= info_level
;
2177 state
.check_mangled_names
= lp_manglednames(conn
->params
);
2178 state
.has_wild
= dptr_has_wild(dirptr
);
2179 state
.got_exact_match
= false;
2181 *out_of_space
= false;
2182 *got_exact_match
= false;
2184 p
= strrchr_m(path_mask
,'/');
2195 ok
= smbd_dirptr_get_entry(ctx
,
2201 smbd_dirptr_lanman2_match_fn
,
2202 smbd_dirptr_lanman2_mode_fn
,
2212 *got_exact_match
= state
.got_exact_match
;
2214 ok
= smbd_marshall_dir_entry(ctx
,
2219 state
.check_mangled_names
,
2220 requires_resume_key
,
2233 TALLOC_FREE(smb_fname
);
2234 if (*out_of_space
) {
2235 dptr_SeekDir(dirptr
, prev_dirpos
);
2242 *_last_entry_off
= last_entry_off
;
2246 static bool get_lanman2_dir_entry(TALLOC_CTX
*ctx
,
2247 connection_struct
*conn
,
2248 struct dptr_struct
*dirptr
,
2250 const char *path_mask
,
2253 bool requires_resume_key
,
2259 int space_remaining
,
2261 bool *got_exact_match
,
2262 int *last_entry_off
,
2263 struct ea_list
*name_list
)
2266 const bool do_pad
= true;
2268 if (info_level
>= 1 && info_level
<= 3) {
2269 /* No alignment on earlier info levels. */
2273 return smbd_dirptr_lanman2_entry(ctx
, conn
, dirptr
, flags2
,
2274 path_mask
, dirtype
, info_level
,
2275 requires_resume_key
, dont_descend
, ask_sharemode
,
2277 ppdata
, base_data
, end_data
,
2279 out_of_space
, got_exact_match
,
2280 last_entry_off
, name_list
);
2283 /****************************************************************************
2284 Reply to a TRANS2_FINDFIRST.
2285 ****************************************************************************/
2287 static void call_trans2findfirst(connection_struct
*conn
,
2288 struct smb_request
*req
,
2289 char **pparams
, int total_params
,
2290 char **ppdata
, int total_data
,
2291 unsigned int max_data_bytes
)
2293 /* We must be careful here that we don't return more than the
2294 allowed number of data bytes. If this means returning fewer than
2295 maxentries then so be it. We assume that the redirector has
2296 enough room for the fixed number of parameter bytes it has
2298 struct smb_filename
*smb_dname
= NULL
;
2299 char *params
= *pparams
;
2300 char *pdata
= *ppdata
;
2304 uint16 findfirst_flags
;
2305 bool close_after_first
;
2307 bool requires_resume_key
;
2309 char *directory
= NULL
;
2312 int last_entry_off
=0;
2316 bool finished
= False
;
2317 bool dont_descend
= False
;
2318 bool out_of_space
= False
;
2319 int space_remaining
;
2320 bool mask_contains_wcard
= False
;
2321 struct ea_list
*ea_list
= NULL
;
2322 NTSTATUS ntstatus
= NT_STATUS_OK
;
2323 bool ask_sharemode
= lp_parm_bool(SNUM(conn
), "smbd", "search ask sharemode", true);
2324 TALLOC_CTX
*ctx
= talloc_tos();
2325 struct dptr_struct
*dirptr
= NULL
;
2326 struct smbd_server_connection
*sconn
= req
->sconn
;
2327 uint32_t ucf_flags
= (UCF_SAVE_LCOMP
| UCF_ALWAYS_ALLOW_WCARD_LCOMP
);
2328 bool backup_priv
= false;
2330 if (total_params
< 13) {
2331 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2335 dirtype
= SVAL(params
,0);
2336 maxentries
= SVAL(params
,2);
2337 findfirst_flags
= SVAL(params
,4);
2338 close_after_first
= (findfirst_flags
& FLAG_TRANS2_FIND_CLOSE
);
2339 close_if_end
= (findfirst_flags
& FLAG_TRANS2_FIND_CLOSE_IF_END
);
2340 requires_resume_key
= (findfirst_flags
& FLAG_TRANS2_FIND_REQUIRE_RESUME
);
2341 backup_priv
= ((findfirst_flags
& FLAG_TRANS2_FIND_BACKUP_INTENT
) &&
2342 security_token_has_privilege(get_current_nttok(conn
),
2345 info_level
= SVAL(params
,6);
2347 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2348 close_if_end = %d requires_resume_key = %d backup_priv = %d level = 0x%x, max_data_bytes = %d\n",
2349 (unsigned int)dirtype
, maxentries
, close_after_first
, close_if_end
, requires_resume_key
,
2351 info_level
, max_data_bytes
));
2354 /* W2K3 seems to treat zero as 1. */
2358 switch (info_level
) {
2359 case SMB_FIND_INFO_STANDARD
:
2360 case SMB_FIND_EA_SIZE
:
2361 case SMB_FIND_EA_LIST
:
2362 case SMB_FIND_FILE_DIRECTORY_INFO
:
2363 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
2364 case SMB_FIND_FILE_NAMES_INFO
:
2365 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
2366 case SMB_FIND_ID_FULL_DIRECTORY_INFO
:
2367 case SMB_FIND_ID_BOTH_DIRECTORY_INFO
:
2369 case SMB_FIND_FILE_UNIX
:
2370 case SMB_FIND_FILE_UNIX_INFO2
:
2371 /* Always use filesystem for UNIX mtime query. */
2372 ask_sharemode
= false;
2373 if (!lp_unix_extensions()) {
2374 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2377 ucf_flags
|= UCF_UNIX_NAME_LOOKUP
;
2380 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2384 srvstr_get_path_wcard(ctx
, params
, req
->flags2
, &directory
,
2385 params
+12, total_params
- 12,
2386 STR_TERMINATE
, &ntstatus
, &mask_contains_wcard
);
2387 if (!NT_STATUS_IS_OK(ntstatus
)) {
2388 reply_nterror(req
, ntstatus
);
2394 ntstatus
= filename_convert_with_privilege(ctx
,
2399 &mask_contains_wcard
,
2402 ntstatus
= filename_convert(ctx
, conn
,
2403 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
2406 &mask_contains_wcard
,
2410 if (!NT_STATUS_IS_OK(ntstatus
)) {
2411 if (NT_STATUS_EQUAL(ntstatus
,NT_STATUS_PATH_NOT_COVERED
)) {
2412 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
2413 ERRSRV
, ERRbadpath
);
2416 reply_nterror(req
, ntstatus
);
2420 mask
= smb_dname
->original_lcomp
;
2422 directory
= smb_dname
->base_name
;
2424 p
= strrchr_m(directory
,'/');
2426 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2427 if((directory
[0] == '.') && (directory
[1] == '\0')) {
2428 mask
= talloc_strdup(ctx
,"*");
2430 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2433 mask_contains_wcard
= True
;
2439 if (p
== NULL
|| p
== directory
) {
2440 /* Ensure we don't have a directory name of "". */
2441 directory
= talloc_strdup(talloc_tos(), ".");
2443 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2448 DEBUG(5,("dir=%s, mask = %s\n",directory
, mask
));
2450 if (info_level
== SMB_FIND_EA_LIST
) {
2453 if (total_data
< 4) {
2454 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2458 ea_size
= IVAL(pdata
,0);
2459 if (ea_size
!= total_data
) {
2460 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2461 total_data=%u (should be %u)\n", (unsigned int)total_data
, (unsigned int)IVAL(pdata
,0) ));
2462 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2466 if (!lp_ea_support(SNUM(conn
))) {
2467 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
2471 /* Pull out the list of names. */
2472 ea_list
= read_ea_name_list(ctx
, pdata
+ 4, ea_size
- 4);
2474 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2479 *ppdata
= (char *)SMB_REALLOC(
2480 *ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
2481 if(*ppdata
== NULL
) {
2482 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2486 data_end
= pdata
+ max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
- 1;
2488 /* Realloc the params space */
2489 *pparams
= (char *)SMB_REALLOC(*pparams
, 10);
2490 if (*pparams
== NULL
) {
2491 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2496 /* Save the wildcard match and attribs we are using on this directory -
2497 needed as lanman2 assumes these are being saved between calls */
2499 ntstatus
= dptr_create(conn
,
2507 mask_contains_wcard
,
2511 if (!NT_STATUS_IS_OK(ntstatus
)) {
2512 reply_nterror(req
, ntstatus
);
2517 /* Remember this in case we have
2518 to do a findnext. */
2519 dptr_set_priv(dirptr
);
2522 dptr_num
= dptr_dnum(dirptr
);
2523 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num
, mask
, dirtype
));
2525 /* Initialize per TRANS2_FIND_FIRST operation data */
2526 dptr_init_search_op(dirptr
);
2528 /* We don't need to check for VOL here as this is returned by
2529 a different TRANS2 call. */
2531 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2532 directory
,lp_dontdescend(ctx
, SNUM(conn
))));
2533 if (in_list(directory
,lp_dontdescend(ctx
, SNUM(conn
)),conn
->case_sensitive
))
2534 dont_descend
= True
;
2537 space_remaining
= max_data_bytes
;
2538 out_of_space
= False
;
2540 for (i
=0;(i
<maxentries
) && !finished
&& !out_of_space
;i
++) {
2541 bool got_exact_match
= False
;
2543 /* this is a heuristic to avoid seeking the dirptr except when
2544 absolutely necessary. It allows for a filename of about 40 chars */
2545 if (space_remaining
< DIRLEN_GUESS
&& numentries
> 0) {
2546 out_of_space
= True
;
2549 finished
= !get_lanman2_dir_entry(ctx
,
2553 mask
,dirtype
,info_level
,
2554 requires_resume_key
,dont_descend
,
2557 space_remaining
, &out_of_space
,
2559 &last_entry_off
, ea_list
);
2562 if (finished
&& out_of_space
)
2565 if (!finished
&& !out_of_space
)
2569 * As an optimisation if we know we aren't looking
2570 * for a wildcard name (ie. the name matches the wildcard exactly)
2571 * then we can finish on any (first) match.
2572 * This speeds up large directory searches. JRA.
2578 /* Ensure space_remaining never goes -ve. */
2579 if (PTR_DIFF(p
,pdata
) > max_data_bytes
) {
2580 space_remaining
= 0;
2581 out_of_space
= true;
2583 space_remaining
= max_data_bytes
- PTR_DIFF(p
,pdata
);
2587 /* Check if we can close the dirptr */
2588 if(close_after_first
|| (finished
&& close_if_end
)) {
2589 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num
));
2590 dptr_close(sconn
, &dptr_num
);
2594 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2595 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2596 * the protocol level is less than NT1. Tested with smbclient. JRA.
2597 * This should fix the OS/2 client bug #2335.
2600 if(numentries
== 0) {
2601 dptr_close(sconn
, &dptr_num
);
2602 if (get_Protocol() < PROTOCOL_NT1
) {
2603 reply_force_doserror(req
, ERRDOS
, ERRnofiles
);
2606 reply_botherror(req
, NT_STATUS_NO_SUCH_FILE
,
2607 ERRDOS
, ERRbadfile
);
2612 /* At this point pdata points to numentries directory entries. */
2614 /* Set up the return parameter block */
2615 SSVAL(params
,0,dptr_num
);
2616 SSVAL(params
,2,numentries
);
2617 SSVAL(params
,4,finished
);
2618 SSVAL(params
,6,0); /* Never an EA error */
2619 SSVAL(params
,8,last_entry_off
);
2621 send_trans2_replies(conn
, req
, params
, 10, pdata
, PTR_DIFF(p
,pdata
),
2624 if ((! *directory
) && dptr_path(sconn
, dptr_num
)) {
2625 directory
= talloc_strdup(talloc_tos(),dptr_path(sconn
, dptr_num
));
2627 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2631 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2632 smb_fn_name(req
->cmd
),
2633 mask
, directory
, dirtype
, numentries
) );
2636 * Force a name mangle here to ensure that the
2637 * mask as an 8.3 name is top of the mangled cache.
2638 * The reasons for this are subtle. Don't remove
2639 * this code unless you know what you are doing
2640 * (see PR#13758). JRA.
2643 if(!mangle_is_8_3_wildcards( mask
, False
, conn
->params
)) {
2644 char mangled_name
[13];
2645 name_to_8_3(mask
, mangled_name
, True
, conn
->params
);
2653 TALLOC_FREE(smb_dname
);
2657 /****************************************************************************
2658 Reply to a TRANS2_FINDNEXT.
2659 ****************************************************************************/
2661 static void call_trans2findnext(connection_struct
*conn
,
2662 struct smb_request
*req
,
2663 char **pparams
, int total_params
,
2664 char **ppdata
, int total_data
,
2665 unsigned int max_data_bytes
)
2667 /* We must be careful here that we don't return more than the
2668 allowed number of data bytes. If this means returning fewer than
2669 maxentries then so be it. We assume that the redirector has
2670 enough room for the fixed number of parameter bytes it has
2672 char *params
= *pparams
;
2673 char *pdata
= *ppdata
;
2679 uint16 findnext_flags
;
2680 bool close_after_request
;
2682 bool requires_resume_key
;
2684 bool mask_contains_wcard
= False
;
2685 char *resume_name
= NULL
;
2686 const char *mask
= NULL
;
2687 const char *directory
= NULL
;
2691 int i
, last_entry_off
=0;
2692 bool finished
= False
;
2693 bool dont_descend
= False
;
2694 bool out_of_space
= False
;
2695 int space_remaining
;
2696 struct ea_list
*ea_list
= NULL
;
2697 NTSTATUS ntstatus
= NT_STATUS_OK
;
2698 bool ask_sharemode
= lp_parm_bool(SNUM(conn
), "smbd", "search ask sharemode", true);
2699 TALLOC_CTX
*ctx
= talloc_tos();
2700 struct dptr_struct
*dirptr
;
2701 struct smbd_server_connection
*sconn
= req
->sconn
;
2702 bool backup_priv
= false;
2704 if (total_params
< 13) {
2705 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2709 dptr_num
= SVAL(params
,0);
2710 maxentries
= SVAL(params
,2);
2711 info_level
= SVAL(params
,4);
2712 resume_key
= IVAL(params
,6);
2713 findnext_flags
= SVAL(params
,10);
2714 close_after_request
= (findnext_flags
& FLAG_TRANS2_FIND_CLOSE
);
2715 close_if_end
= (findnext_flags
& FLAG_TRANS2_FIND_CLOSE_IF_END
);
2716 requires_resume_key
= (findnext_flags
& FLAG_TRANS2_FIND_REQUIRE_RESUME
);
2717 continue_bit
= (findnext_flags
& FLAG_TRANS2_FIND_CONTINUE
);
2719 if (!continue_bit
) {
2720 /* We only need resume_name if continue_bit is zero. */
2721 srvstr_get_path_wcard(ctx
, params
, req
->flags2
, &resume_name
,
2723 total_params
- 12, STR_TERMINATE
, &ntstatus
,
2724 &mask_contains_wcard
);
2725 if (!NT_STATUS_IS_OK(ntstatus
)) {
2726 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2727 complain (it thinks we're asking for the directory above the shared
2728 path or an invalid name). Catch this as the resume name is only compared, never used in
2729 a file access. JRA. */
2730 srvstr_pull_talloc(ctx
, params
, req
->flags2
,
2731 &resume_name
, params
+12,
2735 if (!resume_name
|| !(ISDOT(resume_name
) || ISDOTDOT(resume_name
))) {
2736 reply_nterror(req
, ntstatus
);
2742 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2743 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2744 resume_key = %d resume name = %s continue=%d level = %d\n",
2745 dptr_num
, max_data_bytes
, maxentries
, close_after_request
, close_if_end
,
2746 requires_resume_key
, resume_key
,
2747 resume_name
? resume_name
: "(NULL)", continue_bit
, info_level
));
2750 /* W2K3 seems to treat zero as 1. */
2754 switch (info_level
) {
2755 case SMB_FIND_INFO_STANDARD
:
2756 case SMB_FIND_EA_SIZE
:
2757 case SMB_FIND_EA_LIST
:
2758 case SMB_FIND_FILE_DIRECTORY_INFO
:
2759 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
2760 case SMB_FIND_FILE_NAMES_INFO
:
2761 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
2762 case SMB_FIND_ID_FULL_DIRECTORY_INFO
:
2763 case SMB_FIND_ID_BOTH_DIRECTORY_INFO
:
2765 case SMB_FIND_FILE_UNIX
:
2766 case SMB_FIND_FILE_UNIX_INFO2
:
2767 /* Always use filesystem for UNIX mtime query. */
2768 ask_sharemode
= false;
2769 if (!lp_unix_extensions()) {
2770 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2775 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2779 if (info_level
== SMB_FIND_EA_LIST
) {
2782 if (total_data
< 4) {
2783 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2787 ea_size
= IVAL(pdata
,0);
2788 if (ea_size
!= total_data
) {
2789 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2790 total_data=%u (should be %u)\n", (unsigned int)total_data
, (unsigned int)IVAL(pdata
,0) ));
2791 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2795 if (!lp_ea_support(SNUM(conn
))) {
2796 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
2800 /* Pull out the list of names. */
2801 ea_list
= read_ea_name_list(ctx
, pdata
+ 4, ea_size
- 4);
2803 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2808 *ppdata
= (char *)SMB_REALLOC(
2809 *ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
2810 if(*ppdata
== NULL
) {
2811 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2816 data_end
= pdata
+ max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
- 1;
2818 /* Realloc the params space */
2819 *pparams
= (char *)SMB_REALLOC(*pparams
, 6*SIZEOFWORD
);
2820 if(*pparams
== NULL
) {
2821 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2827 /* Check that the dptr is valid */
2828 if(!(dirptr
= dptr_fetch_lanman2(sconn
, dptr_num
))) {
2829 reply_nterror(req
, STATUS_NO_MORE_FILES
);
2833 directory
= dptr_path(sconn
, dptr_num
);
2835 /* Get the wildcard mask from the dptr */
2836 if((mask
= dptr_wcard(sconn
, dptr_num
))== NULL
) {
2837 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num
));
2838 reply_nterror(req
, STATUS_NO_MORE_FILES
);
2842 /* Get the attr mask from the dptr */
2843 dirtype
= dptr_attr(sconn
, dptr_num
);
2845 backup_priv
= dptr_get_priv(dirptr
);
2847 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld) "
2848 "backup_priv = %d\n",
2849 dptr_num
, mask
, dirtype
,
2851 dptr_TellDir(dirptr
),
2854 /* Initialize per TRANS2_FIND_NEXT operation data */
2855 dptr_init_search_op(dirptr
);
2857 /* We don't need to check for VOL here as this is returned by
2858 a different TRANS2 call. */
2860 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2861 directory
,lp_dontdescend(ctx
, SNUM(conn
))));
2862 if (in_list(directory
,lp_dontdescend(ctx
, SNUM(conn
)),conn
->case_sensitive
))
2863 dont_descend
= True
;
2866 space_remaining
= max_data_bytes
;
2867 out_of_space
= False
;
2874 * Seek to the correct position. We no longer use the resume key but
2875 * depend on the last file name instead.
2878 if(!continue_bit
&& resume_name
&& *resume_name
) {
2881 long current_pos
= 0;
2883 * Remember, name_to_8_3 is called by
2884 * get_lanman2_dir_entry(), so the resume name
2885 * could be mangled. Ensure we check the unmangled name.
2888 if (mangle_is_mangled(resume_name
, conn
->params
)) {
2889 char *new_resume_name
= NULL
;
2890 mangle_lookup_name_from_8_3(ctx
,
2894 if (new_resume_name
) {
2895 resume_name
= new_resume_name
;
2900 * Fix for NT redirector problem triggered by resume key indexes
2901 * changing between directory scans. We now return a resume key of 0
2902 * and instead look for the filename to continue from (also given
2903 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2904 * findfirst/findnext (as is usual) then the directory pointer
2905 * should already be at the correct place.
2908 finished
= !dptr_SearchDir(dirptr
, resume_name
, ¤t_pos
, &st
);
2909 } /* end if resume_name && !continue_bit */
2911 for (i
=0;(i
<(int)maxentries
) && !finished
&& !out_of_space
;i
++) {
2912 bool got_exact_match
= False
;
2914 /* this is a heuristic to avoid seeking the dirptr except when
2915 absolutely necessary. It allows for a filename of about 40 chars */
2916 if (space_remaining
< DIRLEN_GUESS
&& numentries
> 0) {
2917 out_of_space
= True
;
2920 finished
= !get_lanman2_dir_entry(ctx
,
2924 mask
,dirtype
,info_level
,
2925 requires_resume_key
,dont_descend
,
2928 space_remaining
, &out_of_space
,
2930 &last_entry_off
, ea_list
);
2933 if (finished
&& out_of_space
)
2936 if (!finished
&& !out_of_space
)
2940 * As an optimisation if we know we aren't looking
2941 * for a wildcard name (ie. the name matches the wildcard exactly)
2942 * then we can finish on any (first) match.
2943 * This speeds up large directory searches. JRA.
2949 space_remaining
= max_data_bytes
- PTR_DIFF(p
,pdata
);
2952 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2953 smb_fn_name(req
->cmd
),
2954 mask
, directory
, dirtype
, numentries
) );
2956 /* Check if we can close the dirptr */
2957 if(close_after_request
|| (finished
&& close_if_end
)) {
2958 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num
));
2959 dptr_close(sconn
, &dptr_num
); /* This frees up the saved mask */
2966 /* Set up the return parameter block */
2967 SSVAL(params
,0,numentries
);
2968 SSVAL(params
,2,finished
);
2969 SSVAL(params
,4,0); /* Never an EA error */
2970 SSVAL(params
,6,last_entry_off
);
2972 send_trans2_replies(conn
, req
, params
, 8, pdata
, PTR_DIFF(p
,pdata
),
2978 unsigned char *create_volume_objectid(connection_struct
*conn
, unsigned char objid
[16])
2980 E_md4hash(lp_servicename(talloc_tos(), SNUM(conn
)),objid
);
2984 static void samba_extended_info_version(struct smb_extended_info
*extended_info
)
2986 SMB_ASSERT(extended_info
!= NULL
);
2988 extended_info
->samba_magic
= SAMBA_EXTENDED_INFO_MAGIC
;
2989 extended_info
->samba_version
= ((SAMBA_VERSION_MAJOR
& 0xff) << 24)
2990 | ((SAMBA_VERSION_MINOR
& 0xff) << 16)
2991 | ((SAMBA_VERSION_RELEASE
& 0xff) << 8);
2992 #ifdef SAMBA_VERSION_REVISION
2993 extended_info
->samba_version
|= (tolower(*SAMBA_VERSION_REVISION
) - 'a' + 1) & 0xff;
2995 extended_info
->samba_subversion
= 0;
2996 #ifdef SAMBA_VERSION_RC_RELEASE
2997 extended_info
->samba_subversion
|= (SAMBA_VERSION_RC_RELEASE
& 0xff) << 24;
2999 #ifdef SAMBA_VERSION_PRE_RELEASE
3000 extended_info
->samba_subversion
|= (SAMBA_VERSION_PRE_RELEASE
& 0xff) << 16;
3003 #ifdef SAMBA_VERSION_VENDOR_PATCH
3004 extended_info
->samba_subversion
|= (SAMBA_VERSION_VENDOR_PATCH
& 0xffff);
3006 extended_info
->samba_gitcommitdate
= 0;
3007 #ifdef SAMBA_VERSION_COMMIT_TIME
3008 unix_to_nt_time(&extended_info
->samba_gitcommitdate
, SAMBA_VERSION_COMMIT_TIME
);
3011 memset(extended_info
->samba_version_string
, 0,
3012 sizeof(extended_info
->samba_version_string
));
3014 snprintf (extended_info
->samba_version_string
,
3015 sizeof(extended_info
->samba_version_string
),
3016 "%s", samba_version_string());
3019 NTSTATUS
smbd_do_qfsinfo(connection_struct
*conn
,
3020 TALLOC_CTX
*mem_ctx
,
3021 uint16_t info_level
,
3023 unsigned int max_data_bytes
,
3027 char *pdata
, *end_data
;
3028 int data_len
= 0, len
;
3029 const char *vname
= volume_label(talloc_tos(), SNUM(conn
));
3030 int snum
= SNUM(conn
);
3031 char *fstype
= lp_fstype(talloc_tos(), SNUM(conn
));
3032 uint32 additional_flags
= 0;
3033 struct smb_filename smb_fname_dot
;
3037 if (info_level
!= SMB_QUERY_CIFS_UNIX_INFO
) {
3038 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
3039 "info level (0x%x) on IPC$.\n",
3040 (unsigned int)info_level
));
3041 return NT_STATUS_ACCESS_DENIED
;
3045 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level
));
3047 ZERO_STRUCT(smb_fname_dot
);
3048 smb_fname_dot
.base_name
= discard_const_p(char, ".");
3050 if(SMB_VFS_STAT(conn
, &smb_fname_dot
) != 0) {
3051 DEBUG(2,("stat of . failed (%s)\n", strerror(errno
)));
3052 return map_nt_error_from_unix(errno
);
3055 st
= smb_fname_dot
.st
;
3057 *ppdata
= (char *)SMB_REALLOC(
3058 *ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
3059 if (*ppdata
== NULL
) {
3060 return NT_STATUS_NO_MEMORY
;
3064 memset((char *)pdata
,'\0',max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
3065 end_data
= pdata
+ max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
- 1;
3067 switch (info_level
) {
3068 case SMB_INFO_ALLOCATION
:
3070 uint64_t dfree
,dsize
,bsize
,block_size
,sectors_per_unit
,bytes_per_sector
;
3072 if (get_dfree_info(conn
,".",False
,&bsize
,&dfree
,&dsize
) == (uint64_t)-1) {
3073 return map_nt_error_from_unix(errno
);
3076 block_size
= lp_block_size(snum
);
3077 if (bsize
< block_size
) {
3078 uint64_t factor
= block_size
/bsize
;
3083 if (bsize
> block_size
) {
3084 uint64_t factor
= bsize
/block_size
;
3089 bytes_per_sector
= 512;
3090 sectors_per_unit
= bsize
/bytes_per_sector
;
3092 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
3093 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st
.st_ex_dev
, (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
3094 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
3096 SIVAL(pdata
,l1_idFileSystem
,st
.st_ex_dev
);
3097 SIVAL(pdata
,l1_cSectorUnit
,sectors_per_unit
);
3098 SIVAL(pdata
,l1_cUnit
,dsize
);
3099 SIVAL(pdata
,l1_cUnitAvail
,dfree
);
3100 SSVAL(pdata
,l1_cbSector
,bytes_per_sector
);
3104 case SMB_INFO_VOLUME
:
3105 /* Return volume name */
3107 * Add volume serial number - hash of a combination of
3108 * the called hostname and the service name.
3110 SIVAL(pdata
,0,str_checksum(lp_servicename(talloc_tos(), snum
)) ^ (str_checksum(get_local_machine_name())<<16) );
3112 * Win2k3 and previous mess this up by sending a name length
3113 * one byte short. I believe only older clients (OS/2 Win9x) use
3114 * this call so try fixing this by adding a terminating null to
3115 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
3119 pdata
+l2_vol_szVolLabel
, vname
,
3120 PTR_DIFF(end_data
, pdata
+l2_vol_szVolLabel
),
3121 STR_NOALIGN
|STR_TERMINATE
);
3122 SCVAL(pdata
,l2_vol_cch
,len
);
3123 data_len
= l2_vol_szVolLabel
+ len
;
3124 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %d, name = %s\n",
3125 (unsigned)convert_timespec_to_time_t(st
.st_ex_ctime
),
3129 case SMB_QUERY_FS_ATTRIBUTE_INFO
:
3130 case SMB_FS_ATTRIBUTE_INFORMATION
:
3132 additional_flags
= 0;
3133 #if defined(HAVE_SYS_QUOTAS)
3134 additional_flags
|= FILE_VOLUME_QUOTAS
;
3137 if(lp_nt_acl_support(SNUM(conn
))) {
3138 additional_flags
|= FILE_PERSISTENT_ACLS
;
3141 /* Capabilities are filled in at connection time through STATVFS call */
3142 additional_flags
|= conn
->fs_capabilities
;
3143 additional_flags
|= lp_parm_int(conn
->params
->service
,
3144 "share", "fake_fscaps",
3147 SIVAL(pdata
,0,FILE_CASE_PRESERVED_NAMES
|FILE_CASE_SENSITIVE_SEARCH
|
3148 FILE_SUPPORTS_OBJECT_IDS
|FILE_UNICODE_ON_DISK
|
3149 additional_flags
); /* FS ATTRIBUTES */
3151 SIVAL(pdata
,4,255); /* Max filename component length */
3152 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
3153 and will think we can't do long filenames */
3154 len
= srvstr_push(pdata
, flags2
, pdata
+12, fstype
,
3155 PTR_DIFF(end_data
, pdata
+12),
3158 data_len
= 12 + len
;
3161 case SMB_QUERY_FS_LABEL_INFO
:
3162 case SMB_FS_LABEL_INFORMATION
:
3163 len
= srvstr_push(pdata
, flags2
, pdata
+4, vname
,
3164 PTR_DIFF(end_data
, pdata
+4), 0);
3169 case SMB_QUERY_FS_VOLUME_INFO
:
3170 case SMB_FS_VOLUME_INFORMATION
:
3173 * Add volume serial number - hash of a combination of
3174 * the called hostname and the service name.
3176 SIVAL(pdata
,8,str_checksum(lp_servicename(talloc_tos(), snum
)) ^
3177 (str_checksum(get_local_machine_name())<<16));
3179 /* Max label len is 32 characters. */
3180 len
= srvstr_push(pdata
, flags2
, pdata
+18, vname
,
3181 PTR_DIFF(end_data
, pdata
+18),
3183 SIVAL(pdata
,12,len
);
3186 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3187 (int)strlen(vname
),vname
,
3188 lp_servicename(talloc_tos(), snum
)));
3191 case SMB_QUERY_FS_SIZE_INFO
:
3192 case SMB_FS_SIZE_INFORMATION
:
3194 uint64_t dfree
,dsize
,bsize
,block_size
,sectors_per_unit
,bytes_per_sector
;
3196 if (get_dfree_info(conn
,".",False
,&bsize
,&dfree
,&dsize
) == (uint64_t)-1) {
3197 return map_nt_error_from_unix(errno
);
3199 block_size
= lp_block_size(snum
);
3200 if (bsize
< block_size
) {
3201 uint64_t factor
= block_size
/bsize
;
3206 if (bsize
> block_size
) {
3207 uint64_t factor
= bsize
/block_size
;
3212 bytes_per_sector
= 512;
3213 sectors_per_unit
= bsize
/bytes_per_sector
;
3214 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3215 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
3216 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
3217 SBIG_UINT(pdata
,0,dsize
);
3218 SBIG_UINT(pdata
,8,dfree
);
3219 SIVAL(pdata
,16,sectors_per_unit
);
3220 SIVAL(pdata
,20,bytes_per_sector
);
3224 case SMB_FS_FULL_SIZE_INFORMATION
:
3226 uint64_t dfree
,dsize
,bsize
,block_size
,sectors_per_unit
,bytes_per_sector
;
3228 if (get_dfree_info(conn
,".",False
,&bsize
,&dfree
,&dsize
) == (uint64_t)-1) {
3229 return map_nt_error_from_unix(errno
);
3231 block_size
= lp_block_size(snum
);
3232 if (bsize
< block_size
) {
3233 uint64_t factor
= block_size
/bsize
;
3238 if (bsize
> block_size
) {
3239 uint64_t factor
= bsize
/block_size
;
3244 bytes_per_sector
= 512;
3245 sectors_per_unit
= bsize
/bytes_per_sector
;
3246 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3247 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
3248 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
3249 SBIG_UINT(pdata
,0,dsize
); /* Total Allocation units. */
3250 SBIG_UINT(pdata
,8,dfree
); /* Caller available allocation units. */
3251 SBIG_UINT(pdata
,16,dfree
); /* Actual available allocation units. */
3252 SIVAL(pdata
,24,sectors_per_unit
); /* Sectors per allocation unit. */
3253 SIVAL(pdata
,28,bytes_per_sector
); /* Bytes per sector. */
3257 case SMB_QUERY_FS_DEVICE_INFO
:
3258 case SMB_FS_DEVICE_INFORMATION
:
3260 uint32_t characteristics
= FILE_DEVICE_IS_MOUNTED
;
3262 if (!CAN_WRITE(conn
)) {
3263 characteristics
|= FILE_READ_ONLY_DEVICE
;
3266 SIVAL(pdata
,0,FILE_DEVICE_DISK
); /* dev type */
3267 SIVAL(pdata
,4,characteristics
);
3271 #ifdef HAVE_SYS_QUOTAS
3272 case SMB_FS_QUOTA_INFORMATION
:
3274 * what we have to send --metze:
3276 * Unknown1: 24 NULL bytes
3277 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3278 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3279 * Quota Flags: 2 byte :
3280 * Unknown3: 6 NULL bytes
3284 * details for Quota Flags:
3286 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3287 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3288 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3289 * 0x0001 Enable Quotas: enable quota for this fs
3293 /* we need to fake up a fsp here,
3294 * because its not send in this call
3297 SMB_NTQUOTA_STRUCT quotas
;
3300 ZERO_STRUCT(quotas
);
3303 fsp
.fnum
= FNUM_FIELD_INVALID
;
3306 if (get_current_uid(conn
) != 0) {
3307 DEBUG(0,("set_user_quota: access_denied "
3308 "service [%s] user [%s]\n",
3309 lp_servicename(talloc_tos(), SNUM(conn
)),
3310 conn
->session_info
->unix_info
->unix_name
));
3311 return NT_STATUS_ACCESS_DENIED
;
3314 if (vfs_get_ntquota(&fsp
, SMB_USER_FS_QUOTA_TYPE
, NULL
, "as
)!=0) {
3315 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn
))));
3316 return map_nt_error_from_unix(errno
);
3321 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3322 lp_servicename(talloc_tos(), SNUM(conn
))));
3324 /* Unknown1 24 NULL bytes*/
3325 SBIG_UINT(pdata
,0,(uint64_t)0);
3326 SBIG_UINT(pdata
,8,(uint64_t)0);
3327 SBIG_UINT(pdata
,16,(uint64_t)0);
3329 /* Default Soft Quota 8 bytes */
3330 SBIG_UINT(pdata
,24,quotas
.softlim
);
3332 /* Default Hard Quota 8 bytes */
3333 SBIG_UINT(pdata
,32,quotas
.hardlim
);
3335 /* Quota flag 2 bytes */
3336 SSVAL(pdata
,40,quotas
.qflags
);
3338 /* Unknown3 6 NULL bytes */
3344 #endif /* HAVE_SYS_QUOTAS */
3345 case SMB_FS_OBJECTID_INFORMATION
:
3347 unsigned char objid
[16];
3348 struct smb_extended_info extended_info
;
3349 memcpy(pdata
,create_volume_objectid(conn
, objid
),16);
3350 samba_extended_info_version (&extended_info
);
3351 SIVAL(pdata
,16,extended_info
.samba_magic
);
3352 SIVAL(pdata
,20,extended_info
.samba_version
);
3353 SIVAL(pdata
,24,extended_info
.samba_subversion
);
3354 SBIG_UINT(pdata
,28,extended_info
.samba_gitcommitdate
);
3355 memcpy(pdata
+36,extended_info
.samba_version_string
,28);
3361 * Query the version and capabilities of the CIFS UNIX extensions
3365 case SMB_QUERY_CIFS_UNIX_INFO
:
3367 bool large_write
= lp_min_receive_file_size() &&
3368 !srv_is_signing_active(conn
->sconn
);
3369 bool large_read
= !srv_is_signing_active(conn
->sconn
);
3370 int encrypt_caps
= 0;
3372 if (!lp_unix_extensions()) {
3373 return NT_STATUS_INVALID_LEVEL
;
3376 switch (conn
->encrypt_level
) {
3377 case SMB_SIGNING_OFF
:
3380 case SMB_SIGNING_IF_REQUIRED
:
3381 case SMB_SIGNING_DEFAULT
:
3382 encrypt_caps
= CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP
;
3384 case SMB_SIGNING_REQUIRED
:
3385 encrypt_caps
= CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP
|
3386 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP
;
3387 large_write
= false;
3393 SSVAL(pdata
,0,CIFS_UNIX_MAJOR_VERSION
);
3394 SSVAL(pdata
,2,CIFS_UNIX_MINOR_VERSION
);
3396 /* We have POSIX ACLs, pathname, encryption,
3397 * large read/write, and locking capability. */
3399 SBIG_UINT(pdata
,4,((uint64_t)(
3400 CIFS_UNIX_POSIX_ACLS_CAP
|
3401 CIFS_UNIX_POSIX_PATHNAMES_CAP
|
3402 CIFS_UNIX_FCNTL_LOCKS_CAP
|
3403 CIFS_UNIX_EXTATTR_CAP
|
3404 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP
|
3406 (large_read
? CIFS_UNIX_LARGE_READ_CAP
: 0) |
3408 CIFS_UNIX_LARGE_WRITE_CAP
: 0))));
3412 case SMB_QUERY_POSIX_FS_INFO
:
3415 vfs_statvfs_struct svfs
;
3417 if (!lp_unix_extensions()) {
3418 return NT_STATUS_INVALID_LEVEL
;
3421 rc
= SMB_VFS_STATVFS(conn
, ".", &svfs
);
3425 SIVAL(pdata
,0,svfs
.OptimalTransferSize
);
3426 SIVAL(pdata
,4,svfs
.BlockSize
);
3427 SBIG_UINT(pdata
,8,svfs
.TotalBlocks
);
3428 SBIG_UINT(pdata
,16,svfs
.BlocksAvail
);
3429 SBIG_UINT(pdata
,24,svfs
.UserBlocksAvail
);
3430 SBIG_UINT(pdata
,32,svfs
.TotalFileNodes
);
3431 SBIG_UINT(pdata
,40,svfs
.FreeFileNodes
);
3432 SBIG_UINT(pdata
,48,svfs
.FsIdentifier
);
3433 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3435 } else if (rc
== EOPNOTSUPP
) {
3436 return NT_STATUS_INVALID_LEVEL
;
3437 #endif /* EOPNOTSUPP */
3439 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn
))));
3440 return NT_STATUS_DOS(ERRSRV
, ERRerror
);
3445 case SMB_QUERY_POSIX_WHOAMI
:
3451 if (!lp_unix_extensions()) {
3452 return NT_STATUS_INVALID_LEVEL
;
3455 if (max_data_bytes
< 40) {
3456 return NT_STATUS_BUFFER_TOO_SMALL
;
3459 if (security_session_user_level(conn
->session_info
, NULL
) < SECURITY_USER
) {
3460 flags
|= SMB_WHOAMI_GUEST
;
3463 /* NOTE: 8 bytes for UID/GID, irrespective of native
3464 * platform size. This matches
3465 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3467 data_len
= 4 /* flags */
3474 + 4 /* pad/reserved */
3475 + (conn
->session_info
->unix_token
->ngroups
* 8)
3477 + (conn
->session_info
->security_token
->num_sids
*
3481 SIVAL(pdata
, 0, flags
);
3482 SIVAL(pdata
, 4, SMB_WHOAMI_MASK
);
3484 (uint64_t)conn
->session_info
->unix_token
->uid
);
3485 SBIG_UINT(pdata
, 16,
3486 (uint64_t)conn
->session_info
->unix_token
->gid
);
3489 if (data_len
>= max_data_bytes
) {
3490 /* Potential overflow, skip the GIDs and SIDs. */
3492 SIVAL(pdata
, 24, 0); /* num_groups */
3493 SIVAL(pdata
, 28, 0); /* num_sids */
3494 SIVAL(pdata
, 32, 0); /* num_sid_bytes */
3495 SIVAL(pdata
, 36, 0); /* reserved */
3501 SIVAL(pdata
, 24, conn
->session_info
->unix_token
->ngroups
);
3502 SIVAL(pdata
, 28, conn
->session_info
->security_token
->num_sids
);
3504 /* We walk the SID list twice, but this call is fairly
3505 * infrequent, and I don't expect that it's performance
3506 * sensitive -- jpeach
3508 for (i
= 0, sid_bytes
= 0;
3509 i
< conn
->session_info
->security_token
->num_sids
; ++i
) {
3510 sid_bytes
+= ndr_size_dom_sid(
3511 &conn
->session_info
->security_token
->sids
[i
],
3515 /* SID list byte count */
3516 SIVAL(pdata
, 32, sid_bytes
);
3518 /* 4 bytes pad/reserved - must be zero */
3519 SIVAL(pdata
, 36, 0);
3523 for (i
= 0; i
< conn
->session_info
->unix_token
->ngroups
; ++i
) {
3524 SBIG_UINT(pdata
, data_len
,
3525 (uint64_t)conn
->session_info
->unix_token
->groups
[i
]);
3531 i
< conn
->session_info
->security_token
->num_sids
; ++i
) {
3532 int sid_len
= ndr_size_dom_sid(
3533 &conn
->session_info
->security_token
->sids
[i
],
3536 sid_linearize(pdata
+ data_len
, sid_len
,
3537 &conn
->session_info
->security_token
->sids
[i
]);
3538 data_len
+= sid_len
;
3544 case SMB_MAC_QUERY_FS_INFO
:
3546 * Thursby MAC extension... ONLY on NTFS filesystems
3547 * once we do streams then we don't need this
3549 if (strequal(lp_fstype(talloc_tos(), SNUM(conn
)),"NTFS")) {
3551 SIVAL(pdata
,84,0x100); /* Don't support mac... */
3556 return NT_STATUS_INVALID_LEVEL
;
3559 *ret_data_len
= data_len
;
3560 return NT_STATUS_OK
;
3563 /****************************************************************************
3564 Reply to a TRANS2_QFSINFO (query filesystem info).
3565 ****************************************************************************/
3567 static void call_trans2qfsinfo(connection_struct
*conn
,
3568 struct smb_request
*req
,
3569 char **pparams
, int total_params
,
3570 char **ppdata
, int total_data
,
3571 unsigned int max_data_bytes
)
3573 char *params
= *pparams
;
3574 uint16_t info_level
;
3578 if (total_params
< 2) {
3579 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3583 info_level
= SVAL(params
,0);
3585 if (ENCRYPTION_REQUIRED(conn
) && !req
->encrypted
) {
3586 if (info_level
!= SMB_QUERY_CIFS_UNIX_INFO
) {
3587 DEBUG(0,("call_trans2qfsinfo: encryption required "
3588 "and info level 0x%x sent.\n",
3589 (unsigned int)info_level
));
3590 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3595 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level
));
3597 status
= smbd_do_qfsinfo(conn
, req
,
3602 if (!NT_STATUS_IS_OK(status
)) {
3603 reply_nterror(req
, status
);
3607 send_trans2_replies(conn
, req
, params
, 0, *ppdata
, data_len
,
3610 DEBUG( 4, ( "%s info_level = %d\n",
3611 smb_fn_name(req
->cmd
), info_level
) );
3616 /****************************************************************************
3617 Reply to a TRANS2_SETFSINFO (set filesystem info).
3618 ****************************************************************************/
3620 static void call_trans2setfsinfo(connection_struct
*conn
,
3621 struct smb_request
*req
,
3622 char **pparams
, int total_params
,
3623 char **ppdata
, int total_data
,
3624 unsigned int max_data_bytes
)
3626 struct smbd_server_connection
*sconn
= req
->sconn
;
3627 char *pdata
= *ppdata
;
3628 char *params
= *pparams
;
3631 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",
3632 lp_servicename(talloc_tos(), SNUM(conn
))));
3635 if (total_params
< 4) {
3636 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3638 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3642 info_level
= SVAL(params
,2);
3645 if (info_level
!= SMB_REQUEST_TRANSPORT_ENCRYPTION
&&
3646 info_level
!= SMB_SET_CIFS_UNIX_INFO
) {
3647 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3648 "info level (0x%x) on IPC$.\n",
3649 (unsigned int)info_level
));
3650 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3655 if (ENCRYPTION_REQUIRED(conn
) && !req
->encrypted
) {
3656 if (info_level
!= SMB_REQUEST_TRANSPORT_ENCRYPTION
) {
3657 DEBUG(0,("call_trans2setfsinfo: encryption required "
3658 "and info level 0x%x sent.\n",
3659 (unsigned int)info_level
));
3660 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3665 switch(info_level
) {
3666 case SMB_SET_CIFS_UNIX_INFO
:
3667 if (!lp_unix_extensions()) {
3668 DEBUG(2,("call_trans2setfsinfo: "
3669 "SMB_SET_CIFS_UNIX_INFO is invalid with "
3670 "unix extensions off\n"));
3672 NT_STATUS_INVALID_LEVEL
);
3676 /* There should be 12 bytes of capabilities set. */
3677 if (total_data
< 12) {
3680 NT_STATUS_INVALID_PARAMETER
);
3683 sconn
->smb1
.unix_info
.client_major
= SVAL(pdata
,0);
3684 sconn
->smb1
.unix_info
.client_minor
= SVAL(pdata
,2);
3685 sconn
->smb1
.unix_info
.client_cap_low
= IVAL(pdata
,4);
3686 sconn
->smb1
.unix_info
.client_cap_high
= IVAL(pdata
,8);
3687 /* Just print these values for now. */
3688 DEBUG(10, ("call_trans2setfsinfo: set unix_info info. "
3689 "major = %u, minor = %u cap_low = 0x%x, "
3691 (unsigned int)sconn
->
3692 smb1
.unix_info
.client_major
,
3693 (unsigned int)sconn
->
3694 smb1
.unix_info
.client_minor
,
3695 (unsigned int)sconn
->
3696 smb1
.unix_info
.client_cap_low
,
3697 (unsigned int)sconn
->
3698 smb1
.unix_info
.client_cap_high
));
3700 /* Here is where we must switch to posix pathname processing... */
3701 if (sconn
->smb1
.unix_info
.client_cap_low
& CIFS_UNIX_POSIX_PATHNAMES_CAP
) {
3702 lp_set_posix_pathnames();
3703 mangle_change_to_posix();
3706 if ((sconn
->smb1
.unix_info
.client_cap_low
& CIFS_UNIX_FCNTL_LOCKS_CAP
) &&
3707 !(sconn
->smb1
.unix_info
.client_cap_low
& CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP
)) {
3708 /* Client that knows how to do posix locks,
3709 * but not posix open/mkdir operations. Set a
3710 * default type for read/write checks. */
3712 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK
);
3717 case SMB_REQUEST_TRANSPORT_ENCRYPTION
:
3720 size_t param_len
= 0;
3721 size_t data_len
= total_data
;
3723 if (!lp_unix_extensions()) {
3726 NT_STATUS_INVALID_LEVEL
);
3730 if (lp_smb_encrypt(SNUM(conn
)) == SMB_SIGNING_OFF
) {
3733 NT_STATUS_NOT_SUPPORTED
);
3737 if (req
->sconn
->smb1
.echo_handler
.trusted_fde
) {
3738 DEBUG( 2,("call_trans2setfsinfo: "
3739 "request transport encryption disabled"
3740 "with 'fork echo handler = yes'\n"));
3743 NT_STATUS_NOT_SUPPORTED
);
3747 DEBUG( 4,("call_trans2setfsinfo: "
3748 "request transport encryption.\n"));
3750 status
= srv_request_encryption_setup(conn
,
3751 (unsigned char **)ppdata
,
3753 (unsigned char **)pparams
,
3756 if (!NT_STATUS_EQUAL(status
, NT_STATUS_MORE_PROCESSING_REQUIRED
) &&
3757 !NT_STATUS_IS_OK(status
)) {
3758 reply_nterror(req
, status
);
3762 send_trans2_replies(conn
, req
,
3769 if (NT_STATUS_IS_OK(status
)) {
3770 /* Server-side transport
3771 * encryption is now *on*. */
3772 status
= srv_encryption_start(conn
);
3773 if (!NT_STATUS_IS_OK(status
)) {
3774 char *reason
= talloc_asprintf(talloc_tos(),
3775 "Failure in setting "
3776 "up encrypted transport: %s",
3778 exit_server_cleanly(reason
);
3784 case SMB_FS_QUOTA_INFORMATION
:
3786 files_struct
*fsp
= NULL
;
3787 SMB_NTQUOTA_STRUCT quotas
;
3789 ZERO_STRUCT(quotas
);
3792 if ((get_current_uid(conn
) != 0) || !CAN_WRITE(conn
)) {
3793 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3794 lp_servicename(talloc_tos(), SNUM(conn
)),
3795 conn
->session_info
->unix_info
->unix_name
));
3796 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3800 /* note: normaly there're 48 bytes,
3801 * but we didn't use the last 6 bytes for now
3804 fsp
= file_fsp(req
, SVAL(params
,0));
3806 if (!check_fsp_ntquota_handle(conn
, req
,
3808 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3810 req
, NT_STATUS_INVALID_HANDLE
);
3814 if (total_data
< 42) {
3815 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3819 NT_STATUS_INVALID_PARAMETER
);
3823 /* unknown_1 24 NULL bytes in pdata*/
3825 /* the soft quotas 8 bytes (uint64_t)*/
3826 quotas
.softlim
= BVAL(pdata
,24);
3828 /* the hard quotas 8 bytes (uint64_t)*/
3829 quotas
.hardlim
= BVAL(pdata
,32);
3831 /* quota_flags 2 bytes **/
3832 quotas
.qflags
= SVAL(pdata
,40);
3834 /* unknown_2 6 NULL bytes follow*/
3836 /* now set the quotas */
3837 if (vfs_set_ntquota(fsp
, SMB_USER_FS_QUOTA_TYPE
, NULL
, "as
)!=0) {
3838 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn
))));
3839 reply_nterror(req
, map_nt_error_from_unix(errno
));
3846 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3848 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
3854 * sending this reply works fine,
3855 * but I'm not sure it's the same
3856 * like windows do...
3859 reply_outbuf(req
, 10, 0);
3862 #if defined(HAVE_POSIX_ACLS)
3863 /****************************************************************************
3864 Utility function to count the number of entries in a POSIX acl.
3865 ****************************************************************************/
3867 static unsigned int count_acl_entries(connection_struct
*conn
, SMB_ACL_T posix_acl
)
3869 unsigned int ace_count
= 0;
3870 int entry_id
= SMB_ACL_FIRST_ENTRY
;
3871 SMB_ACL_ENTRY_T entry
;
3873 while ( posix_acl
&& (sys_acl_get_entry(posix_acl
, entry_id
, &entry
) == 1)) {
3875 if (entry_id
== SMB_ACL_FIRST_ENTRY
) {
3876 entry_id
= SMB_ACL_NEXT_ENTRY
;
3883 /****************************************************************************
3884 Utility function to marshall a POSIX acl into wire format.
3885 ****************************************************************************/
3887 static bool marshall_posix_acl(connection_struct
*conn
, char *pdata
, SMB_STRUCT_STAT
*pst
, SMB_ACL_T posix_acl
)
3889 int entry_id
= SMB_ACL_FIRST_ENTRY
;
3890 SMB_ACL_ENTRY_T entry
;
3892 while ( posix_acl
&& (sys_acl_get_entry(posix_acl
, entry_id
, &entry
) == 1)) {
3893 SMB_ACL_TAG_T tagtype
;
3894 SMB_ACL_PERMSET_T permset
;
3895 unsigned char perms
= 0;
3896 unsigned int own_grp
;
3899 if (entry_id
== SMB_ACL_FIRST_ENTRY
) {
3900 entry_id
= SMB_ACL_NEXT_ENTRY
;
3903 if (sys_acl_get_tag_type(entry
, &tagtype
) == -1) {
3904 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3908 if (sys_acl_get_permset(entry
, &permset
) == -1) {
3909 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3913 perms
|= (sys_acl_get_perm(permset
, SMB_ACL_READ
) ? SMB_POSIX_ACL_READ
: 0);
3914 perms
|= (sys_acl_get_perm(permset
, SMB_ACL_WRITE
) ? SMB_POSIX_ACL_WRITE
: 0);
3915 perms
|= (sys_acl_get_perm(permset
, SMB_ACL_EXECUTE
) ? SMB_POSIX_ACL_EXECUTE
: 0);
3917 SCVAL(pdata
,1,perms
);
3920 case SMB_ACL_USER_OBJ
:
3921 SCVAL(pdata
,0,SMB_POSIX_ACL_USER_OBJ
);
3922 own_grp
= (unsigned int)pst
->st_ex_uid
;
3923 SIVAL(pdata
,2,own_grp
);
3928 uid_t
*puid
= (uid_t
*)sys_acl_get_qualifier(entry
);
3930 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3933 own_grp
= (unsigned int)*puid
;
3934 SCVAL(pdata
,0,SMB_POSIX_ACL_USER
);
3935 SIVAL(pdata
,2,own_grp
);
3939 case SMB_ACL_GROUP_OBJ
:
3940 SCVAL(pdata
,0,SMB_POSIX_ACL_GROUP_OBJ
);
3941 own_grp
= (unsigned int)pst
->st_ex_gid
;
3942 SIVAL(pdata
,2,own_grp
);
3947 gid_t
*pgid
= (gid_t
*)sys_acl_get_qualifier(entry
);
3949 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3952 own_grp
= (unsigned int)*pgid
;
3953 SCVAL(pdata
,0,SMB_POSIX_ACL_GROUP
);
3954 SIVAL(pdata
,2,own_grp
);
3959 SCVAL(pdata
,0,SMB_POSIX_ACL_MASK
);
3960 SIVAL(pdata
,2,0xFFFFFFFF);
3961 SIVAL(pdata
,6,0xFFFFFFFF);
3964 SCVAL(pdata
,0,SMB_POSIX_ACL_OTHER
);
3965 SIVAL(pdata
,2,0xFFFFFFFF);
3966 SIVAL(pdata
,6,0xFFFFFFFF);
3969 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3972 pdata
+= SMB_POSIX_ACL_ENTRY_SIZE
;
3979 /****************************************************************************
3980 Store the FILE_UNIX_BASIC info.
3981 ****************************************************************************/
3983 static char *store_file_unix_basic(connection_struct
*conn
,
3986 const SMB_STRUCT_STAT
*psbuf
)
3988 uint64_t file_index
= get_FileIndex(conn
, psbuf
);
3991 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3992 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf
->st_ex_mode
));
3994 SOFF_T(pdata
,0,get_file_size_stat(psbuf
)); /* File size 64 Bit */
3997 SOFF_T(pdata
,0,SMB_VFS_GET_ALLOC_SIZE(conn
,fsp
,psbuf
)); /* Number of bytes used on disk - 64 Bit */
4000 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER
, pdata
, psbuf
->st_ex_ctime
); /* Change Time 64 Bit */
4001 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER
,pdata
+8, psbuf
->st_ex_atime
); /* Last access time 64 Bit */
4002 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER
, pdata
+16, psbuf
->st_ex_mtime
); /* Last modification time 64 Bit */
4005 SIVAL(pdata
,0,psbuf
->st_ex_uid
); /* user id for the owner */
4009 SIVAL(pdata
,0,psbuf
->st_ex_gid
); /* group id of owner */
4013 SIVAL(pdata
,0,unix_filetype(psbuf
->st_ex_mode
));
4016 if (S_ISBLK(psbuf
->st_ex_mode
) || S_ISCHR(psbuf
->st_ex_mode
)) {
4017 devno
= psbuf
->st_ex_rdev
;
4019 devno
= psbuf
->st_ex_dev
;
4022 SIVAL(pdata
,0,unix_dev_major(devno
)); /* Major device number if type is device */
4026 SIVAL(pdata
,0,unix_dev_minor(devno
)); /* Minor device number if type is device */
4030 SINO_T_VAL(pdata
,0,(SMB_INO_T
)file_index
); /* inode number */
4033 SIVAL(pdata
,0, unix_perms_to_wire(psbuf
->st_ex_mode
)); /* Standard UNIX file permissions */
4037 SIVAL(pdata
,0,psbuf
->st_ex_nlink
); /* number of hard links */
4044 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
4045 * the chflags(2) (or equivalent) flags.
4047 * XXX: this really should be behind the VFS interface. To do this, we would
4048 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
4049 * Each VFS module could then implement its own mapping as appropriate for the
4050 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
4052 static const struct {unsigned stat_fflag
; unsigned smb_fflag
;}
4056 { UF_NODUMP
, EXT_DO_NOT_BACKUP
},
4060 { UF_IMMUTABLE
, EXT_IMMUTABLE
},
4064 { UF_APPEND
, EXT_OPEN_APPEND_ONLY
},
4068 { UF_HIDDEN
, EXT_HIDDEN
},
4071 /* Do not remove. We need to guarantee that this array has at least one
4072 * entry to build on HP-UX.
4078 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT
*psbuf
,
4079 uint32
*smb_fflags
, uint32
*smb_fmask
)
4083 for (i
= 0; i
< ARRAY_SIZE(info2_flags_map
); ++i
) {
4084 *smb_fmask
|= info2_flags_map
[i
].smb_fflag
;
4085 if (psbuf
->st_ex_flags
& info2_flags_map
[i
].stat_fflag
) {
4086 *smb_fflags
|= info2_flags_map
[i
].smb_fflag
;
4091 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT
*psbuf
,
4092 const uint32 smb_fflags
,
4093 const uint32 smb_fmask
,
4096 uint32 max_fmask
= 0;
4099 *stat_fflags
= psbuf
->st_ex_flags
;
4101 /* For each flags requested in smb_fmask, check the state of the
4102 * corresponding flag in smb_fflags and set or clear the matching
4106 for (i
= 0; i
< ARRAY_SIZE(info2_flags_map
); ++i
) {
4107 max_fmask
|= info2_flags_map
[i
].smb_fflag
;
4108 if (smb_fmask
& info2_flags_map
[i
].smb_fflag
) {
4109 if (smb_fflags
& info2_flags_map
[i
].smb_fflag
) {
4110 *stat_fflags
|= info2_flags_map
[i
].stat_fflag
;
4112 *stat_fflags
&= ~info2_flags_map
[i
].stat_fflag
;
4117 /* If smb_fmask is asking to set any bits that are not supported by
4118 * our flag mappings, we should fail.
4120 if ((smb_fmask
& max_fmask
) != smb_fmask
) {
4128 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
4129 * of file flags and birth (create) time.
4131 static char *store_file_unix_basic_info2(connection_struct
*conn
,
4134 const SMB_STRUCT_STAT
*psbuf
)
4136 uint32 file_flags
= 0;
4137 uint32 flags_mask
= 0;
4139 pdata
= store_file_unix_basic(conn
, pdata
, fsp
, psbuf
);
4141 /* Create (birth) time 64 bit */
4142 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER
,pdata
, psbuf
->st_ex_btime
);
4145 map_info2_flags_from_sbuf(psbuf
, &file_flags
, &flags_mask
);
4146 SIVAL(pdata
, 0, file_flags
); /* flags */
4147 SIVAL(pdata
, 4, flags_mask
); /* mask */
4153 static NTSTATUS
marshall_stream_info(unsigned int num_streams
,
4154 const struct stream_struct
*streams
,
4156 unsigned int max_data_bytes
,
4157 unsigned int *data_size
)
4160 unsigned int ofs
= 0;
4162 for (i
= 0; i
< num_streams
&& ofs
<= max_data_bytes
; i
++) {
4163 unsigned int next_offset
;
4165 smb_ucs2_t
*namebuf
;
4167 if (!push_ucs2_talloc(talloc_tos(), &namebuf
,
4168 streams
[i
].name
, &namelen
) ||
4171 return NT_STATUS_INVALID_PARAMETER
;
4175 * name_buf is now null-terminated, we need to marshall as not
4181 SIVAL(data
, ofs
+4, namelen
);
4182 SOFF_T(data
, ofs
+8, streams
[i
].size
);
4183 SOFF_T(data
, ofs
+16, streams
[i
].alloc_size
);
4184 memcpy(data
+ofs
+24, namebuf
, namelen
);
4185 TALLOC_FREE(namebuf
);
4187 next_offset
= ofs
+ 24 + namelen
;
4189 if (i
== num_streams
-1) {
4190 SIVAL(data
, ofs
, 0);
4193 unsigned int align
= ndr_align_size(next_offset
, 8);
4195 memset(data
+next_offset
, 0, align
);
4196 next_offset
+= align
;
4198 SIVAL(data
, ofs
, next_offset
- ofs
);
4207 return NT_STATUS_OK
;
4210 /****************************************************************************
4211 Reply to a TRANSACT2_QFILEINFO on a PIPE !
4212 ****************************************************************************/
4214 static void call_trans2qpipeinfo(connection_struct
*conn
,
4215 struct smb_request
*req
,
4216 unsigned int tran_call
,
4217 char **pparams
, int total_params
,
4218 char **ppdata
, int total_data
,
4219 unsigned int max_data_bytes
)
4221 char *params
= *pparams
;
4222 char *pdata
= *ppdata
;
4223 unsigned int data_size
= 0;
4224 unsigned int param_size
= 2;
4229 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4233 if (total_params
< 4) {
4234 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4238 fsp
= file_fsp(req
, SVAL(params
,0));
4239 if (!fsp_is_np(fsp
)) {
4240 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
4244 info_level
= SVAL(params
,2);
4246 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
4247 if (*pparams
== NULL
) {
4248 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
4253 data_size
= max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
;
4254 *ppdata
= (char *)SMB_REALLOC(*ppdata
, data_size
);
4255 if (*ppdata
== NULL
) {
4256 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
4261 switch (info_level
) {
4262 case SMB_FILE_STANDARD_INFORMATION
:
4264 SOFF_T(pdata
,0,4096LL);
4271 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
4275 send_trans2_replies(conn
, req
, params
, param_size
, *ppdata
, data_size
,
4281 NTSTATUS
smbd_do_qfilepathinfo(connection_struct
*conn
,
4282 TALLOC_CTX
*mem_ctx
,
4283 uint16_t info_level
,
4285 struct smb_filename
*smb_fname
,
4286 bool delete_pending
,
4287 struct timespec write_time_ts
,
4288 struct ea_list
*ea_list
,
4289 int lock_data_count
,
4292 unsigned int max_data_bytes
,
4294 unsigned int *pdata_size
)
4296 char *pdata
= *ppdata
;
4297 char *dstart
, *dend
;
4298 unsigned int data_size
;
4299 struct timespec create_time_ts
, mtime_ts
, atime_ts
, ctime_ts
;
4300 time_t create_time
, mtime
, atime
, c_time
;
4301 SMB_STRUCT_STAT
*psbuf
= &smb_fname
->st
;
4308 uint64_t file_size
= 0;
4310 uint64_t allocation_size
= 0;
4311 uint64_t file_index
= 0;
4312 uint32_t access_mask
= 0;
4314 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
4315 return NT_STATUS_INVALID_LEVEL
;
4318 DEBUG(5,("smbd_do_qfilepathinfo: %s (%s) level=%d max_data=%u\n",
4319 smb_fname_str_dbg(smb_fname
),
4321 info_level
, max_data_bytes
));
4323 mode
= dos_mode(conn
, smb_fname
);
4324 nlink
= psbuf
->st_ex_nlink
;
4326 if (nlink
&& (mode
&FILE_ATTRIBUTE_DIRECTORY
)) {
4330 if ((nlink
> 0) && delete_pending
) {
4334 data_size
= max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
;
4335 *ppdata
= (char *)SMB_REALLOC(*ppdata
, data_size
);
4336 if (*ppdata
== NULL
) {
4337 return NT_STATUS_NO_MEMORY
;
4341 dend
= dstart
+ data_size
- 1;
4343 if (!null_timespec(write_time_ts
) && !INFO_LEVEL_IS_UNIX(info_level
)) {
4344 update_stat_ex_mtime(psbuf
, write_time_ts
);
4347 create_time_ts
= get_create_timespec(conn
, fsp
, smb_fname
);
4348 mtime_ts
= psbuf
->st_ex_mtime
;
4349 atime_ts
= psbuf
->st_ex_atime
;
4350 ctime_ts
= get_change_timespec(conn
, fsp
, smb_fname
);
4352 if (lp_dos_filetime_resolution(SNUM(conn
))) {
4353 dos_filetime_timespec(&create_time_ts
);
4354 dos_filetime_timespec(&mtime_ts
);
4355 dos_filetime_timespec(&atime_ts
);
4356 dos_filetime_timespec(&ctime_ts
);
4359 create_time
= convert_timespec_to_time_t(create_time_ts
);
4360 mtime
= convert_timespec_to_time_t(mtime_ts
);
4361 atime
= convert_timespec_to_time_t(atime_ts
);
4362 c_time
= convert_timespec_to_time_t(ctime_ts
);
4364 p
= strrchr_m(smb_fname
->base_name
,'/');
4366 base_name
= smb_fname
->base_name
;
4370 /* NT expects the name to be in an exact form of the *full*
4371 filename. See the trans2 torture test */
4372 if (ISDOT(base_name
)) {
4373 dos_fname
= talloc_strdup(mem_ctx
, "\\");
4375 return NT_STATUS_NO_MEMORY
;
4378 dos_fname
= talloc_asprintf(mem_ctx
,
4380 smb_fname
->base_name
);
4382 return NT_STATUS_NO_MEMORY
;
4384 if (is_ntfs_stream_smb_fname(smb_fname
)) {
4385 dos_fname
= talloc_asprintf(dos_fname
, "%s",
4386 smb_fname
->stream_name
);
4388 return NT_STATUS_NO_MEMORY
;
4392 string_replace(dos_fname
, '/', '\\');
4395 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
, fsp
, psbuf
);
4398 /* Do we have this path open ? */
4400 struct file_id fileid
= vfs_file_id_from_sbuf(conn
, psbuf
);
4401 fsp1
= file_find_di_first(conn
->sconn
, fileid
);
4402 if (fsp1
&& fsp1
->initial_allocation_size
) {
4403 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
, fsp1
, psbuf
);
4407 if (!(mode
& FILE_ATTRIBUTE_DIRECTORY
)) {
4408 file_size
= get_file_size_stat(psbuf
);
4412 pos
= fsp
->fh
->position_information
;
4416 access_mask
= fsp
->access_mask
;
4418 /* GENERIC_EXECUTE mapping from Windows */
4419 access_mask
= 0x12019F;
4422 /* This should be an index number - looks like
4425 I think this causes us to fail the IFSKIT
4426 BasicFileInformationTest. -tpot */
4427 file_index
= get_FileIndex(conn
, psbuf
);
4429 switch (info_level
) {
4430 case SMB_INFO_STANDARD
:
4431 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4433 srv_put_dos_date2(pdata
,l1_fdateCreation
,create_time
);
4434 srv_put_dos_date2(pdata
,l1_fdateLastAccess
,atime
);
4435 srv_put_dos_date2(pdata
,l1_fdateLastWrite
,mtime
); /* write time */
4436 SIVAL(pdata
,l1_cbFile
,(uint32
)file_size
);
4437 SIVAL(pdata
,l1_cbFileAlloc
,(uint32
)allocation_size
);
4438 SSVAL(pdata
,l1_attrFile
,mode
);
4441 case SMB_INFO_QUERY_EA_SIZE
:
4443 unsigned int ea_size
=
4444 estimate_ea_size(conn
, fsp
,
4446 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4448 srv_put_dos_date2(pdata
,0,create_time
);
4449 srv_put_dos_date2(pdata
,4,atime
);
4450 srv_put_dos_date2(pdata
,8,mtime
); /* write time */
4451 SIVAL(pdata
,12,(uint32
)file_size
);
4452 SIVAL(pdata
,16,(uint32
)allocation_size
);
4453 SSVAL(pdata
,20,mode
);
4454 SIVAL(pdata
,22,ea_size
);
4458 case SMB_INFO_IS_NAME_VALID
:
4459 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4461 /* os/2 needs this ? really ?*/
4462 return NT_STATUS_DOS(ERRDOS
, ERRbadfunc
);
4464 /* This is only reached for qpathinfo */
4468 case SMB_INFO_QUERY_EAS_FROM_LIST
:
4470 size_t total_ea_len
= 0;
4471 struct ea_list
*ea_file_list
= NULL
;
4472 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4475 get_ea_list_from_file(mem_ctx
, conn
, fsp
,
4477 &total_ea_len
, &ea_file_list
);
4478 if (!NT_STATUS_IS_OK(status
)) {
4482 ea_list
= ea_list_union(ea_list
, ea_file_list
, &total_ea_len
);
4484 if (!ea_list
|| (total_ea_len
> data_size
)) {
4486 SIVAL(pdata
,0,4); /* EA List Length must be set to 4 if no EA's. */
4490 data_size
= fill_ea_buffer(mem_ctx
, pdata
, data_size
, conn
, ea_list
);
4494 case SMB_INFO_QUERY_ALL_EAS
:
4496 /* We have data_size bytes to put EA's into. */
4497 size_t total_ea_len
= 0;
4498 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4500 status
= get_ea_list_from_file(mem_ctx
, conn
, fsp
,
4502 &total_ea_len
, &ea_list
);
4503 if (!NT_STATUS_IS_OK(status
)) {
4507 if (!ea_list
|| (total_ea_len
> data_size
)) {
4509 SIVAL(pdata
,0,4); /* EA List Length must be set to 4 if no EA's. */
4513 data_size
= fill_ea_buffer(mem_ctx
, pdata
, data_size
, conn
, ea_list
);
4517 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
4519 /* This is FileFullEaInformation - 0xF which maps to
4520 * 1015 (decimal) in smbd_do_setfilepathinfo. */
4522 /* We have data_size bytes to put EA's into. */
4523 size_t total_ea_len
= 0;
4524 struct ea_list
*ea_file_list
= NULL
;
4526 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
4528 /*TODO: add filtering and index handling */
4531 get_ea_list_from_file(mem_ctx
, conn
, fsp
,
4533 &total_ea_len
, &ea_file_list
);
4534 if (!NT_STATUS_IS_OK(status
)) {
4537 if (!ea_file_list
) {
4538 return NT_STATUS_NO_EAS_ON_FILE
;
4541 status
= fill_ea_chained_buffer(mem_ctx
,
4545 conn
, ea_file_list
);
4546 if (!NT_STATUS_IS_OK(status
)) {
4552 case SMB_FILE_BASIC_INFORMATION
:
4553 case SMB_QUERY_FILE_BASIC_INFO
:
4555 if (info_level
== SMB_QUERY_FILE_BASIC_INFO
) {
4556 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4557 data_size
= 36; /* w95 returns 40 bytes not 36 - why ?. */
4559 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4563 put_long_date_timespec(conn
->ts_res
,pdata
,create_time_ts
);
4564 put_long_date_timespec(conn
->ts_res
,pdata
+8,atime_ts
);
4565 put_long_date_timespec(conn
->ts_res
,pdata
+16,mtime_ts
); /* write time */
4566 put_long_date_timespec(conn
->ts_res
,pdata
+24,ctime_ts
); /* change time */
4567 SIVAL(pdata
,32,mode
);
4569 DEBUG(5,("SMB_QFBI - "));
4570 DEBUG(5,("create: %s ", ctime(&create_time
)));
4571 DEBUG(5,("access: %s ", ctime(&atime
)));
4572 DEBUG(5,("write: %s ", ctime(&mtime
)));
4573 DEBUG(5,("change: %s ", ctime(&c_time
)));
4574 DEBUG(5,("mode: %x\n", mode
));
4577 case SMB_FILE_STANDARD_INFORMATION
:
4578 case SMB_QUERY_FILE_STANDARD_INFO
:
4580 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4582 SOFF_T(pdata
,0,allocation_size
);
4583 SOFF_T(pdata
,8,file_size
);
4584 SIVAL(pdata
,16,nlink
);
4585 SCVAL(pdata
,20,delete_pending
?1:0);
4586 SCVAL(pdata
,21,(mode
&FILE_ATTRIBUTE_DIRECTORY
)?1:0);
4587 SSVAL(pdata
,22,0); /* Padding. */
4590 case SMB_FILE_EA_INFORMATION
:
4591 case SMB_QUERY_FILE_EA_INFO
:
4593 unsigned int ea_size
=
4594 estimate_ea_size(conn
, fsp
, smb_fname
);
4595 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4597 SIVAL(pdata
,0,ea_size
);
4601 /* Get the 8.3 name - used if NT SMB was negotiated. */
4602 case SMB_QUERY_FILE_ALT_NAME_INFO
:
4603 case SMB_FILE_ALTERNATE_NAME_INFORMATION
:
4606 char mangled_name
[13];
4607 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4608 if (!name_to_8_3(base_name
,mangled_name
,
4609 True
,conn
->params
)) {
4610 return NT_STATUS_NO_MEMORY
;
4612 len
= srvstr_push(dstart
, flags2
,
4613 pdata
+4, mangled_name
,
4614 PTR_DIFF(dend
, pdata
+4),
4616 data_size
= 4 + len
;
4621 case SMB_QUERY_FILE_NAME_INFO
:
4625 this must be *exactly* right for ACLs on mapped drives to work
4627 len
= srvstr_push(dstart
, flags2
,
4629 PTR_DIFF(dend
, pdata
+4),
4631 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4632 data_size
= 4 + len
;
4637 case SMB_FILE_ALLOCATION_INFORMATION
:
4638 case SMB_QUERY_FILE_ALLOCATION_INFO
:
4639 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4641 SOFF_T(pdata
,0,allocation_size
);
4644 case SMB_FILE_END_OF_FILE_INFORMATION
:
4645 case SMB_QUERY_FILE_END_OF_FILEINFO
:
4646 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4648 SOFF_T(pdata
,0,file_size
);
4651 case SMB_QUERY_FILE_ALL_INFO
:
4652 case SMB_FILE_ALL_INFORMATION
:
4655 unsigned int ea_size
=
4656 estimate_ea_size(conn
, fsp
, smb_fname
);
4657 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4658 put_long_date_timespec(conn
->ts_res
,pdata
,create_time_ts
);
4659 put_long_date_timespec(conn
->ts_res
,pdata
+8,atime_ts
);
4660 put_long_date_timespec(conn
->ts_res
,pdata
+16,mtime_ts
); /* write time */
4661 put_long_date_timespec(conn
->ts_res
,pdata
+24,ctime_ts
); /* change time */
4662 SIVAL(pdata
,32,mode
);
4663 SIVAL(pdata
,36,0); /* padding. */
4665 SOFF_T(pdata
,0,allocation_size
);
4666 SOFF_T(pdata
,8,file_size
);
4667 SIVAL(pdata
,16,nlink
);
4668 SCVAL(pdata
,20,delete_pending
);
4669 SCVAL(pdata
,21,(mode
&FILE_ATTRIBUTE_DIRECTORY
)?1:0);
4672 SIVAL(pdata
,0,ea_size
);
4673 pdata
+= 4; /* EA info */
4674 len
= srvstr_push(dstart
, flags2
,
4676 PTR_DIFF(dend
, pdata
+4),
4680 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4684 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
4687 unsigned int ea_size
=
4688 estimate_ea_size(conn
, fsp
, smb_fname
);
4689 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
4690 put_long_date_timespec(conn
->ts_res
,pdata
+0x00,create_time_ts
);
4691 put_long_date_timespec(conn
->ts_res
,pdata
+0x08,atime_ts
);
4692 put_long_date_timespec(conn
->ts_res
,pdata
+0x10,mtime_ts
); /* write time */
4693 put_long_date_timespec(conn
->ts_res
,pdata
+0x18,ctime_ts
); /* change time */
4694 SIVAL(pdata
, 0x20, mode
);
4695 SIVAL(pdata
, 0x24, 0); /* padding. */
4696 SBVAL(pdata
, 0x28, allocation_size
);
4697 SBVAL(pdata
, 0x30, file_size
);
4698 SIVAL(pdata
, 0x38, nlink
);
4699 SCVAL(pdata
, 0x3C, delete_pending
);
4700 SCVAL(pdata
, 0x3D, (mode
&FILE_ATTRIBUTE_DIRECTORY
)?1:0);
4701 SSVAL(pdata
, 0x3E, 0); /* padding */
4702 SBVAL(pdata
, 0x40, file_index
);
4703 SIVAL(pdata
, 0x48, ea_size
);
4704 SIVAL(pdata
, 0x4C, access_mask
);
4705 SBVAL(pdata
, 0x50, pos
);
4706 SIVAL(pdata
, 0x58, mode
); /*TODO: mode != mode fix this!!! */
4707 SIVAL(pdata
, 0x5C, 0); /* No alignment needed. */
4711 len
= srvstr_push(dstart
, flags2
,
4713 PTR_DIFF(dend
, pdata
+4),
4717 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4720 case SMB_FILE_INTERNAL_INFORMATION
:
4722 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4723 SBVAL(pdata
, 0, file_index
);
4727 case SMB_FILE_ACCESS_INFORMATION
:
4728 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4729 SIVAL(pdata
, 0, access_mask
);
4733 case SMB_FILE_NAME_INFORMATION
:
4734 /* Pathname with leading '\'. */
4737 byte_len
= dos_PutUniCode(pdata
+4,dos_fname
,(size_t)max_data_bytes
,False
);
4738 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4739 SIVAL(pdata
,0,byte_len
);
4740 data_size
= 4 + byte_len
;
4744 case SMB_FILE_DISPOSITION_INFORMATION
:
4745 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4747 SCVAL(pdata
,0,delete_pending
);
4750 case SMB_FILE_POSITION_INFORMATION
:
4751 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4753 SOFF_T(pdata
,0,pos
);
4756 case SMB_FILE_MODE_INFORMATION
:
4757 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4758 SIVAL(pdata
,0,mode
);
4762 case SMB_FILE_ALIGNMENT_INFORMATION
:
4763 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4764 SIVAL(pdata
,0,0); /* No alignment needed. */
4769 * NT4 server just returns "invalid query" to this - if we try
4770 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4773 /* The first statement above is false - verified using Thursby
4774 * client against NT4 -- gcolley.
4776 case SMB_QUERY_FILE_STREAM_INFO
:
4777 case SMB_FILE_STREAM_INFORMATION
: {
4778 unsigned int num_streams
= 0;
4779 struct stream_struct
*streams
= NULL
;
4781 DEBUG(10,("smbd_do_qfilepathinfo: "
4782 "SMB_FILE_STREAM_INFORMATION\n"));
4784 if (is_ntfs_stream_smb_fname(smb_fname
)) {
4785 return NT_STATUS_INVALID_PARAMETER
;
4788 status
= vfs_streaminfo(conn
, fsp
, smb_fname
->base_name
,
4789 talloc_tos(), &num_streams
, &streams
);
4791 if (!NT_STATUS_IS_OK(status
)) {
4792 DEBUG(10, ("could not get stream info: %s\n",
4793 nt_errstr(status
)));
4797 status
= marshall_stream_info(num_streams
, streams
,
4798 pdata
, max_data_bytes
,
4801 if (!NT_STATUS_IS_OK(status
)) {
4802 DEBUG(10, ("marshall_stream_info failed: %s\n",
4803 nt_errstr(status
)));
4807 TALLOC_FREE(streams
);
4811 case SMB_QUERY_COMPRESSION_INFO
:
4812 case SMB_FILE_COMPRESSION_INFORMATION
:
4813 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4814 SOFF_T(pdata
,0,file_size
);
4815 SIVAL(pdata
,8,0); /* ??? */
4816 SIVAL(pdata
,12,0); /* ??? */
4820 case SMB_FILE_NETWORK_OPEN_INFORMATION
:
4821 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4822 put_long_date_timespec(conn
->ts_res
,pdata
,create_time_ts
);
4823 put_long_date_timespec(conn
->ts_res
,pdata
+8,atime_ts
);
4824 put_long_date_timespec(conn
->ts_res
,pdata
+16,mtime_ts
); /* write time */
4825 put_long_date_timespec(conn
->ts_res
,pdata
+24,ctime_ts
); /* change time */
4826 SOFF_T(pdata
,32,allocation_size
);
4827 SOFF_T(pdata
,40,file_size
);
4828 SIVAL(pdata
,48,mode
);
4829 SIVAL(pdata
,52,0); /* ??? */
4833 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION
:
4834 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4835 SIVAL(pdata
,0,mode
);
4841 * CIFS UNIX Extensions.
4844 case SMB_QUERY_FILE_UNIX_BASIC
:
4846 pdata
= store_file_unix_basic(conn
, pdata
, fsp
, psbuf
);
4847 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4849 DEBUG(4,("smbd_do_qfilepathinfo: "
4850 "SMB_QUERY_FILE_UNIX_BASIC\n"));
4851 dump_data(4, (uint8_t *)(*ppdata
), data_size
);
4855 case SMB_QUERY_FILE_UNIX_INFO2
:
4857 pdata
= store_file_unix_basic_info2(conn
, pdata
, fsp
, psbuf
);
4858 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4862 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4864 for (i
=0; i
<100; i
++)
4865 DEBUG(4,("%d=%x, ",i
, (*ppdata
)[i
]));
4871 case SMB_QUERY_FILE_UNIX_LINK
:
4874 char *buffer
= talloc_array(mem_ctx
, char, PATH_MAX
+1);
4877 return NT_STATUS_NO_MEMORY
;
4880 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4882 if(!S_ISLNK(psbuf
->st_ex_mode
)) {
4883 return NT_STATUS_DOS(ERRSRV
, ERRbadlink
);
4886 return NT_STATUS_DOS(ERRDOS
, ERRbadlink
);
4888 len
= SMB_VFS_READLINK(conn
,
4889 smb_fname
->base_name
,
4892 return map_nt_error_from_unix(errno
);
4895 len
= srvstr_push(dstart
, flags2
,
4897 PTR_DIFF(dend
, pdata
),
4900 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4905 #if defined(HAVE_POSIX_ACLS)
4906 case SMB_QUERY_POSIX_ACL
:
4908 SMB_ACL_T file_acl
= NULL
;
4909 SMB_ACL_T def_acl
= NULL
;
4910 uint16 num_file_acls
= 0;
4911 uint16 num_def_acls
= 0;
4913 if (fsp
&& fsp
->fh
->fd
!= -1) {
4914 file_acl
= SMB_VFS_SYS_ACL_GET_FD(fsp
,
4918 SMB_VFS_SYS_ACL_GET_FILE(conn
,
4919 smb_fname
->base_name
,
4920 SMB_ACL_TYPE_ACCESS
,
4924 if (file_acl
== NULL
&& no_acl_syscall_error(errno
)) {
4925 DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
4926 "not implemented on "
4927 "filesystem containing %s\n",
4928 smb_fname
->base_name
));
4929 return NT_STATUS_NOT_IMPLEMENTED
;
4932 if (S_ISDIR(psbuf
->st_ex_mode
)) {
4933 if (fsp
&& fsp
->is_directory
) {
4935 SMB_VFS_SYS_ACL_GET_FILE(
4937 fsp
->fsp_name
->base_name
,
4938 SMB_ACL_TYPE_DEFAULT
,
4942 SMB_VFS_SYS_ACL_GET_FILE(
4944 smb_fname
->base_name
,
4945 SMB_ACL_TYPE_DEFAULT
,
4948 def_acl
= free_empty_sys_acl(conn
, def_acl
);
4951 num_file_acls
= count_acl_entries(conn
, file_acl
);
4952 num_def_acls
= count_acl_entries(conn
, def_acl
);
4954 if ( data_size
< (num_file_acls
+ num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
+ SMB_POSIX_ACL_HEADER_SIZE
) {
4955 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
4957 (unsigned int)((num_file_acls
+ num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
+
4958 SMB_POSIX_ACL_HEADER_SIZE
) ));
4960 TALLOC_FREE(file_acl
);
4963 TALLOC_FREE(def_acl
);
4965 return NT_STATUS_BUFFER_TOO_SMALL
;
4968 SSVAL(pdata
,0,SMB_POSIX_ACL_VERSION
);
4969 SSVAL(pdata
,2,num_file_acls
);
4970 SSVAL(pdata
,4,num_def_acls
);
4971 if (!marshall_posix_acl(conn
, pdata
+ SMB_POSIX_ACL_HEADER_SIZE
, psbuf
, file_acl
)) {
4973 TALLOC_FREE(file_acl
);
4976 TALLOC_FREE(def_acl
);
4978 return NT_STATUS_INTERNAL_ERROR
;
4980 if (!marshall_posix_acl(conn
, pdata
+ SMB_POSIX_ACL_HEADER_SIZE
+ (num_file_acls
*SMB_POSIX_ACL_ENTRY_SIZE
), psbuf
, def_acl
)) {
4982 TALLOC_FREE(file_acl
);
4985 TALLOC_FREE(def_acl
);
4987 return NT_STATUS_INTERNAL_ERROR
;
4991 TALLOC_FREE(file_acl
);
4994 TALLOC_FREE(def_acl
);
4996 data_size
= (num_file_acls
+ num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
+ SMB_POSIX_ACL_HEADER_SIZE
;
5002 case SMB_QUERY_POSIX_LOCK
:
5007 enum brl_type lock_type
;
5009 /* We need an open file with a real fd for this. */
5010 if (!fsp
|| fsp
->fh
->fd
== -1) {
5011 return NT_STATUS_INVALID_LEVEL
;
5014 if (lock_data_count
!= POSIX_LOCK_DATA_SIZE
) {
5015 return NT_STATUS_INVALID_PARAMETER
;
5018 switch (SVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
)) {
5019 case POSIX_LOCK_TYPE_READ
:
5020 lock_type
= READ_LOCK
;
5022 case POSIX_LOCK_TYPE_WRITE
:
5023 lock_type
= WRITE_LOCK
;
5025 case POSIX_LOCK_TYPE_UNLOCK
:
5027 /* There's no point in asking for an unlock... */
5028 return NT_STATUS_INVALID_PARAMETER
;
5031 smblctx
= (uint64_t)IVAL(pdata
, POSIX_LOCK_PID_OFFSET
);
5032 #if defined(HAVE_LONGLONG)
5033 offset
= (((uint64_t) IVAL(pdata
,(POSIX_LOCK_START_OFFSET
+4))) << 32) |
5034 ((uint64_t) IVAL(pdata
,POSIX_LOCK_START_OFFSET
));
5035 count
= (((uint64_t) IVAL(pdata
,(POSIX_LOCK_LEN_OFFSET
+4))) << 32) |
5036 ((uint64_t) IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
));
5037 #else /* HAVE_LONGLONG */
5038 offset
= (uint64_t)IVAL(pdata
,POSIX_LOCK_START_OFFSET
);
5039 count
= (uint64_t)IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
);
5040 #endif /* HAVE_LONGLONG */
5042 status
= query_lock(fsp
,
5049 if (ERROR_WAS_LOCK_DENIED(status
)) {
5050 /* Here we need to report who has it locked... */
5051 data_size
= POSIX_LOCK_DATA_SIZE
;
5053 SSVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
, lock_type
);
5054 SSVAL(pdata
, POSIX_LOCK_FLAGS_OFFSET
, 0);
5055 SIVAL(pdata
, POSIX_LOCK_PID_OFFSET
, (uint32_t)smblctx
);
5056 #if defined(HAVE_LONGLONG)
5057 SIVAL(pdata
, POSIX_LOCK_START_OFFSET
, (uint32
)(offset
& 0xFFFFFFFF));
5058 SIVAL(pdata
, POSIX_LOCK_START_OFFSET
+ 4, (uint32
)((offset
>> 32) & 0xFFFFFFFF));
5059 SIVAL(pdata
, POSIX_LOCK_LEN_OFFSET
, (uint32
)(count
& 0xFFFFFFFF));
5060 SIVAL(pdata
, POSIX_LOCK_LEN_OFFSET
+ 4, (uint32
)((count
>> 32) & 0xFFFFFFFF));
5061 #else /* HAVE_LONGLONG */
5062 SIVAL(pdata
, POSIX_LOCK_START_OFFSET
, offset
);
5063 SIVAL(pdata
, POSIX_LOCK_LEN_OFFSET
, count
);
5064 #endif /* HAVE_LONGLONG */
5066 } else if (NT_STATUS_IS_OK(status
)) {
5067 /* For success we just return a copy of what we sent
5068 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
5069 data_size
= POSIX_LOCK_DATA_SIZE
;
5070 memcpy(pdata
, lock_data
, POSIX_LOCK_DATA_SIZE
);
5071 SSVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
, POSIX_LOCK_TYPE_UNLOCK
);
5079 return NT_STATUS_INVALID_LEVEL
;
5082 *pdata_size
= data_size
;
5083 return NT_STATUS_OK
;
5086 /****************************************************************************
5087 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
5088 file name or file id).
5089 ****************************************************************************/
5091 static void call_trans2qfilepathinfo(connection_struct
*conn
,
5092 struct smb_request
*req
,
5093 unsigned int tran_call
,
5094 char **pparams
, int total_params
,
5095 char **ppdata
, int total_data
,
5096 unsigned int max_data_bytes
)
5098 char *params
= *pparams
;
5099 char *pdata
= *ppdata
;
5101 unsigned int data_size
= 0;
5102 unsigned int param_size
= 2;
5103 struct smb_filename
*smb_fname
= NULL
;
5104 bool delete_pending
= False
;
5105 struct timespec write_time_ts
;
5106 files_struct
*fsp
= NULL
;
5107 struct file_id fileid
;
5108 struct ea_list
*ea_list
= NULL
;
5109 int lock_data_count
= 0;
5110 char *lock_data
= NULL
;
5111 NTSTATUS status
= NT_STATUS_OK
;
5114 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5118 ZERO_STRUCT(write_time_ts
);
5120 if (tran_call
== TRANSACT2_QFILEINFO
) {
5121 if (total_params
< 4) {
5122 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5127 call_trans2qpipeinfo(conn
, req
, tran_call
,
5128 pparams
, total_params
,
5134 fsp
= file_fsp(req
, SVAL(params
,0));
5135 info_level
= SVAL(params
,2);
5137 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level
));
5139 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
5140 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
5144 /* Initial check for valid fsp ptr. */
5145 if (!check_fsp_open(conn
, req
, fsp
)) {
5149 status
= copy_smb_filename(talloc_tos(), fsp
->fsp_name
,
5151 if (!NT_STATUS_IS_OK(status
)) {
5152 reply_nterror(req
, status
);
5156 if(fsp
->fake_file_handle
) {
5158 * This is actually for the QUOTA_FAKE_FILE --metze
5161 /* We know this name is ok, it's already passed the checks. */
5163 } else if(fsp
->fh
->fd
== -1) {
5165 * This is actually a QFILEINFO on a directory
5166 * handle (returned from an NT SMB). NT5.0 seems
5167 * to do this call. JRA.
5170 if (INFO_LEVEL_IS_UNIX(info_level
)) {
5171 /* Always do lstat for UNIX calls. */
5172 if (SMB_VFS_LSTAT(conn
, smb_fname
)) {
5173 DEBUG(3,("call_trans2qfilepathinfo: "
5174 "SMB_VFS_LSTAT of %s failed "
5176 smb_fname_str_dbg(smb_fname
),
5179 map_nt_error_from_unix(errno
));
5182 } else if (SMB_VFS_STAT(conn
, smb_fname
)) {
5183 DEBUG(3,("call_trans2qfilepathinfo: "
5184 "SMB_VFS_STAT of %s failed (%s)\n",
5185 smb_fname_str_dbg(smb_fname
),
5188 map_nt_error_from_unix(errno
));
5192 fileid
= vfs_file_id_from_sbuf(conn
, &smb_fname
->st
);
5193 get_file_infos(fileid
, fsp
->name_hash
, &delete_pending
, &write_time_ts
);
5196 * Original code - this is an open file.
5198 if (SMB_VFS_FSTAT(fsp
, &smb_fname
->st
) != 0) {
5199 DEBUG(3, ("fstat of %s failed (%s)\n",
5200 fsp_fnum_dbg(fsp
), strerror(errno
)));
5202 map_nt_error_from_unix(errno
));
5205 fileid
= vfs_file_id_from_sbuf(conn
, &smb_fname
->st
);
5206 get_file_infos(fileid
, fsp
->name_hash
, &delete_pending
, &write_time_ts
);
5212 uint32_t ucf_flags
= 0;
5215 if (total_params
< 7) {
5216 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5220 info_level
= SVAL(params
,0);
5222 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level
));
5224 if (INFO_LEVEL_IS_UNIX(info_level
)) {
5225 if (!lp_unix_extensions()) {
5226 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
5229 if (info_level
== SMB_QUERY_FILE_UNIX_BASIC
||
5230 info_level
== SMB_QUERY_FILE_UNIX_INFO2
||
5231 info_level
== SMB_QUERY_FILE_UNIX_LINK
) {
5232 ucf_flags
|= UCF_UNIX_NAME_LOOKUP
;
5236 srvstr_get_path(req
, params
, req
->flags2
, &fname
, ¶ms
[6],
5238 STR_TERMINATE
, &status
);
5239 if (!NT_STATUS_IS_OK(status
)) {
5240 reply_nterror(req
, status
);
5244 status
= filename_convert(req
,
5246 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
5251 if (!NT_STATUS_IS_OK(status
)) {
5252 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
5253 reply_botherror(req
,
5254 NT_STATUS_PATH_NOT_COVERED
,
5255 ERRSRV
, ERRbadpath
);
5258 reply_nterror(req
, status
);
5262 /* If this is a stream, check if there is a delete_pending. */
5263 if ((conn
->fs_capabilities
& FILE_NAMED_STREAMS
)
5264 && is_ntfs_stream_smb_fname(smb_fname
)) {
5265 struct smb_filename
*smb_fname_base
= NULL
;
5267 /* Create an smb_filename with stream_name == NULL. */
5269 create_synthetic_smb_fname(talloc_tos(),
5270 smb_fname
->base_name
,
5273 if (!NT_STATUS_IS_OK(status
)) {
5274 reply_nterror(req
, status
);
5278 if (INFO_LEVEL_IS_UNIX(info_level
)) {
5279 /* Always do lstat for UNIX calls. */
5280 if (SMB_VFS_LSTAT(conn
, smb_fname_base
) != 0) {
5281 DEBUG(3,("call_trans2qfilepathinfo: "
5282 "SMB_VFS_LSTAT of %s failed "
5284 smb_fname_str_dbg(smb_fname_base
),
5286 TALLOC_FREE(smb_fname_base
);
5288 map_nt_error_from_unix(errno
));
5292 if (SMB_VFS_STAT(conn
, smb_fname_base
) != 0) {
5293 DEBUG(3,("call_trans2qfilepathinfo: "
5294 "fileinfo of %s failed "
5296 smb_fname_str_dbg(smb_fname_base
),
5298 TALLOC_FREE(smb_fname_base
);
5300 map_nt_error_from_unix(errno
));
5305 status
= file_name_hash(conn
,
5306 smb_fname_str_dbg(smb_fname_base
),
5308 if (!NT_STATUS_IS_OK(status
)) {
5309 TALLOC_FREE(smb_fname_base
);
5310 reply_nterror(req
, status
);
5314 fileid
= vfs_file_id_from_sbuf(conn
,
5315 &smb_fname_base
->st
);
5316 TALLOC_FREE(smb_fname_base
);
5317 get_file_infos(fileid
, name_hash
, &delete_pending
, NULL
);
5318 if (delete_pending
) {
5319 reply_nterror(req
, NT_STATUS_DELETE_PENDING
);
5324 if (INFO_LEVEL_IS_UNIX(info_level
)) {
5325 /* Always do lstat for UNIX calls. */
5326 if (SMB_VFS_LSTAT(conn
, smb_fname
)) {
5327 DEBUG(3,("call_trans2qfilepathinfo: "
5328 "SMB_VFS_LSTAT of %s failed (%s)\n",
5329 smb_fname_str_dbg(smb_fname
),
5332 map_nt_error_from_unix(errno
));
5337 if (SMB_VFS_STAT(conn
, smb_fname
) != 0) {
5338 DEBUG(3,("call_trans2qfilepathinfo: "
5339 "SMB_VFS_STAT of %s failed (%s)\n",
5340 smb_fname_str_dbg(smb_fname
),
5343 map_nt_error_from_unix(errno
));
5348 status
= file_name_hash(conn
,
5349 smb_fname_str_dbg(smb_fname
),
5351 if (!NT_STATUS_IS_OK(status
)) {
5352 reply_nterror(req
, status
);
5356 fileid
= vfs_file_id_from_sbuf(conn
, &smb_fname
->st
);
5357 get_file_infos(fileid
, name_hash
, &delete_pending
, &write_time_ts
);
5358 if (delete_pending
) {
5359 reply_nterror(req
, NT_STATUS_DELETE_PENDING
);
5364 DEBUG(3,("call_trans2qfilepathinfo %s (%s) level=%d call=%d "
5365 "total_data=%d\n", smb_fname_str_dbg(smb_fname
),
5367 info_level
,tran_call
,total_data
));
5369 /* Pull out any data sent here before we realloc. */
5370 switch (info_level
) {
5371 case SMB_INFO_QUERY_EAS_FROM_LIST
:
5373 /* Pull any EA list from the data portion. */
5376 if (total_data
< 4) {
5378 req
, NT_STATUS_INVALID_PARAMETER
);
5381 ea_size
= IVAL(pdata
,0);
5383 if (total_data
> 0 && ea_size
!= total_data
) {
5384 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5385 total_data=%u (should be %u)\n", (unsigned int)total_data
, (unsigned int)IVAL(pdata
,0) ));
5387 req
, NT_STATUS_INVALID_PARAMETER
);
5391 if (!lp_ea_support(SNUM(conn
))) {
5392 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
5396 /* Pull out the list of names. */
5397 ea_list
= read_ea_name_list(req
, pdata
+ 4, ea_size
- 4);
5400 req
, NT_STATUS_INVALID_PARAMETER
);
5406 case SMB_QUERY_POSIX_LOCK
:
5408 if (fsp
== NULL
|| fsp
->fh
->fd
== -1) {
5409 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
5413 if (total_data
!= POSIX_LOCK_DATA_SIZE
) {
5415 req
, NT_STATUS_INVALID_PARAMETER
);
5419 /* Copy the lock range data. */
5420 lock_data
= (char *)talloc_memdup(
5421 req
, pdata
, total_data
);
5423 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5426 lock_data_count
= total_data
;
5432 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
5433 if (*pparams
== NULL
) {
5434 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5441 * draft-leach-cifs-v1-spec-02.txt
5442 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
5445 * The requested information is placed in the Data portion of the
5446 * transaction response. For the information levels greater than 0x100,
5447 * the transaction response has 1 parameter word which should be
5448 * ignored by the client.
5450 * However Windows only follows this rule for the IS_NAME_VALID call.
5452 switch (info_level
) {
5453 case SMB_INFO_IS_NAME_VALID
:
5458 if ((info_level
& 0xFF00) == 0xFF00) {
5460 * We use levels that start with 0xFF00
5461 * internally to represent SMB2 specific levels
5463 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
5467 status
= smbd_do_qfilepathinfo(conn
, req
, info_level
,
5469 delete_pending
, write_time_ts
,
5471 lock_data_count
, lock_data
,
5472 req
->flags2
, max_data_bytes
,
5473 ppdata
, &data_size
);
5474 if (!NT_STATUS_IS_OK(status
)) {
5475 reply_nterror(req
, status
);
5479 send_trans2_replies(conn
, req
, params
, param_size
, *ppdata
, data_size
,
5485 /****************************************************************************
5486 Set a hard link (called by UNIX extensions and by NT rename with HARD link
5488 ****************************************************************************/
5490 NTSTATUS
hardlink_internals(TALLOC_CTX
*ctx
,
5491 connection_struct
*conn
,
5492 struct smb_request
*req
,
5493 bool overwrite_if_exists
,
5494 const struct smb_filename
*smb_fname_old
,
5495 struct smb_filename
*smb_fname_new
)
5497 NTSTATUS status
= NT_STATUS_OK
;
5499 /* source must already exist. */
5500 if (!VALID_STAT(smb_fname_old
->st
)) {
5501 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5504 if (VALID_STAT(smb_fname_new
->st
)) {
5505 if (overwrite_if_exists
) {
5506 if (S_ISDIR(smb_fname_new
->st
.st_ex_mode
)) {
5507 return NT_STATUS_FILE_IS_A_DIRECTORY
;
5509 status
= unlink_internals(conn
,
5511 FILE_ATTRIBUTE_NORMAL
,
5514 if (!NT_STATUS_IS_OK(status
)) {
5518 /* Disallow if newname already exists. */
5519 return NT_STATUS_OBJECT_NAME_COLLISION
;
5523 /* No links from a directory. */
5524 if (S_ISDIR(smb_fname_old
->st
.st_ex_mode
)) {
5525 return NT_STATUS_FILE_IS_A_DIRECTORY
;
5528 /* Setting a hardlink to/from a stream isn't currently supported. */
5529 if (is_ntfs_stream_smb_fname(smb_fname_old
) ||
5530 is_ntfs_stream_smb_fname(smb_fname_new
)) {
5531 return NT_STATUS_INVALID_PARAMETER
;
5534 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
5535 smb_fname_old
->base_name
, smb_fname_new
->base_name
));
5537 if (SMB_VFS_LINK(conn
, smb_fname_old
->base_name
,
5538 smb_fname_new
->base_name
) != 0) {
5539 status
= map_nt_error_from_unix(errno
);
5540 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
5541 nt_errstr(status
), smb_fname_old
->base_name
,
5542 smb_fname_new
->base_name
));
5547 /****************************************************************************
5548 Deal with setting the time from any of the setfilepathinfo functions.
5549 NOTE !!!! The check for FILE_WRITE_ATTRIBUTES access must be done *before*
5550 calling this function.
5551 ****************************************************************************/
5553 NTSTATUS
smb_set_file_time(connection_struct
*conn
,
5555 const struct smb_filename
*smb_fname
,
5556 struct smb_file_time
*ft
,
5557 bool setting_write_time
)
5559 struct smb_filename smb_fname_base
;
5561 FILE_NOTIFY_CHANGE_LAST_ACCESS
5562 |FILE_NOTIFY_CHANGE_LAST_WRITE
5563 |FILE_NOTIFY_CHANGE_CREATION
;
5565 if (!VALID_STAT(smb_fname
->st
)) {
5566 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5569 /* get some defaults (no modifications) if any info is zero or -1. */
5570 if (null_timespec(ft
->create_time
)) {
5571 action
&= ~FILE_NOTIFY_CHANGE_CREATION
;
5574 if (null_timespec(ft
->atime
)) {
5575 action
&= ~FILE_NOTIFY_CHANGE_LAST_ACCESS
;
5578 if (null_timespec(ft
->mtime
)) {
5579 action
&= ~FILE_NOTIFY_CHANGE_LAST_WRITE
;
5582 if (!setting_write_time
) {
5583 /* ft->mtime comes from change time, not write time. */
5584 action
&= ~FILE_NOTIFY_CHANGE_LAST_WRITE
;
5587 /* Ensure the resolution is the correct for
5588 * what we can store on this filesystem. */
5590 round_timespec(conn
->ts_res
, &ft
->create_time
);
5591 round_timespec(conn
->ts_res
, &ft
->ctime
);
5592 round_timespec(conn
->ts_res
, &ft
->atime
);
5593 round_timespec(conn
->ts_res
, &ft
->mtime
);
5595 DEBUG(5,("smb_set_filetime: actime: %s\n ",
5596 time_to_asc(convert_timespec_to_time_t(ft
->atime
))));
5597 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
5598 time_to_asc(convert_timespec_to_time_t(ft
->mtime
))));
5599 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
5600 time_to_asc(convert_timespec_to_time_t(ft
->ctime
))));
5601 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
5602 time_to_asc(convert_timespec_to_time_t(ft
->create_time
))));
5604 if (setting_write_time
) {
5606 * This was a Windows setfileinfo on an open file.
5607 * NT does this a lot. We also need to
5608 * set the time here, as it can be read by
5609 * FindFirst/FindNext and with the patch for bug #2045
5610 * in smbd/fileio.c it ensures that this timestamp is
5611 * kept sticky even after a write. We save the request
5612 * away and will set it on file close and after a write. JRA.
5615 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
5616 time_to_asc(convert_timespec_to_time_t(ft
->mtime
))));
5619 if (fsp
->base_fsp
) {
5620 set_sticky_write_time_fsp(fsp
->base_fsp
,
5623 set_sticky_write_time_fsp(fsp
, ft
->mtime
);
5626 set_sticky_write_time_path(
5627 vfs_file_id_from_sbuf(conn
, &smb_fname
->st
),
5632 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5634 /* Always call ntimes on the base, even if a stream was passed in. */
5635 smb_fname_base
= *smb_fname
;
5636 smb_fname_base
.stream_name
= NULL
;
5638 if(file_ntimes(conn
, &smb_fname_base
, ft
)!=0) {
5639 return map_nt_error_from_unix(errno
);
5642 notify_fname(conn
, NOTIFY_ACTION_MODIFIED
, action
,
5643 smb_fname
->base_name
);
5644 return NT_STATUS_OK
;
5647 /****************************************************************************
5648 Deal with setting the dosmode from any of the setfilepathinfo functions.
5649 NB. The check for FILE_WRITE_ATTRIBUTES access on this path must have been
5650 done before calling this function.
5651 ****************************************************************************/
5653 static NTSTATUS
smb_set_file_dosmode(connection_struct
*conn
,
5654 const struct smb_filename
*smb_fname
,
5657 struct smb_filename
*smb_fname_base
= NULL
;
5660 if (!VALID_STAT(smb_fname
->st
)) {
5661 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5664 /* Always operate on the base_name, even if a stream was passed in. */
5665 status
= create_synthetic_smb_fname(talloc_tos(), smb_fname
->base_name
,
5666 NULL
, &smb_fname
->st
,
5668 if (!NT_STATUS_IS_OK(status
)) {
5673 if (S_ISDIR(smb_fname_base
->st
.st_ex_mode
)) {
5674 dosmode
|= FILE_ATTRIBUTE_DIRECTORY
;
5676 dosmode
&= ~FILE_ATTRIBUTE_DIRECTORY
;
5680 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode
));
5682 /* check the mode isn't different, before changing it */
5683 if ((dosmode
!= 0) && (dosmode
!= dos_mode(conn
, smb_fname_base
))) {
5684 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
5685 "0x%x\n", smb_fname_str_dbg(smb_fname_base
),
5686 (unsigned int)dosmode
));
5688 if(file_set_dosmode(conn
, smb_fname_base
, dosmode
, NULL
,
5690 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
5692 smb_fname_str_dbg(smb_fname_base
),
5694 status
= map_nt_error_from_unix(errno
);
5698 status
= NT_STATUS_OK
;
5700 TALLOC_FREE(smb_fname_base
);
5704 /****************************************************************************
5705 Deal with setting the size from any of the setfilepathinfo functions.
5706 ****************************************************************************/
5708 static NTSTATUS
smb_set_file_size(connection_struct
*conn
,
5709 struct smb_request
*req
,
5711 const struct smb_filename
*smb_fname
,
5712 const SMB_STRUCT_STAT
*psbuf
,
5714 bool fail_after_createfile
)
5716 NTSTATUS status
= NT_STATUS_OK
;
5717 struct smb_filename
*smb_fname_tmp
= NULL
;
5718 files_struct
*new_fsp
= NULL
;
5720 if (!VALID_STAT(*psbuf
)) {
5721 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5724 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size
));
5726 if (size
== get_file_size_stat(psbuf
)) {
5727 return NT_STATUS_OK
;
5730 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5731 smb_fname_str_dbg(smb_fname
), (double)size
));
5733 if (fsp
&& fsp
->fh
->fd
!= -1) {
5734 /* Handle based call. */
5735 if (!(fsp
->access_mask
& FILE_WRITE_DATA
)) {
5736 return NT_STATUS_ACCESS_DENIED
;
5739 if (vfs_set_filelen(fsp
, size
) == -1) {
5740 return map_nt_error_from_unix(errno
);
5742 trigger_write_time_update_immediate(fsp
);
5743 return NT_STATUS_OK
;
5746 status
= copy_smb_filename(talloc_tos(), smb_fname
, &smb_fname_tmp
);
5747 if (!NT_STATUS_IS_OK(status
)) {
5751 smb_fname_tmp
->st
= *psbuf
;
5753 status
= SMB_VFS_CREATE_FILE(
5756 0, /* root_dir_fid */
5757 smb_fname_tmp
, /* fname */
5758 FILE_WRITE_DATA
, /* access_mask */
5759 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
5761 FILE_OPEN
, /* create_disposition*/
5762 0, /* create_options */
5763 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
5764 FORCE_OPLOCK_BREAK_TO_NONE
, /* oplock_request */
5765 0, /* allocation_size */
5766 0, /* private_flags */
5769 &new_fsp
, /* result */
5772 TALLOC_FREE(smb_fname_tmp
);
5774 if (!NT_STATUS_IS_OK(status
)) {
5775 /* NB. We check for open_was_deferred in the caller. */
5779 /* See RAW-SFILEINFO-END-OF-FILE */
5780 if (fail_after_createfile
) {
5781 close_file(req
, new_fsp
,NORMAL_CLOSE
);
5782 return NT_STATUS_INVALID_LEVEL
;
5785 if (vfs_set_filelen(new_fsp
, size
) == -1) {
5786 status
= map_nt_error_from_unix(errno
);
5787 close_file(req
, new_fsp
,NORMAL_CLOSE
);
5791 trigger_write_time_update_immediate(new_fsp
);
5792 close_file(req
, new_fsp
,NORMAL_CLOSE
);
5793 return NT_STATUS_OK
;
5796 /****************************************************************************
5797 Deal with SMB_INFO_SET_EA.
5798 ****************************************************************************/
5800 static NTSTATUS
smb_info_set_ea(connection_struct
*conn
,
5804 const struct smb_filename
*smb_fname
)
5806 struct ea_list
*ea_list
= NULL
;
5807 TALLOC_CTX
*ctx
= NULL
;
5808 NTSTATUS status
= NT_STATUS_OK
;
5810 if (total_data
< 10) {
5812 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5813 length. They seem to have no effect. Bug #3212. JRA */
5815 if ((total_data
== 4) && (IVAL(pdata
,0) == 4)) {
5816 /* We're done. We only get EA info in this call. */
5817 return NT_STATUS_OK
;
5820 return NT_STATUS_INVALID_PARAMETER
;
5823 if (IVAL(pdata
,0) > total_data
) {
5824 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5825 IVAL(pdata
,0), (unsigned int)total_data
));
5826 return NT_STATUS_INVALID_PARAMETER
;
5830 ea_list
= read_ea_list(ctx
, pdata
+ 4, total_data
- 4);
5832 return NT_STATUS_INVALID_PARAMETER
;
5835 status
= set_ea(conn
, fsp
, smb_fname
, ea_list
);
5840 /****************************************************************************
5841 Deal with SMB_FILE_FULL_EA_INFORMATION set.
5842 ****************************************************************************/
5844 static NTSTATUS
smb_set_file_full_ea_info(connection_struct
*conn
,
5849 struct ea_list
*ea_list
= NULL
;
5853 return NT_STATUS_INVALID_HANDLE
;
5856 if (!lp_ea_support(SNUM(conn
))) {
5857 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
5858 "EA's not supported.\n",
5859 (unsigned int)total_data
));
5860 return NT_STATUS_EAS_NOT_SUPPORTED
;
5863 if (total_data
< 10) {
5864 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
5866 (unsigned int)total_data
));
5867 return NT_STATUS_INVALID_PARAMETER
;
5870 ea_list
= read_nttrans_ea_list(talloc_tos(),
5875 return NT_STATUS_INVALID_PARAMETER
;
5878 status
= set_ea(conn
, fsp
, fsp
->fsp_name
, ea_list
);
5880 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
5881 smb_fname_str_dbg(fsp
->fsp_name
),
5882 nt_errstr(status
) ));
5888 /****************************************************************************
5889 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5890 ****************************************************************************/
5892 static NTSTATUS
smb_set_file_disposition_info(connection_struct
*conn
,
5896 struct smb_filename
*smb_fname
)
5898 NTSTATUS status
= NT_STATUS_OK
;
5899 bool delete_on_close
;
5902 if (total_data
< 1) {
5903 return NT_STATUS_INVALID_PARAMETER
;
5907 return NT_STATUS_INVALID_HANDLE
;
5910 delete_on_close
= (CVAL(pdata
,0) ? True
: False
);
5911 dosmode
= dos_mode(conn
, smb_fname
);
5913 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5914 "delete_on_close = %u\n",
5915 smb_fname_str_dbg(smb_fname
),
5916 (unsigned int)dosmode
,
5917 (unsigned int)delete_on_close
));
5919 if (delete_on_close
) {
5920 status
= can_set_delete_on_close(fsp
, dosmode
);
5921 if (!NT_STATUS_IS_OK(status
)) {
5926 /* The set is across all open files on this dev/inode pair. */
5927 if (!set_delete_on_close(fsp
, delete_on_close
,
5928 conn
->session_info
->security_token
,
5929 conn
->session_info
->unix_token
)) {
5930 return NT_STATUS_ACCESS_DENIED
;
5932 return NT_STATUS_OK
;
5935 /****************************************************************************
5936 Deal with SMB_FILE_POSITION_INFORMATION.
5937 ****************************************************************************/
5939 static NTSTATUS
smb_file_position_information(connection_struct
*conn
,
5944 uint64_t position_information
;
5946 if (total_data
< 8) {
5947 return NT_STATUS_INVALID_PARAMETER
;
5951 /* Ignore on pathname based set. */
5952 return NT_STATUS_OK
;
5955 position_information
= (uint64_t)IVAL(pdata
,0);
5956 position_information
|= (((uint64_t)IVAL(pdata
,4)) << 32);
5958 DEBUG(10,("smb_file_position_information: Set file position "
5959 "information for file %s to %.0f\n", fsp_str_dbg(fsp
),
5960 (double)position_information
));
5961 fsp
->fh
->position_information
= position_information
;
5962 return NT_STATUS_OK
;
5965 /****************************************************************************
5966 Deal with SMB_FILE_MODE_INFORMATION.
5967 ****************************************************************************/
5969 static NTSTATUS
smb_file_mode_information(connection_struct
*conn
,
5975 if (total_data
< 4) {
5976 return NT_STATUS_INVALID_PARAMETER
;
5978 mode
= IVAL(pdata
,0);
5979 if (mode
!= 0 && mode
!= 2 && mode
!= 4 && mode
!= 6) {
5980 return NT_STATUS_INVALID_PARAMETER
;
5982 return NT_STATUS_OK
;
5985 /****************************************************************************
5986 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
5987 ****************************************************************************/
5989 static NTSTATUS
smb_set_file_unix_link(connection_struct
*conn
,
5990 struct smb_request
*req
,
5993 const struct smb_filename
*smb_fname
)
5995 char *link_target
= NULL
;
5996 const char *newname
= smb_fname
->base_name
;
5997 TALLOC_CTX
*ctx
= talloc_tos();
5999 /* Set a symbolic link. */
6000 /* Don't allow this if follow links is false. */
6002 if (total_data
== 0) {
6003 return NT_STATUS_INVALID_PARAMETER
;
6006 if (!lp_symlinks(SNUM(conn
))) {
6007 return NT_STATUS_ACCESS_DENIED
;
6010 srvstr_pull_talloc(ctx
, pdata
, req
->flags2
, &link_target
, pdata
,
6011 total_data
, STR_TERMINATE
);
6014 return NT_STATUS_INVALID_PARAMETER
;
6017 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
6018 newname
, link_target
));
6020 if (SMB_VFS_SYMLINK(conn
,link_target
,newname
) != 0) {
6021 return map_nt_error_from_unix(errno
);
6024 return NT_STATUS_OK
;
6027 /****************************************************************************
6028 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
6029 ****************************************************************************/
6031 static NTSTATUS
smb_set_file_unix_hlink(connection_struct
*conn
,
6032 struct smb_request
*req
,
6033 const char *pdata
, int total_data
,
6034 struct smb_filename
*smb_fname_new
)
6036 char *oldname
= NULL
;
6037 struct smb_filename
*smb_fname_old
= NULL
;
6038 TALLOC_CTX
*ctx
= talloc_tos();
6039 NTSTATUS status
= NT_STATUS_OK
;
6041 /* Set a hard link. */
6042 if (total_data
== 0) {
6043 return NT_STATUS_INVALID_PARAMETER
;
6046 srvstr_get_path(ctx
, pdata
, req
->flags2
, &oldname
, pdata
,
6047 total_data
, STR_TERMINATE
, &status
);
6048 if (!NT_STATUS_IS_OK(status
)) {
6052 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
6053 smb_fname_str_dbg(smb_fname_new
), oldname
));
6055 status
= filename_convert(ctx
,
6057 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6062 if (!NT_STATUS_IS_OK(status
)) {
6066 return hardlink_internals(ctx
, conn
, req
, false,
6067 smb_fname_old
, smb_fname_new
);
6070 /****************************************************************************
6071 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
6072 ****************************************************************************/
6074 static NTSTATUS
smb2_file_rename_information(connection_struct
*conn
,
6075 struct smb_request
*req
,
6079 struct smb_filename
*smb_fname_src
)
6083 char *newname
= NULL
;
6084 struct smb_filename
*smb_fname_dst
= NULL
;
6085 NTSTATUS status
= NT_STATUS_OK
;
6086 TALLOC_CTX
*ctx
= talloc_tos();
6089 return NT_STATUS_INVALID_HANDLE
;
6092 if (total_data
< 20) {
6093 return NT_STATUS_INVALID_PARAMETER
;
6096 overwrite
= (CVAL(pdata
,0) ? True
: False
);
6097 len
= IVAL(pdata
,16);
6099 if (len
> (total_data
- 20) || (len
== 0)) {
6100 return NT_STATUS_INVALID_PARAMETER
;
6103 srvstr_get_path(ctx
, pdata
, req
->flags2
, &newname
,
6104 &pdata
[20], len
, STR_TERMINATE
,
6106 if (!NT_STATUS_IS_OK(status
)) {
6110 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
6113 status
= filename_convert(ctx
,
6115 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6120 if (!NT_STATUS_IS_OK(status
)) {
6124 if (fsp
->base_fsp
) {
6125 /* newname must be a stream name. */
6126 if (newname
[0] != ':') {
6127 return NT_STATUS_NOT_SUPPORTED
;
6130 /* Create an smb_fname to call rename_internals_fsp() with. */
6131 status
= create_synthetic_smb_fname(talloc_tos(),
6132 fsp
->base_fsp
->fsp_name
->base_name
, newname
, NULL
,
6134 if (!NT_STATUS_IS_OK(status
)) {
6139 * Set the original last component, since
6140 * rename_internals_fsp() requires it.
6142 smb_fname_dst
->original_lcomp
= talloc_strdup(smb_fname_dst
,
6144 if (smb_fname_dst
->original_lcomp
== NULL
) {
6145 status
= NT_STATUS_NO_MEMORY
;
6151 DEBUG(10,("smb2_file_rename_information: "
6152 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
6153 fsp_fnum_dbg(fsp
), fsp_str_dbg(fsp
),
6154 smb_fname_str_dbg(smb_fname_dst
)));
6155 status
= rename_internals_fsp(conn
, fsp
, smb_fname_dst
,
6156 (FILE_ATTRIBUTE_HIDDEN
|FILE_ATTRIBUTE_SYSTEM
),
6160 TALLOC_FREE(smb_fname_dst
);
6164 static NTSTATUS
smb_file_link_information(connection_struct
*conn
,
6165 struct smb_request
*req
,
6169 struct smb_filename
*smb_fname_src
)
6173 char *newname
= NULL
;
6174 struct smb_filename
*smb_fname_dst
= NULL
;
6175 NTSTATUS status
= NT_STATUS_OK
;
6176 TALLOC_CTX
*ctx
= talloc_tos();
6179 return NT_STATUS_INVALID_HANDLE
;
6182 if (total_data
< 20) {
6183 return NT_STATUS_INVALID_PARAMETER
;
6186 overwrite
= (CVAL(pdata
,0) ? true : false);
6187 len
= IVAL(pdata
,16);
6189 if (len
> (total_data
- 20) || (len
== 0)) {
6190 return NT_STATUS_INVALID_PARAMETER
;
6193 srvstr_get_path(ctx
, pdata
, req
->flags2
, &newname
,
6194 &pdata
[20], len
, STR_TERMINATE
,
6196 if (!NT_STATUS_IS_OK(status
)) {
6200 DEBUG(10,("smb_file_link_information: got name |%s|\n",
6203 status
= filename_convert(ctx
,
6205 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6210 if (!NT_STATUS_IS_OK(status
)) {
6214 if (fsp
->base_fsp
) {
6215 /* No stream names. */
6216 return NT_STATUS_NOT_SUPPORTED
;
6219 DEBUG(10,("smb_file_link_information: "
6220 "SMB_FILE_LINK_INFORMATION (%s) %s -> %s\n",
6221 fsp_fnum_dbg(fsp
), fsp_str_dbg(fsp
),
6222 smb_fname_str_dbg(smb_fname_dst
)));
6223 status
= hardlink_internals(ctx
,
6230 TALLOC_FREE(smb_fname_dst
);
6234 /****************************************************************************
6235 Deal with SMB_FILE_RENAME_INFORMATION.
6236 ****************************************************************************/
6238 static NTSTATUS
smb_file_rename_information(connection_struct
*conn
,
6239 struct smb_request
*req
,
6243 struct smb_filename
*smb_fname_src
)
6248 char *newname
= NULL
;
6249 struct smb_filename
*smb_fname_dst
= NULL
;
6250 bool dest_has_wcard
= False
;
6251 NTSTATUS status
= NT_STATUS_OK
;
6253 TALLOC_CTX
*ctx
= talloc_tos();
6255 if (total_data
< 13) {
6256 return NT_STATUS_INVALID_PARAMETER
;
6259 overwrite
= (CVAL(pdata
,0) ? True
: False
);
6260 root_fid
= IVAL(pdata
,4);
6261 len
= IVAL(pdata
,8);
6263 if (len
> (total_data
- 12) || (len
== 0) || (root_fid
!= 0)) {
6264 return NT_STATUS_INVALID_PARAMETER
;
6267 srvstr_get_path_wcard(ctx
, pdata
, req
->flags2
, &newname
, &pdata
[12],
6270 if (!NT_STATUS_IS_OK(status
)) {
6274 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
6277 status
= resolve_dfspath_wcard(ctx
, conn
,
6278 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6281 !conn
->sconn
->using_smb2
,
6284 if (!NT_STATUS_IS_OK(status
)) {
6288 /* Check the new name has no '/' characters. */
6289 if (strchr_m(newname
, '/')) {
6290 return NT_STATUS_NOT_SUPPORTED
;
6293 if (fsp
&& fsp
->base_fsp
) {
6294 /* newname must be a stream name. */
6295 if (newname
[0] != ':') {
6296 return NT_STATUS_NOT_SUPPORTED
;
6299 /* Create an smb_fname to call rename_internals_fsp() with. */
6300 status
= create_synthetic_smb_fname(talloc_tos(),
6301 fsp
->base_fsp
->fsp_name
->base_name
, newname
, NULL
,
6303 if (!NT_STATUS_IS_OK(status
)) {
6308 * Set the original last component, since
6309 * rename_internals_fsp() requires it.
6311 smb_fname_dst
->original_lcomp
= talloc_strdup(smb_fname_dst
,
6313 if (smb_fname_dst
->original_lcomp
== NULL
) {
6314 status
= NT_STATUS_NO_MEMORY
;
6320 * Build up an smb_fname_dst based on the filename passed in.
6321 * We basically just strip off the last component, and put on
6322 * the newname instead.
6324 char *base_name
= NULL
;
6326 /* newname must *not* be a stream name. */
6327 if (newname
[0] == ':') {
6328 return NT_STATUS_NOT_SUPPORTED
;
6332 * Strip off the last component (filename) of the path passed
6335 base_name
= talloc_strdup(ctx
, smb_fname_src
->base_name
);
6337 return NT_STATUS_NO_MEMORY
;
6339 p
= strrchr_m(base_name
, '/');
6343 base_name
= talloc_strdup(ctx
, "");
6345 return NT_STATUS_NO_MEMORY
;
6348 /* Append the new name. */
6349 base_name
= talloc_asprintf_append(base_name
,
6353 return NT_STATUS_NO_MEMORY
;
6356 status
= unix_convert(ctx
, conn
, base_name
, &smb_fname_dst
,
6359 UCF_ALWAYS_ALLOW_WCARD_LCOMP
:
6362 /* If an error we expect this to be
6363 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
6365 if (!NT_STATUS_IS_OK(status
)) {
6366 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND
,
6370 /* Create an smb_fname to call rename_internals_fsp() */
6371 status
= create_synthetic_smb_fname(ctx
,
6375 if (!NT_STATUS_IS_OK(status
)) {
6382 DEBUG(10,("smb_file_rename_information: "
6383 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
6384 fsp_fnum_dbg(fsp
), fsp_str_dbg(fsp
),
6385 smb_fname_str_dbg(smb_fname_dst
)));
6386 status
= rename_internals_fsp(conn
, fsp
, smb_fname_dst
, 0,
6389 DEBUG(10,("smb_file_rename_information: "
6390 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
6391 smb_fname_str_dbg(smb_fname_src
),
6392 smb_fname_str_dbg(smb_fname_dst
)));
6393 status
= rename_internals(ctx
, conn
, req
, smb_fname_src
,
6394 smb_fname_dst
, 0, overwrite
, false,
6396 FILE_WRITE_ATTRIBUTES
);
6399 TALLOC_FREE(smb_fname_dst
);
6403 /****************************************************************************
6404 Deal with SMB_SET_POSIX_ACL.
6405 ****************************************************************************/
6407 #if defined(HAVE_POSIX_ACLS)
6408 static NTSTATUS
smb_set_posix_acl(connection_struct
*conn
,
6412 const struct smb_filename
*smb_fname
)
6414 uint16 posix_acl_version
;
6415 uint16 num_file_acls
;
6416 uint16 num_def_acls
;
6417 bool valid_file_acls
= True
;
6418 bool valid_def_acls
= True
;
6420 if (total_data
< SMB_POSIX_ACL_HEADER_SIZE
) {
6421 return NT_STATUS_INVALID_PARAMETER
;
6423 posix_acl_version
= SVAL(pdata
,0);
6424 num_file_acls
= SVAL(pdata
,2);
6425 num_def_acls
= SVAL(pdata
,4);
6427 if (num_file_acls
== SMB_POSIX_IGNORE_ACE_ENTRIES
) {
6428 valid_file_acls
= False
;
6432 if (num_def_acls
== SMB_POSIX_IGNORE_ACE_ENTRIES
) {
6433 valid_def_acls
= False
;
6437 if (posix_acl_version
!= SMB_POSIX_ACL_VERSION
) {
6438 return NT_STATUS_INVALID_PARAMETER
;
6441 if (total_data
< SMB_POSIX_ACL_HEADER_SIZE
+
6442 (num_file_acls
+num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
) {
6443 return NT_STATUS_INVALID_PARAMETER
;
6446 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
6447 smb_fname
? smb_fname_str_dbg(smb_fname
) : fsp_str_dbg(fsp
),
6448 (unsigned int)num_file_acls
,
6449 (unsigned int)num_def_acls
));
6451 if (valid_file_acls
&& !set_unix_posix_acl(conn
, fsp
,
6452 smb_fname
->base_name
, num_file_acls
,
6453 pdata
+ SMB_POSIX_ACL_HEADER_SIZE
)) {
6454 return map_nt_error_from_unix(errno
);
6457 if (valid_def_acls
&& !set_unix_posix_default_acl(conn
,
6458 smb_fname
->base_name
, &smb_fname
->st
, num_def_acls
,
6459 pdata
+ SMB_POSIX_ACL_HEADER_SIZE
+
6460 (num_file_acls
*SMB_POSIX_ACL_ENTRY_SIZE
))) {
6461 return map_nt_error_from_unix(errno
);
6463 return NT_STATUS_OK
;
6467 /****************************************************************************
6468 Deal with SMB_SET_POSIX_LOCK.
6469 ****************************************************************************/
6471 static NTSTATUS
smb_set_posix_lock(connection_struct
*conn
,
6472 struct smb_request
*req
,
6480 bool blocking_lock
= False
;
6481 enum brl_type lock_type
;
6483 NTSTATUS status
= NT_STATUS_OK
;
6485 if (fsp
== NULL
|| fsp
->fh
->fd
== -1) {
6486 return NT_STATUS_INVALID_HANDLE
;
6489 if (total_data
!= POSIX_LOCK_DATA_SIZE
) {
6490 return NT_STATUS_INVALID_PARAMETER
;
6493 switch (SVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
)) {
6494 case POSIX_LOCK_TYPE_READ
:
6495 lock_type
= READ_LOCK
;
6497 case POSIX_LOCK_TYPE_WRITE
:
6498 /* Return the right POSIX-mappable error code for files opened read-only. */
6499 if (!fsp
->can_write
) {
6500 return NT_STATUS_INVALID_HANDLE
;
6502 lock_type
= WRITE_LOCK
;
6504 case POSIX_LOCK_TYPE_UNLOCK
:
6505 lock_type
= UNLOCK_LOCK
;
6508 return NT_STATUS_INVALID_PARAMETER
;
6511 if (SVAL(pdata
,POSIX_LOCK_FLAGS_OFFSET
) == POSIX_LOCK_FLAG_NOWAIT
) {
6512 blocking_lock
= False
;
6513 } else if (SVAL(pdata
,POSIX_LOCK_FLAGS_OFFSET
) == POSIX_LOCK_FLAG_WAIT
) {
6514 blocking_lock
= True
;
6516 return NT_STATUS_INVALID_PARAMETER
;
6519 if (!lp_blocking_locks(SNUM(conn
))) {
6520 blocking_lock
= False
;
6523 smblctx
= (uint64_t)IVAL(pdata
, POSIX_LOCK_PID_OFFSET
);
6524 #if defined(HAVE_LONGLONG)
6525 offset
= (((uint64_t) IVAL(pdata
,(POSIX_LOCK_START_OFFSET
+4))) << 32) |
6526 ((uint64_t) IVAL(pdata
,POSIX_LOCK_START_OFFSET
));
6527 count
= (((uint64_t) IVAL(pdata
,(POSIX_LOCK_LEN_OFFSET
+4))) << 32) |
6528 ((uint64_t) IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
));
6529 #else /* HAVE_LONGLONG */
6530 offset
= (uint64_t)IVAL(pdata
,POSIX_LOCK_START_OFFSET
);
6531 count
= (uint64_t)IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
);
6532 #endif /* HAVE_LONGLONG */
6534 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
6535 "smblctx = %llu, count = %.0f, offset = %.0f\n",
6537 (unsigned int)lock_type
,
6538 (unsigned long long)smblctx
,
6542 if (lock_type
== UNLOCK_LOCK
) {
6543 status
= do_unlock(req
->sconn
->msg_ctx
,
6550 uint64_t block_smblctx
;
6552 struct byte_range_lock
*br_lck
= do_lock(req
->sconn
->msg_ctx
,
6564 if (br_lck
&& blocking_lock
&& ERROR_WAS_LOCK_DENIED(status
)) {
6566 * A blocking lock was requested. Package up
6567 * this smb into a queued request and push it
6568 * onto the blocking lock queue.
6570 if(push_blocking_lock_request(br_lck
,
6573 -1, /* infinite timeout. */
6581 TALLOC_FREE(br_lck
);
6585 TALLOC_FREE(br_lck
);
6591 /****************************************************************************
6592 Deal with SMB_SET_FILE_BASIC_INFO.
6593 ****************************************************************************/
6595 static NTSTATUS
smb_set_file_basic_info(connection_struct
*conn
,
6599 const struct smb_filename
*smb_fname
)
6601 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
6602 struct smb_file_time ft
;
6604 NTSTATUS status
= NT_STATUS_OK
;
6608 if (total_data
< 36) {
6609 return NT_STATUS_INVALID_PARAMETER
;
6612 status
= check_access(conn
, fsp
, smb_fname
, FILE_WRITE_ATTRIBUTES
);
6613 if (!NT_STATUS_IS_OK(status
)) {
6617 /* Set the attributes */
6618 dosmode
= IVAL(pdata
,32);
6619 status
= smb_set_file_dosmode(conn
, smb_fname
, dosmode
);
6620 if (!NT_STATUS_IS_OK(status
)) {
6625 ft
.create_time
= interpret_long_date(pdata
);
6628 ft
.atime
= interpret_long_date(pdata
+8);
6631 ft
.mtime
= interpret_long_date(pdata
+16);
6634 ft
.ctime
= interpret_long_date(pdata
+24);
6636 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
6637 smb_fname_str_dbg(smb_fname
)));
6639 return smb_set_file_time(conn
, fsp
, smb_fname
, &ft
,
6643 /****************************************************************************
6644 Deal with SMB_INFO_STANDARD.
6645 ****************************************************************************/
6647 static NTSTATUS
smb_set_info_standard(connection_struct
*conn
,
6651 const struct smb_filename
*smb_fname
)
6654 struct smb_file_time ft
;
6658 if (total_data
< 12) {
6659 return NT_STATUS_INVALID_PARAMETER
;
6663 ft
.create_time
= convert_time_t_to_timespec(srv_make_unix_date2(pdata
));
6665 ft
.atime
= convert_time_t_to_timespec(srv_make_unix_date2(pdata
+4));
6667 ft
.mtime
= convert_time_t_to_timespec(srv_make_unix_date2(pdata
+8));
6669 DEBUG(10,("smb_set_info_standard: file %s\n",
6670 smb_fname_str_dbg(smb_fname
)));
6672 status
= check_access(conn
, fsp
, smb_fname
, FILE_WRITE_ATTRIBUTES
);
6673 if (!NT_STATUS_IS_OK(status
)) {
6677 return smb_set_file_time(conn
,
6684 /****************************************************************************
6685 Deal with SMB_SET_FILE_ALLOCATION_INFO.
6686 ****************************************************************************/
6688 static NTSTATUS
smb_set_file_allocation_info(connection_struct
*conn
,
6689 struct smb_request
*req
,
6693 struct smb_filename
*smb_fname
)
6695 uint64_t allocation_size
= 0;
6696 NTSTATUS status
= NT_STATUS_OK
;
6697 files_struct
*new_fsp
= NULL
;
6699 if (!VALID_STAT(smb_fname
->st
)) {
6700 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
6703 if (total_data
< 8) {
6704 return NT_STATUS_INVALID_PARAMETER
;
6707 allocation_size
= (uint64_t)IVAL(pdata
,0);
6708 allocation_size
|= (((uint64_t)IVAL(pdata
,4)) << 32);
6709 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
6710 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname
),
6711 (double)allocation_size
));
6713 if (allocation_size
) {
6714 allocation_size
= smb_roundup(conn
, allocation_size
);
6717 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
6718 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname
),
6719 (double)allocation_size
));
6721 if (fsp
&& fsp
->fh
->fd
!= -1) {
6722 /* Open file handle. */
6723 if (!(fsp
->access_mask
& FILE_WRITE_DATA
)) {
6724 return NT_STATUS_ACCESS_DENIED
;
6727 /* Only change if needed. */
6728 if (allocation_size
!= get_file_size_stat(&smb_fname
->st
)) {
6729 if (vfs_allocate_file_space(fsp
, allocation_size
) == -1) {
6730 return map_nt_error_from_unix(errno
);
6733 /* But always update the time. */
6735 * This is equivalent to a write. Ensure it's seen immediately
6736 * if there are no pending writes.
6738 trigger_write_time_update_immediate(fsp
);
6739 return NT_STATUS_OK
;
6742 /* Pathname or stat or directory file. */
6743 status
= SMB_VFS_CREATE_FILE(
6746 0, /* root_dir_fid */
6747 smb_fname
, /* fname */
6748 FILE_WRITE_DATA
, /* access_mask */
6749 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
6751 FILE_OPEN
, /* create_disposition*/
6752 0, /* create_options */
6753 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
6754 FORCE_OPLOCK_BREAK_TO_NONE
, /* oplock_request */
6755 0, /* allocation_size */
6756 0, /* private_flags */
6759 &new_fsp
, /* result */
6762 if (!NT_STATUS_IS_OK(status
)) {
6763 /* NB. We check for open_was_deferred in the caller. */
6767 /* Only change if needed. */
6768 if (allocation_size
!= get_file_size_stat(&smb_fname
->st
)) {
6769 if (vfs_allocate_file_space(new_fsp
, allocation_size
) == -1) {
6770 status
= map_nt_error_from_unix(errno
);
6771 close_file(req
, new_fsp
, NORMAL_CLOSE
);
6776 /* Changing the allocation size should set the last mod time. */
6778 * This is equivalent to a write. Ensure it's seen immediately
6779 * if there are no pending writes.
6781 trigger_write_time_update_immediate(new_fsp
);
6783 close_file(req
, new_fsp
, NORMAL_CLOSE
);
6784 return NT_STATUS_OK
;
6787 /****************************************************************************
6788 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
6789 ****************************************************************************/
6791 static NTSTATUS
smb_set_file_end_of_file_info(connection_struct
*conn
,
6792 struct smb_request
*req
,
6796 const struct smb_filename
*smb_fname
,
6797 bool fail_after_createfile
)
6801 if (total_data
< 8) {
6802 return NT_STATUS_INVALID_PARAMETER
;
6805 size
= IVAL(pdata
,0);
6806 size
|= (((off_t
)IVAL(pdata
,4)) << 32);
6807 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
6808 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname
),
6811 return smb_set_file_size(conn
, req
,
6816 fail_after_createfile
);
6819 /****************************************************************************
6820 Allow a UNIX info mknod.
6821 ****************************************************************************/
6823 static NTSTATUS
smb_unix_mknod(connection_struct
*conn
,
6826 const struct smb_filename
*smb_fname
)
6828 uint32 file_type
= IVAL(pdata
,56);
6829 #if defined(HAVE_MAKEDEV)
6830 uint32 dev_major
= IVAL(pdata
,60);
6831 uint32 dev_minor
= IVAL(pdata
,68);
6833 SMB_DEV_T dev
= (SMB_DEV_T
)0;
6834 uint32 raw_unixmode
= IVAL(pdata
,84);
6838 if (total_data
< 100) {
6839 return NT_STATUS_INVALID_PARAMETER
;
6842 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
6843 PERM_NEW_FILE
, &unixmode
);
6844 if (!NT_STATUS_IS_OK(status
)) {
6848 #if defined(HAVE_MAKEDEV)
6849 dev
= makedev(dev_major
, dev_minor
);
6852 switch (file_type
) {
6853 #if defined(S_IFIFO)
6854 case UNIX_TYPE_FIFO
:
6855 unixmode
|= S_IFIFO
;
6858 #if defined(S_IFSOCK)
6859 case UNIX_TYPE_SOCKET
:
6860 unixmode
|= S_IFSOCK
;
6863 #if defined(S_IFCHR)
6864 case UNIX_TYPE_CHARDEV
:
6865 unixmode
|= S_IFCHR
;
6868 #if defined(S_IFBLK)
6869 case UNIX_TYPE_BLKDEV
:
6870 unixmode
|= S_IFBLK
;
6874 return NT_STATUS_INVALID_PARAMETER
;
6877 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
6878 "%.0f mode 0%o for file %s\n", (double)dev
,
6879 (unsigned int)unixmode
, smb_fname_str_dbg(smb_fname
)));
6881 /* Ok - do the mknod. */
6882 if (SMB_VFS_MKNOD(conn
, smb_fname
->base_name
, unixmode
, dev
) != 0) {
6883 return map_nt_error_from_unix(errno
);
6886 /* If any of the other "set" calls fail we
6887 * don't want to end up with a half-constructed mknod.
6890 if (lp_inherit_perms(SNUM(conn
))) {
6892 if (!parent_dirname(talloc_tos(), smb_fname
->base_name
,
6894 return NT_STATUS_NO_MEMORY
;
6896 inherit_access_posix_acl(conn
, parent
, smb_fname
->base_name
,
6898 TALLOC_FREE(parent
);
6901 return NT_STATUS_OK
;
6904 /****************************************************************************
6905 Deal with SMB_SET_FILE_UNIX_BASIC.
6906 ****************************************************************************/
6908 static NTSTATUS
smb_set_file_unix_basic(connection_struct
*conn
,
6909 struct smb_request
*req
,
6913 const struct smb_filename
*smb_fname
)
6915 struct smb_file_time ft
;
6916 uint32 raw_unixmode
;
6919 uid_t set_owner
= (uid_t
)SMB_UID_NO_CHANGE
;
6920 gid_t set_grp
= (uid_t
)SMB_GID_NO_CHANGE
;
6921 NTSTATUS status
= NT_STATUS_OK
;
6922 bool delete_on_fail
= False
;
6923 enum perm_type ptype
;
6924 files_struct
*all_fsps
= NULL
;
6925 bool modify_mtime
= true;
6927 struct smb_filename
*smb_fname_tmp
= NULL
;
6928 SMB_STRUCT_STAT sbuf
;
6932 if (total_data
< 100) {
6933 return NT_STATUS_INVALID_PARAMETER
;
6936 if(IVAL(pdata
, 0) != SMB_SIZE_NO_CHANGE_LO
&&
6937 IVAL(pdata
, 4) != SMB_SIZE_NO_CHANGE_HI
) {
6938 size
=IVAL(pdata
,0); /* first 8 Bytes are size */
6939 size
|= (((off_t
)IVAL(pdata
,4)) << 32);
6942 ft
.atime
= interpret_long_date(pdata
+24); /* access_time */
6943 ft
.mtime
= interpret_long_date(pdata
+32); /* modification_time */
6944 set_owner
= (uid_t
)IVAL(pdata
,40);
6945 set_grp
= (gid_t
)IVAL(pdata
,48);
6946 raw_unixmode
= IVAL(pdata
,84);
6948 if (VALID_STAT(smb_fname
->st
)) {
6949 if (S_ISDIR(smb_fname
->st
.st_ex_mode
)) {
6950 ptype
= PERM_EXISTING_DIR
;
6952 ptype
= PERM_EXISTING_FILE
;
6955 ptype
= PERM_NEW_FILE
;
6958 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
6960 if (!NT_STATUS_IS_OK(status
)) {
6964 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
6965 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
6966 smb_fname_str_dbg(smb_fname
), (double)size
,
6967 (unsigned int)set_owner
, (unsigned int)set_grp
,
6968 (int)raw_unixmode
));
6970 sbuf
= smb_fname
->st
;
6972 if (!VALID_STAT(sbuf
)) {
6974 * The only valid use of this is to create character and block
6975 * devices, and named pipes. This is deprecated (IMHO) and
6976 * a new info level should be used for mknod. JRA.
6979 status
= smb_unix_mknod(conn
,
6983 if (!NT_STATUS_IS_OK(status
)) {
6987 status
= copy_smb_filename(talloc_tos(), smb_fname
,
6989 if (!NT_STATUS_IS_OK(status
)) {
6993 if (SMB_VFS_STAT(conn
, smb_fname_tmp
) != 0) {
6994 status
= map_nt_error_from_unix(errno
);
6995 TALLOC_FREE(smb_fname_tmp
);
6996 SMB_VFS_UNLINK(conn
, smb_fname
);
7000 sbuf
= smb_fname_tmp
->st
;
7001 smb_fname
= smb_fname_tmp
;
7003 /* Ensure we don't try and change anything else. */
7004 raw_unixmode
= SMB_MODE_NO_CHANGE
;
7005 size
= get_file_size_stat(&sbuf
);
7006 ft
.atime
= sbuf
.st_ex_atime
;
7007 ft
.mtime
= sbuf
.st_ex_mtime
;
7009 * We continue here as we might want to change the
7012 delete_on_fail
= True
;
7016 /* Horrible backwards compatibility hack as an old server bug
7017 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
7021 size
= get_file_size_stat(&sbuf
);
7026 * Deal with the UNIX specific mode set.
7029 if (raw_unixmode
!= SMB_MODE_NO_CHANGE
) {
7030 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7031 "setting mode 0%o for file %s\n",
7032 (unsigned int)unixmode
,
7033 smb_fname_str_dbg(smb_fname
)));
7034 if (SMB_VFS_CHMOD(conn
, smb_fname
->base_name
, unixmode
) != 0) {
7035 return map_nt_error_from_unix(errno
);
7040 * Deal with the UNIX specific uid set.
7043 if ((set_owner
!= (uid_t
)SMB_UID_NO_CHANGE
) &&
7044 (sbuf
.st_ex_uid
!= set_owner
)) {
7047 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7048 "changing owner %u for path %s\n",
7049 (unsigned int)set_owner
,
7050 smb_fname_str_dbg(smb_fname
)));
7052 if (S_ISLNK(sbuf
.st_ex_mode
)) {
7053 ret
= SMB_VFS_LCHOWN(conn
, smb_fname
->base_name
,
7054 set_owner
, (gid_t
)-1);
7056 ret
= SMB_VFS_CHOWN(conn
, smb_fname
->base_name
,
7057 set_owner
, (gid_t
)-1);
7061 status
= map_nt_error_from_unix(errno
);
7062 if (delete_on_fail
) {
7063 SMB_VFS_UNLINK(conn
, smb_fname
);
7070 * Deal with the UNIX specific gid set.
7073 if ((set_grp
!= (uid_t
)SMB_GID_NO_CHANGE
) &&
7074 (sbuf
.st_ex_gid
!= set_grp
)) {
7075 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7076 "changing group %u for file %s\n",
7077 (unsigned int)set_owner
,
7078 smb_fname_str_dbg(smb_fname
)));
7079 if (SMB_VFS_CHOWN(conn
, smb_fname
->base_name
, (uid_t
)-1,
7081 status
= map_nt_error_from_unix(errno
);
7082 if (delete_on_fail
) {
7083 SMB_VFS_UNLINK(conn
, smb_fname
);
7089 /* Deal with any size changes. */
7091 status
= smb_set_file_size(conn
, req
,
7097 if (!NT_STATUS_IS_OK(status
)) {
7101 /* Deal with any time changes. */
7102 if (null_timespec(ft
.mtime
) && null_timespec(ft
.atime
)) {
7103 /* No change, don't cancel anything. */
7107 id
= vfs_file_id_from_sbuf(conn
, &sbuf
);
7108 for(all_fsps
= file_find_di_first(conn
->sconn
, id
); all_fsps
;
7109 all_fsps
= file_find_di_next(all_fsps
)) {
7111 * We're setting the time explicitly for UNIX.
7112 * Cancel any pending changes over all handles.
7114 all_fsps
->update_write_time_on_close
= false;
7115 TALLOC_FREE(all_fsps
->update_write_time_event
);
7119 * Override the "setting_write_time"
7120 * parameter here as it almost does what
7121 * we need. Just remember if we modified
7122 * mtime and send the notify ourselves.
7124 if (null_timespec(ft
.mtime
)) {
7125 modify_mtime
= false;
7128 status
= smb_set_file_time(conn
,
7134 notify_fname(conn
, NOTIFY_ACTION_MODIFIED
,
7135 FILE_NOTIFY_CHANGE_LAST_WRITE
, smb_fname
->base_name
);
7140 /****************************************************************************
7141 Deal with SMB_SET_FILE_UNIX_INFO2.
7142 ****************************************************************************/
7144 static NTSTATUS
smb_set_file_unix_info2(connection_struct
*conn
,
7145 struct smb_request
*req
,
7149 const struct smb_filename
*smb_fname
)
7155 if (total_data
< 116) {
7156 return NT_STATUS_INVALID_PARAMETER
;
7159 /* Start by setting all the fields that are common between UNIX_BASIC
7162 status
= smb_set_file_unix_basic(conn
, req
, pdata
, total_data
,
7164 if (!NT_STATUS_IS_OK(status
)) {
7168 smb_fflags
= IVAL(pdata
, 108);
7169 smb_fmask
= IVAL(pdata
, 112);
7171 /* NB: We should only attempt to alter the file flags if the client
7172 * sends a non-zero mask.
7174 if (smb_fmask
!= 0) {
7175 int stat_fflags
= 0;
7177 if (!map_info2_flags_to_sbuf(&smb_fname
->st
, smb_fflags
,
7178 smb_fmask
, &stat_fflags
)) {
7179 /* Client asked to alter a flag we don't understand. */
7180 return NT_STATUS_INVALID_PARAMETER
;
7183 if (fsp
&& fsp
->fh
->fd
!= -1) {
7184 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
7185 return NT_STATUS_NOT_SUPPORTED
;
7187 if (SMB_VFS_CHFLAGS(conn
, smb_fname
->base_name
,
7188 stat_fflags
) != 0) {
7189 return map_nt_error_from_unix(errno
);
7194 /* XXX: need to add support for changing the create_time here. You
7195 * can do this for paths on Darwin with setattrlist(2). The right way
7196 * to hook this up is probably by extending the VFS utimes interface.
7199 return NT_STATUS_OK
;
7202 /****************************************************************************
7203 Create a directory with POSIX semantics.
7204 ****************************************************************************/
7206 static NTSTATUS
smb_posix_mkdir(connection_struct
*conn
,
7207 struct smb_request
*req
,
7210 struct smb_filename
*smb_fname
,
7211 int *pdata_return_size
)
7213 NTSTATUS status
= NT_STATUS_OK
;
7214 uint32 raw_unixmode
= 0;
7215 uint32 mod_unixmode
= 0;
7216 mode_t unixmode
= (mode_t
)0;
7217 files_struct
*fsp
= NULL
;
7218 uint16 info_level_return
= 0;
7220 char *pdata
= *ppdata
;
7222 if (total_data
< 18) {
7223 return NT_STATUS_INVALID_PARAMETER
;
7226 raw_unixmode
= IVAL(pdata
,8);
7227 /* Next 4 bytes are not yet defined. */
7229 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
7230 PERM_NEW_DIR
, &unixmode
);
7231 if (!NT_STATUS_IS_OK(status
)) {
7235 mod_unixmode
= (uint32
)unixmode
| FILE_FLAG_POSIX_SEMANTICS
;
7237 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
7238 smb_fname_str_dbg(smb_fname
), (unsigned int)unixmode
));
7240 status
= SMB_VFS_CREATE_FILE(
7243 0, /* root_dir_fid */
7244 smb_fname
, /* fname */
7245 FILE_READ_ATTRIBUTES
, /* access_mask */
7246 FILE_SHARE_NONE
, /* share_access */
7247 FILE_CREATE
, /* create_disposition*/
7248 FILE_DIRECTORY_FILE
, /* create_options */
7249 mod_unixmode
, /* file_attributes */
7250 0, /* oplock_request */
7251 0, /* allocation_size */
7252 0, /* private_flags */
7258 if (NT_STATUS_IS_OK(status
)) {
7259 close_file(req
, fsp
, NORMAL_CLOSE
);
7262 info_level_return
= SVAL(pdata
,16);
7264 if (info_level_return
== SMB_QUERY_FILE_UNIX_BASIC
) {
7265 *pdata_return_size
= 12 + SMB_FILE_UNIX_BASIC_SIZE
;
7266 } else if (info_level_return
== SMB_QUERY_FILE_UNIX_INFO2
) {
7267 *pdata_return_size
= 12 + SMB_FILE_UNIX_INFO2_SIZE
;
7269 *pdata_return_size
= 12;
7272 /* Realloc the data size */
7273 *ppdata
= (char *)SMB_REALLOC(*ppdata
,*pdata_return_size
);
7274 if (*ppdata
== NULL
) {
7275 *pdata_return_size
= 0;
7276 return NT_STATUS_NO_MEMORY
;
7280 SSVAL(pdata
,0,NO_OPLOCK_RETURN
);
7281 SSVAL(pdata
,2,0); /* No fnum. */
7282 SIVAL(pdata
,4,info
); /* Was directory created. */
7284 switch (info_level_return
) {
7285 case SMB_QUERY_FILE_UNIX_BASIC
:
7286 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_BASIC
);
7287 SSVAL(pdata
,10,0); /* Padding. */
7288 store_file_unix_basic(conn
, pdata
+ 12, fsp
,
7291 case SMB_QUERY_FILE_UNIX_INFO2
:
7292 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_INFO2
);
7293 SSVAL(pdata
,10,0); /* Padding. */
7294 store_file_unix_basic_info2(conn
, pdata
+ 12, fsp
,
7298 SSVAL(pdata
,8,SMB_NO_INFO_LEVEL_RETURNED
);
7299 SSVAL(pdata
,10,0); /* Padding. */
7306 /****************************************************************************
7307 Open/Create a file with POSIX semantics.
7308 ****************************************************************************/
7310 #define SMB_O_RDONLY_MAPPING (FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA)
7311 #define SMB_O_WRONLY_MAPPING (FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA)
7313 static NTSTATUS
smb_posix_open(connection_struct
*conn
,
7314 struct smb_request
*req
,
7317 struct smb_filename
*smb_fname
,
7318 int *pdata_return_size
)
7320 bool extended_oplock_granted
= False
;
7321 char *pdata
= *ppdata
;
7323 uint32 wire_open_mode
= 0;
7324 uint32 raw_unixmode
= 0;
7325 uint32 mod_unixmode
= 0;
7326 uint32 create_disp
= 0;
7327 uint32 access_mask
= 0;
7328 uint32 create_options
= FILE_NON_DIRECTORY_FILE
;
7329 NTSTATUS status
= NT_STATUS_OK
;
7330 mode_t unixmode
= (mode_t
)0;
7331 files_struct
*fsp
= NULL
;
7332 int oplock_request
= 0;
7334 uint16 info_level_return
= 0;
7336 if (total_data
< 18) {
7337 return NT_STATUS_INVALID_PARAMETER
;
7340 flags
= IVAL(pdata
,0);
7341 oplock_request
= (flags
& REQUEST_OPLOCK
) ? EXCLUSIVE_OPLOCK
: 0;
7342 if (oplock_request
) {
7343 oplock_request
|= (flags
& REQUEST_BATCH_OPLOCK
) ? BATCH_OPLOCK
: 0;
7346 wire_open_mode
= IVAL(pdata
,4);
7348 if (wire_open_mode
== (SMB_O_CREAT
|SMB_O_DIRECTORY
)) {
7349 return smb_posix_mkdir(conn
, req
,
7356 switch (wire_open_mode
& SMB_ACCMODE
) {
7358 access_mask
= SMB_O_RDONLY_MAPPING
;
7361 access_mask
= SMB_O_WRONLY_MAPPING
;
7364 access_mask
= (SMB_O_RDONLY_MAPPING
|
7365 SMB_O_WRONLY_MAPPING
);
7368 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
7369 (unsigned int)wire_open_mode
));
7370 return NT_STATUS_INVALID_PARAMETER
;
7373 wire_open_mode
&= ~SMB_ACCMODE
;
7375 /* First take care of O_CREAT|O_EXCL interactions. */
7376 switch (wire_open_mode
& (SMB_O_CREAT
| SMB_O_EXCL
)) {
7377 case (SMB_O_CREAT
| SMB_O_EXCL
):
7378 /* File exists fail. File not exist create. */
7379 create_disp
= FILE_CREATE
;
7382 /* File exists open. File not exist create. */
7383 create_disp
= FILE_OPEN_IF
;
7386 /* File exists open. File not exist fail. */
7387 create_disp
= FILE_OPEN
;
7390 /* O_EXCL on its own without O_CREAT is undefined. */
7392 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
7393 (unsigned int)wire_open_mode
));
7394 return NT_STATUS_INVALID_PARAMETER
;
7397 /* Next factor in the effects of O_TRUNC. */
7398 wire_open_mode
&= ~(SMB_O_CREAT
| SMB_O_EXCL
);
7400 if (wire_open_mode
& SMB_O_TRUNC
) {
7401 switch (create_disp
) {
7403 /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
7404 /* Leave create_disp alone as
7405 (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
7407 /* File exists fail. File not exist create. */
7410 /* SMB_O_CREAT | SMB_O_TRUNC */
7411 /* File exists overwrite. File not exist create. */
7412 create_disp
= FILE_OVERWRITE_IF
;
7416 /* File exists overwrite. File not exist fail. */
7417 create_disp
= FILE_OVERWRITE
;
7420 /* Cannot get here. */
7421 smb_panic("smb_posix_open: logic error");
7422 return NT_STATUS_INVALID_PARAMETER
;
7426 raw_unixmode
= IVAL(pdata
,8);
7427 /* Next 4 bytes are not yet defined. */
7429 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
7430 (VALID_STAT(smb_fname
->st
) ?
7431 PERM_EXISTING_FILE
: PERM_NEW_FILE
),
7434 if (!NT_STATUS_IS_OK(status
)) {
7438 mod_unixmode
= (uint32
)unixmode
| FILE_FLAG_POSIX_SEMANTICS
;
7440 if (wire_open_mode
& SMB_O_SYNC
) {
7441 create_options
|= FILE_WRITE_THROUGH
;
7443 if (wire_open_mode
& SMB_O_APPEND
) {
7444 access_mask
|= FILE_APPEND_DATA
;
7446 if (wire_open_mode
& SMB_O_DIRECT
) {
7447 mod_unixmode
|= FILE_FLAG_NO_BUFFERING
;
7450 if ((wire_open_mode
& SMB_O_DIRECTORY
) ||
7451 VALID_STAT_OF_DIR(smb_fname
->st
)) {
7452 if (access_mask
!= SMB_O_RDONLY_MAPPING
) {
7453 return NT_STATUS_FILE_IS_A_DIRECTORY
;
7455 create_options
&= ~FILE_NON_DIRECTORY_FILE
;
7456 create_options
|= FILE_DIRECTORY_FILE
;
7459 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
7460 smb_fname_str_dbg(smb_fname
),
7461 (unsigned int)wire_open_mode
,
7462 (unsigned int)unixmode
));
7464 status
= SMB_VFS_CREATE_FILE(
7467 0, /* root_dir_fid */
7468 smb_fname
, /* fname */
7469 access_mask
, /* access_mask */
7470 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
7472 create_disp
, /* create_disposition*/
7473 create_options
, /* create_options */
7474 mod_unixmode
, /* file_attributes */
7475 oplock_request
, /* oplock_request */
7476 0, /* allocation_size */
7477 0, /* private_flags */
7483 if (!NT_STATUS_IS_OK(status
)) {
7487 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
7488 extended_oplock_granted
= True
;
7491 if(oplock_request
&& EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
7492 extended_oplock_granted
= True
;
7495 info_level_return
= SVAL(pdata
,16);
7497 /* Allocate the correct return size. */
7499 if (info_level_return
== SMB_QUERY_FILE_UNIX_BASIC
) {
7500 *pdata_return_size
= 12 + SMB_FILE_UNIX_BASIC_SIZE
;
7501 } else if (info_level_return
== SMB_QUERY_FILE_UNIX_INFO2
) {
7502 *pdata_return_size
= 12 + SMB_FILE_UNIX_INFO2_SIZE
;
7504 *pdata_return_size
= 12;
7507 /* Realloc the data size */
7508 *ppdata
= (char *)SMB_REALLOC(*ppdata
,*pdata_return_size
);
7509 if (*ppdata
== NULL
) {
7510 close_file(req
, fsp
, ERROR_CLOSE
);
7511 *pdata_return_size
= 0;
7512 return NT_STATUS_NO_MEMORY
;
7516 if (extended_oplock_granted
) {
7517 if (flags
& REQUEST_BATCH_OPLOCK
) {
7518 SSVAL(pdata
,0, BATCH_OPLOCK_RETURN
);
7520 SSVAL(pdata
,0, EXCLUSIVE_OPLOCK_RETURN
);
7522 } else if (fsp
->oplock_type
== LEVEL_II_OPLOCK
) {
7523 SSVAL(pdata
,0, LEVEL_II_OPLOCK_RETURN
);
7525 SSVAL(pdata
,0,NO_OPLOCK_RETURN
);
7528 SSVAL(pdata
,2,fsp
->fnum
);
7529 SIVAL(pdata
,4,info
); /* Was file created etc. */
7531 switch (info_level_return
) {
7532 case SMB_QUERY_FILE_UNIX_BASIC
:
7533 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_BASIC
);
7534 SSVAL(pdata
,10,0); /* padding. */
7535 store_file_unix_basic(conn
, pdata
+ 12, fsp
,
7538 case SMB_QUERY_FILE_UNIX_INFO2
:
7539 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_INFO2
);
7540 SSVAL(pdata
,10,0); /* padding. */
7541 store_file_unix_basic_info2(conn
, pdata
+ 12, fsp
,
7545 SSVAL(pdata
,8,SMB_NO_INFO_LEVEL_RETURNED
);
7546 SSVAL(pdata
,10,0); /* padding. */
7549 return NT_STATUS_OK
;
7552 /****************************************************************************
7553 Delete a file with POSIX semantics.
7554 ****************************************************************************/
7556 static NTSTATUS
smb_posix_unlink(connection_struct
*conn
,
7557 struct smb_request
*req
,
7560 struct smb_filename
*smb_fname
)
7562 NTSTATUS status
= NT_STATUS_OK
;
7563 files_struct
*fsp
= NULL
;
7567 int create_options
= 0;
7569 struct share_mode_lock
*lck
= NULL
;
7571 if (total_data
< 2) {
7572 return NT_STATUS_INVALID_PARAMETER
;
7575 flags
= SVAL(pdata
,0);
7577 if (!VALID_STAT(smb_fname
->st
)) {
7578 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
7581 if ((flags
== SMB_POSIX_UNLINK_DIRECTORY_TARGET
) &&
7582 !VALID_STAT_OF_DIR(smb_fname
->st
)) {
7583 return NT_STATUS_NOT_A_DIRECTORY
;
7586 DEBUG(10,("smb_posix_unlink: %s %s\n",
7587 (flags
== SMB_POSIX_UNLINK_DIRECTORY_TARGET
) ? "directory" : "file",
7588 smb_fname_str_dbg(smb_fname
)));
7590 if (VALID_STAT_OF_DIR(smb_fname
->st
)) {
7591 create_options
|= FILE_DIRECTORY_FILE
;
7594 status
= SMB_VFS_CREATE_FILE(
7597 0, /* root_dir_fid */
7598 smb_fname
, /* fname */
7599 DELETE_ACCESS
, /* access_mask */
7600 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
7602 FILE_OPEN
, /* create_disposition*/
7603 create_options
, /* create_options */
7604 FILE_FLAG_POSIX_SEMANTICS
|0777, /* file_attributes */
7605 0, /* oplock_request */
7606 0, /* allocation_size */
7607 0, /* private_flags */
7613 if (!NT_STATUS_IS_OK(status
)) {
7618 * Don't lie to client. If we can't really delete due to
7619 * non-POSIX opens return SHARING_VIOLATION.
7622 lck
= get_existing_share_mode_lock(talloc_tos(), fsp
->file_id
);
7624 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
7625 "lock for file %s\n", fsp_str_dbg(fsp
)));
7626 close_file(req
, fsp
, NORMAL_CLOSE
);
7627 return NT_STATUS_INVALID_PARAMETER
;
7631 * See if others still have the file open. If this is the case, then
7632 * don't delete. If all opens are POSIX delete we can set the delete
7633 * on close disposition.
7635 for (i
=0; i
<lck
->data
->num_share_modes
; i
++) {
7636 struct share_mode_entry
*e
= &lck
->data
->share_modes
[i
];
7637 if (is_valid_share_mode_entry(e
)) {
7638 if (e
->flags
& SHARE_MODE_FLAG_POSIX_OPEN
) {
7641 if (share_mode_stale_pid(lck
->data
, i
)) {
7644 /* Fail with sharing violation. */
7645 close_file(req
, fsp
, NORMAL_CLOSE
);
7647 return NT_STATUS_SHARING_VIOLATION
;
7652 * Set the delete on close.
7654 status
= smb_set_file_disposition_info(conn
,
7660 if (!NT_STATUS_IS_OK(status
)) {
7661 close_file(req
, fsp
, NORMAL_CLOSE
);
7666 return close_file(req
, fsp
, NORMAL_CLOSE
);
7669 NTSTATUS
smbd_do_setfilepathinfo(connection_struct
*conn
,
7670 struct smb_request
*req
,
7671 TALLOC_CTX
*mem_ctx
,
7672 uint16_t info_level
,
7674 struct smb_filename
*smb_fname
,
7675 char **ppdata
, int total_data
,
7678 char *pdata
= *ppdata
;
7679 NTSTATUS status
= NT_STATUS_OK
;
7680 int data_return_size
= 0;
7684 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
7685 return NT_STATUS_INVALID_LEVEL
;
7688 if (!CAN_WRITE(conn
)) {
7689 /* Allow POSIX opens. The open path will deny
7690 * any non-readonly opens. */
7691 if (info_level
!= SMB_POSIX_PATH_OPEN
) {
7692 return NT_STATUS_DOS(ERRSRV
, ERRaccess
);
7696 DEBUG(3,("smbd_do_setfilepathinfo: %s (%s) info_level=%d "
7697 "totdata=%d\n", smb_fname_str_dbg(smb_fname
),
7699 info_level
, total_data
));
7701 switch (info_level
) {
7703 case SMB_INFO_STANDARD
:
7705 status
= smb_set_info_standard(conn
,
7713 case SMB_INFO_SET_EA
:
7715 status
= smb_info_set_ea(conn
,
7723 case SMB_SET_FILE_BASIC_INFO
:
7724 case SMB_FILE_BASIC_INFORMATION
:
7726 status
= smb_set_file_basic_info(conn
,
7734 case SMB_FILE_ALLOCATION_INFORMATION
:
7735 case SMB_SET_FILE_ALLOCATION_INFO
:
7737 status
= smb_set_file_allocation_info(conn
, req
,
7745 case SMB_FILE_END_OF_FILE_INFORMATION
:
7746 case SMB_SET_FILE_END_OF_FILE_INFO
:
7749 * XP/Win7 both fail after the createfile with
7750 * SMB_SET_FILE_END_OF_FILE_INFO but not
7751 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
7752 * The level is known here, so pass it down
7756 (info_level
== SMB_SET_FILE_END_OF_FILE_INFO
);
7758 status
= smb_set_file_end_of_file_info(conn
, req
,
7767 case SMB_FILE_DISPOSITION_INFORMATION
:
7768 case SMB_SET_FILE_DISPOSITION_INFO
: /* Set delete on close for open file. */
7771 /* JRA - We used to just ignore this on a path ?
7772 * Shouldn't this be invalid level on a pathname
7775 if (tran_call
!= TRANSACT2_SETFILEINFO
) {
7776 return ERROR_NT(NT_STATUS_INVALID_LEVEL
);
7779 status
= smb_set_file_disposition_info(conn
,
7787 case SMB_FILE_POSITION_INFORMATION
:
7789 status
= smb_file_position_information(conn
,
7796 case SMB_FILE_FULL_EA_INFORMATION
:
7798 status
= smb_set_file_full_ea_info(conn
,
7805 /* From tridge Samba4 :
7806 * MODE_INFORMATION in setfileinfo (I have no
7807 * idea what "mode information" on a file is - it takes a value of 0,
7808 * 2, 4 or 6. What could it be?).
7811 case SMB_FILE_MODE_INFORMATION
:
7813 status
= smb_file_mode_information(conn
,
7820 * CIFS UNIX extensions.
7823 case SMB_SET_FILE_UNIX_BASIC
:
7825 status
= smb_set_file_unix_basic(conn
, req
,
7833 case SMB_SET_FILE_UNIX_INFO2
:
7835 status
= smb_set_file_unix_info2(conn
, req
,
7843 case SMB_SET_FILE_UNIX_LINK
:
7846 /* We must have a pathname for this. */
7847 return NT_STATUS_INVALID_LEVEL
;
7849 status
= smb_set_file_unix_link(conn
, req
, pdata
,
7850 total_data
, smb_fname
);
7854 case SMB_SET_FILE_UNIX_HLINK
:
7857 /* We must have a pathname for this. */
7858 return NT_STATUS_INVALID_LEVEL
;
7860 status
= smb_set_file_unix_hlink(conn
, req
,
7866 case SMB_FILE_RENAME_INFORMATION
:
7868 status
= smb_file_rename_information(conn
, req
,
7874 case SMB2_FILE_RENAME_INFORMATION_INTERNAL
:
7876 /* SMB2 rename information. */
7877 status
= smb2_file_rename_information(conn
, req
,
7883 case SMB_FILE_LINK_INFORMATION
:
7885 status
= smb_file_link_information(conn
, req
,
7891 #if defined(HAVE_POSIX_ACLS)
7892 case SMB_SET_POSIX_ACL
:
7894 status
= smb_set_posix_acl(conn
,
7903 case SMB_SET_POSIX_LOCK
:
7906 return NT_STATUS_INVALID_LEVEL
;
7908 status
= smb_set_posix_lock(conn
, req
,
7909 pdata
, total_data
, fsp
);
7913 case SMB_POSIX_PATH_OPEN
:
7916 /* We must have a pathname for this. */
7917 return NT_STATUS_INVALID_LEVEL
;
7920 status
= smb_posix_open(conn
, req
,
7928 case SMB_POSIX_PATH_UNLINK
:
7931 /* We must have a pathname for this. */
7932 return NT_STATUS_INVALID_LEVEL
;
7935 status
= smb_posix_unlink(conn
, req
,
7943 return NT_STATUS_INVALID_LEVEL
;
7946 if (!NT_STATUS_IS_OK(status
)) {
7950 *ret_data_size
= data_return_size
;
7951 return NT_STATUS_OK
;
7954 /****************************************************************************
7955 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
7956 ****************************************************************************/
7958 static void call_trans2setfilepathinfo(connection_struct
*conn
,
7959 struct smb_request
*req
,
7960 unsigned int tran_call
,
7961 char **pparams
, int total_params
,
7962 char **ppdata
, int total_data
,
7963 unsigned int max_data_bytes
)
7965 char *params
= *pparams
;
7966 char *pdata
= *ppdata
;
7968 struct smb_filename
*smb_fname
= NULL
;
7969 files_struct
*fsp
= NULL
;
7970 NTSTATUS status
= NT_STATUS_OK
;
7971 int data_return_size
= 0;
7974 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7978 if (tran_call
== TRANSACT2_SETFILEINFO
) {
7979 if (total_params
< 4) {
7980 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7984 fsp
= file_fsp(req
, SVAL(params
,0));
7985 /* Basic check for non-null fsp. */
7986 if (!check_fsp_open(conn
, req
, fsp
)) {
7989 info_level
= SVAL(params
,2);
7991 status
= copy_smb_filename(talloc_tos(), fsp
->fsp_name
,
7993 if (!NT_STATUS_IS_OK(status
)) {
7994 reply_nterror(req
, status
);
7998 if(fsp
->fh
->fd
== -1) {
8000 * This is actually a SETFILEINFO on a directory
8001 * handle (returned from an NT SMB). NT5.0 seems
8002 * to do this call. JRA.
8004 if (INFO_LEVEL_IS_UNIX(info_level
)) {
8005 /* Always do lstat for UNIX calls. */
8006 if (SMB_VFS_LSTAT(conn
, smb_fname
)) {
8007 DEBUG(3,("call_trans2setfilepathinfo: "
8008 "SMB_VFS_LSTAT of %s failed "
8010 smb_fname_str_dbg(smb_fname
),
8012 reply_nterror(req
, map_nt_error_from_unix(errno
));
8016 if (SMB_VFS_STAT(conn
, smb_fname
) != 0) {
8017 DEBUG(3,("call_trans2setfilepathinfo: "
8018 "fileinfo of %s failed (%s)\n",
8019 smb_fname_str_dbg(smb_fname
),
8021 reply_nterror(req
, map_nt_error_from_unix(errno
));
8025 } else if (fsp
->print_file
) {
8027 * Doing a DELETE_ON_CLOSE should cancel a print job.
8029 if ((info_level
== SMB_SET_FILE_DISPOSITION_INFO
) && CVAL(pdata
,0)) {
8030 fsp
->fh
->private_options
|= NTCREATEX_OPTIONS_PRIVATE_DELETE_ON_CLOSE
;
8032 DEBUG(3,("call_trans2setfilepathinfo: "
8033 "Cancelling print job (%s)\n",
8037 send_trans2_replies(conn
, req
, params
, 2,
8043 NT_STATUS_OBJECT_PATH_NOT_FOUND
);
8048 * Original code - this is an open file.
8050 if (SMB_VFS_FSTAT(fsp
, &smb_fname
->st
) != 0) {
8051 DEBUG(3,("call_trans2setfilepathinfo: fstat "
8052 "of %s failed (%s)\n", fsp_fnum_dbg(fsp
),
8054 reply_nterror(req
, map_nt_error_from_unix(errno
));
8060 uint32_t ucf_flags
= 0;
8063 if (total_params
< 7) {
8064 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8068 info_level
= SVAL(params
,0);
8069 srvstr_get_path(req
, params
, req
->flags2
, &fname
, ¶ms
[6],
8070 total_params
- 6, STR_TERMINATE
,
8072 if (!NT_STATUS_IS_OK(status
)) {
8073 reply_nterror(req
, status
);
8077 if (info_level
== SMB_SET_FILE_UNIX_BASIC
||
8078 info_level
== SMB_SET_FILE_UNIX_INFO2
||
8079 info_level
== SMB_FILE_RENAME_INFORMATION
||
8080 info_level
== SMB_POSIX_PATH_UNLINK
) {
8081 ucf_flags
|= UCF_UNIX_NAME_LOOKUP
;
8084 status
= filename_convert(req
, conn
,
8085 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
8090 if (!NT_STATUS_IS_OK(status
)) {
8091 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
8092 reply_botherror(req
,
8093 NT_STATUS_PATH_NOT_COVERED
,
8094 ERRSRV
, ERRbadpath
);
8097 reply_nterror(req
, status
);
8101 if (INFO_LEVEL_IS_UNIX(info_level
)) {
8103 * For CIFS UNIX extensions the target name may not exist.
8106 /* Always do lstat for UNIX calls. */
8107 SMB_VFS_LSTAT(conn
, smb_fname
);
8109 } else if (!VALID_STAT(smb_fname
->st
) &&
8110 SMB_VFS_STAT(conn
, smb_fname
)) {
8111 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
8113 smb_fname_str_dbg(smb_fname
),
8115 reply_nterror(req
, map_nt_error_from_unix(errno
));
8120 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (%s) info_level=%d "
8121 "totdata=%d\n", tran_call
, smb_fname_str_dbg(smb_fname
),
8123 info_level
,total_data
));
8125 /* Realloc the parameter size */
8126 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
8127 if (*pparams
== NULL
) {
8128 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8135 status
= smbd_do_setfilepathinfo(conn
, req
, req
,
8141 if (!NT_STATUS_IS_OK(status
)) {
8142 if (open_was_deferred(req
->sconn
, req
->mid
)) {
8143 /* We have re-scheduled this call. */
8146 if (blocking_lock_was_deferred_smb1(req
->sconn
, req
->mid
)) {
8147 /* We have re-scheduled this call. */
8150 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
8151 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
8152 ERRSRV
, ERRbadpath
);
8155 if (info_level
== SMB_POSIX_PATH_OPEN
) {
8156 reply_openerror(req
, status
);
8160 reply_nterror(req
, status
);
8164 send_trans2_replies(conn
, req
, params
, 2, *ppdata
, data_return_size
,
8170 /****************************************************************************
8171 Reply to a TRANS2_MKDIR (make directory with extended attributes).
8172 ****************************************************************************/
8174 static void call_trans2mkdir(connection_struct
*conn
, struct smb_request
*req
,
8175 char **pparams
, int total_params
,
8176 char **ppdata
, int total_data
,
8177 unsigned int max_data_bytes
)
8179 struct smb_filename
*smb_dname
= NULL
;
8180 char *params
= *pparams
;
8181 char *pdata
= *ppdata
;
8182 char *directory
= NULL
;
8183 NTSTATUS status
= NT_STATUS_OK
;
8184 struct ea_list
*ea_list
= NULL
;
8185 TALLOC_CTX
*ctx
= talloc_tos();
8187 if (!CAN_WRITE(conn
)) {
8188 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
8192 if (total_params
< 5) {
8193 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8197 srvstr_get_path(ctx
, params
, req
->flags2
, &directory
, ¶ms
[4],
8198 total_params
- 4, STR_TERMINATE
,
8200 if (!NT_STATUS_IS_OK(status
)) {
8201 reply_nterror(req
, status
);
8205 DEBUG(3,("call_trans2mkdir : name = %s\n", directory
));
8207 status
= filename_convert(ctx
,
8209 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
8215 if (!NT_STATUS_IS_OK(status
)) {
8216 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
8217 reply_botherror(req
,
8218 NT_STATUS_PATH_NOT_COVERED
,
8219 ERRSRV
, ERRbadpath
);
8222 reply_nterror(req
, status
);
8227 * OS/2 workplace shell seems to send SET_EA requests of "null"
8228 * length (4 bytes containing IVAL 4).
8229 * They seem to have no effect. Bug #3212. JRA.
8232 if (total_data
&& (total_data
!= 4)) {
8233 /* Any data in this call is an EA list. */
8234 if (total_data
< 10) {
8235 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8239 if (IVAL(pdata
,0) > total_data
) {
8240 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
8241 IVAL(pdata
,0), (unsigned int)total_data
));
8242 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8246 ea_list
= read_ea_list(talloc_tos(), pdata
+ 4,
8249 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8253 if (!lp_ea_support(SNUM(conn
))) {
8254 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
8258 /* If total_data == 4 Windows doesn't care what values
8259 * are placed in that field, it just ignores them.
8260 * The System i QNTC IBM SMB client puts bad values here,
8261 * so ignore them. */
8263 status
= create_directory(conn
, req
, smb_dname
);
8265 if (!NT_STATUS_IS_OK(status
)) {
8266 reply_nterror(req
, status
);
8270 /* Try and set any given EA. */
8272 status
= set_ea(conn
, NULL
, smb_dname
, ea_list
);
8273 if (!NT_STATUS_IS_OK(status
)) {
8274 reply_nterror(req
, status
);
8279 /* Realloc the parameter and data sizes */
8280 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
8281 if(*pparams
== NULL
) {
8282 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8289 send_trans2_replies(conn
, req
, params
, 2, *ppdata
, 0, max_data_bytes
);
8292 TALLOC_FREE(smb_dname
);
8296 /****************************************************************************
8297 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
8298 We don't actually do this - we just send a null response.
8299 ****************************************************************************/
8301 static void call_trans2findnotifyfirst(connection_struct
*conn
,
8302 struct smb_request
*req
,
8303 char **pparams
, int total_params
,
8304 char **ppdata
, int total_data
,
8305 unsigned int max_data_bytes
)
8307 char *params
= *pparams
;
8310 if (total_params
< 6) {
8311 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8315 info_level
= SVAL(params
,4);
8316 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level
));
8318 switch (info_level
) {
8323 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
8327 /* Realloc the parameter and data sizes */
8328 *pparams
= (char *)SMB_REALLOC(*pparams
,6);
8329 if (*pparams
== NULL
) {
8330 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8335 SSVAL(params
,0,fnf_handle
);
8336 SSVAL(params
,2,0); /* No changes */
8337 SSVAL(params
,4,0); /* No EA errors */
8344 send_trans2_replies(conn
, req
, params
, 6, *ppdata
, 0, max_data_bytes
);
8349 /****************************************************************************
8350 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
8351 changes). Currently this does nothing.
8352 ****************************************************************************/
8354 static void call_trans2findnotifynext(connection_struct
*conn
,
8355 struct smb_request
*req
,
8356 char **pparams
, int total_params
,
8357 char **ppdata
, int total_data
,
8358 unsigned int max_data_bytes
)
8360 char *params
= *pparams
;
8362 DEBUG(3,("call_trans2findnotifynext\n"));
8364 /* Realloc the parameter and data sizes */
8365 *pparams
= (char *)SMB_REALLOC(*pparams
,4);
8366 if (*pparams
== NULL
) {
8367 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8372 SSVAL(params
,0,0); /* No changes */
8373 SSVAL(params
,2,0); /* No EA errors */
8375 send_trans2_replies(conn
, req
, params
, 4, *ppdata
, 0, max_data_bytes
);
8380 /****************************************************************************
8381 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
8382 ****************************************************************************/
8384 static void call_trans2getdfsreferral(connection_struct
*conn
,
8385 struct smb_request
*req
,
8386 char **pparams
, int total_params
,
8387 char **ppdata
, int total_data
,
8388 unsigned int max_data_bytes
)
8390 char *params
= *pparams
;
8391 char *pathname
= NULL
;
8393 int max_referral_level
;
8394 NTSTATUS status
= NT_STATUS_OK
;
8395 TALLOC_CTX
*ctx
= talloc_tos();
8397 DEBUG(10,("call_trans2getdfsreferral\n"));
8399 if (total_params
< 3) {
8400 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8404 max_referral_level
= SVAL(params
,0);
8406 if(!lp_host_msdfs()) {
8407 reply_nterror(req
, NT_STATUS_NOT_IMPLEMENTED
);
8411 srvstr_pull_talloc(ctx
, params
, req
->flags2
, &pathname
, ¶ms
[2],
8412 total_params
- 2, STR_TERMINATE
);
8414 reply_nterror(req
, NT_STATUS_NOT_FOUND
);
8417 if((reply_size
= setup_dfs_referral(conn
, pathname
, max_referral_level
,
8418 ppdata
,&status
)) < 0) {
8419 reply_nterror(req
, status
);
8423 SSVAL((discard_const_p(uint8_t, req
->inbuf
)), smb_flg2
,
8424 SVAL(req
->inbuf
,smb_flg2
) | FLAGS2_DFS_PATHNAMES
);
8425 send_trans2_replies(conn
, req
,0,0,*ppdata
,reply_size
, max_data_bytes
);
8430 #define LMCAT_SPL 0x53
8431 #define LMFUNC_GETJOBID 0x60
8433 /****************************************************************************
8434 Reply to a TRANS2_IOCTL - used for OS/2 printing.
8435 ****************************************************************************/
8437 static void call_trans2ioctl(connection_struct
*conn
,
8438 struct smb_request
*req
,
8439 char **pparams
, int total_params
,
8440 char **ppdata
, int total_data
,
8441 unsigned int max_data_bytes
)
8443 char *pdata
= *ppdata
;
8444 files_struct
*fsp
= file_fsp(req
, SVAL(req
->vwv
+15, 0));
8446 /* check for an invalid fid before proceeding */
8449 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
8453 if ((SVAL(req
->vwv
+16, 0) == LMCAT_SPL
)
8454 && (SVAL(req
->vwv
+17, 0) == LMFUNC_GETJOBID
)) {
8455 *ppdata
= (char *)SMB_REALLOC(*ppdata
, 32);
8456 if (*ppdata
== NULL
) {
8457 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8462 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
8463 CAN ACCEPT THIS IN UNICODE. JRA. */
8466 SSVAL(pdata
, 0, print_spool_rap_jobid(fsp
->print_file
));
8468 srvstr_push(pdata
, req
->flags2
, pdata
+ 2,
8469 lp_netbios_name(), 15,
8470 STR_ASCII
|STR_TERMINATE
); /* Our NetBIOS name */
8471 srvstr_push(pdata
, req
->flags2
, pdata
+18,
8472 lp_servicename(talloc_tos(), SNUM(conn
)), 13,
8473 STR_ASCII
|STR_TERMINATE
); /* Service name */
8474 send_trans2_replies(conn
, req
, *pparams
, 0, *ppdata
, 32,
8479 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
8480 reply_nterror(req
, NT_STATUS_NOT_IMPLEMENTED
);
8483 /****************************************************************************
8484 Reply to a SMBfindclose (stop trans2 directory search).
8485 ****************************************************************************/
8487 void reply_findclose(struct smb_request
*req
)
8490 struct smbd_server_connection
*sconn
= req
->sconn
;
8492 START_PROFILE(SMBfindclose
);
8495 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8496 END_PROFILE(SMBfindclose
);
8500 dptr_num
= SVALS(req
->vwv
+0, 0);
8502 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num
));
8504 dptr_close(sconn
, &dptr_num
);
8506 reply_outbuf(req
, 0, 0);
8508 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num
));
8510 END_PROFILE(SMBfindclose
);
8514 /****************************************************************************
8515 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
8516 ****************************************************************************/
8518 void reply_findnclose(struct smb_request
*req
)
8522 START_PROFILE(SMBfindnclose
);
8525 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8526 END_PROFILE(SMBfindnclose
);
8530 dptr_num
= SVAL(req
->vwv
+0, 0);
8532 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num
));
8534 /* We never give out valid handles for a
8535 findnotifyfirst - so any dptr_num is ok here.
8538 reply_outbuf(req
, 0, 0);
8540 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num
));
8542 END_PROFILE(SMBfindnclose
);
8546 static void handle_trans2(connection_struct
*conn
, struct smb_request
*req
,
8547 struct trans_state
*state
)
8549 if (get_Protocol() >= PROTOCOL_NT1
) {
8550 req
->flags2
|= 0x40; /* IS_LONG_NAME */
8551 SSVAL((discard_const_p(uint8_t, req
->inbuf
)),smb_flg2
,req
->flags2
);
8554 if (ENCRYPTION_REQUIRED(conn
) && !req
->encrypted
) {
8555 if (state
->call
!= TRANSACT2_QFSINFO
&&
8556 state
->call
!= TRANSACT2_SETFSINFO
) {
8557 DEBUG(0,("handle_trans2: encryption required "
8559 (unsigned int)state
->call
));
8560 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
8565 SMB_PERFCOUNT_SET_SUBOP(&req
->pcd
, state
->call
);
8567 /* Now we must call the relevant TRANS2 function */
8568 switch(state
->call
) {
8569 case TRANSACT2_OPEN
:
8571 START_PROFILE(Trans2_open
);
8572 call_trans2open(conn
, req
,
8573 &state
->param
, state
->total_param
,
8574 &state
->data
, state
->total_data
,
8575 state
->max_data_return
);
8576 END_PROFILE(Trans2_open
);
8580 case TRANSACT2_FINDFIRST
:
8582 START_PROFILE(Trans2_findfirst
);
8583 call_trans2findfirst(conn
, req
,
8584 &state
->param
, state
->total_param
,
8585 &state
->data
, state
->total_data
,
8586 state
->max_data_return
);
8587 END_PROFILE(Trans2_findfirst
);
8591 case TRANSACT2_FINDNEXT
:
8593 START_PROFILE(Trans2_findnext
);
8594 call_trans2findnext(conn
, req
,
8595 &state
->param
, state
->total_param
,
8596 &state
->data
, state
->total_data
,
8597 state
->max_data_return
);
8598 END_PROFILE(Trans2_findnext
);
8602 case TRANSACT2_QFSINFO
:
8604 START_PROFILE(Trans2_qfsinfo
);
8605 call_trans2qfsinfo(conn
, req
,
8606 &state
->param
, state
->total_param
,
8607 &state
->data
, state
->total_data
,
8608 state
->max_data_return
);
8609 END_PROFILE(Trans2_qfsinfo
);
8613 case TRANSACT2_SETFSINFO
:
8615 START_PROFILE(Trans2_setfsinfo
);
8616 call_trans2setfsinfo(conn
, req
,
8617 &state
->param
, state
->total_param
,
8618 &state
->data
, state
->total_data
,
8619 state
->max_data_return
);
8620 END_PROFILE(Trans2_setfsinfo
);
8624 case TRANSACT2_QPATHINFO
:
8625 case TRANSACT2_QFILEINFO
:
8627 START_PROFILE(Trans2_qpathinfo
);
8628 call_trans2qfilepathinfo(conn
, req
, state
->call
,
8629 &state
->param
, state
->total_param
,
8630 &state
->data
, state
->total_data
,
8631 state
->max_data_return
);
8632 END_PROFILE(Trans2_qpathinfo
);
8636 case TRANSACT2_SETPATHINFO
:
8637 case TRANSACT2_SETFILEINFO
:
8639 START_PROFILE(Trans2_setpathinfo
);
8640 call_trans2setfilepathinfo(conn
, req
, state
->call
,
8641 &state
->param
, state
->total_param
,
8642 &state
->data
, state
->total_data
,
8643 state
->max_data_return
);
8644 END_PROFILE(Trans2_setpathinfo
);
8648 case TRANSACT2_FINDNOTIFYFIRST
:
8650 START_PROFILE(Trans2_findnotifyfirst
);
8651 call_trans2findnotifyfirst(conn
, req
,
8652 &state
->param
, state
->total_param
,
8653 &state
->data
, state
->total_data
,
8654 state
->max_data_return
);
8655 END_PROFILE(Trans2_findnotifyfirst
);
8659 case TRANSACT2_FINDNOTIFYNEXT
:
8661 START_PROFILE(Trans2_findnotifynext
);
8662 call_trans2findnotifynext(conn
, req
,
8663 &state
->param
, state
->total_param
,
8664 &state
->data
, state
->total_data
,
8665 state
->max_data_return
);
8666 END_PROFILE(Trans2_findnotifynext
);
8670 case TRANSACT2_MKDIR
:
8672 START_PROFILE(Trans2_mkdir
);
8673 call_trans2mkdir(conn
, req
,
8674 &state
->param
, state
->total_param
,
8675 &state
->data
, state
->total_data
,
8676 state
->max_data_return
);
8677 END_PROFILE(Trans2_mkdir
);
8681 case TRANSACT2_GET_DFS_REFERRAL
:
8683 START_PROFILE(Trans2_get_dfs_referral
);
8684 call_trans2getdfsreferral(conn
, req
,
8685 &state
->param
, state
->total_param
,
8686 &state
->data
, state
->total_data
,
8687 state
->max_data_return
);
8688 END_PROFILE(Trans2_get_dfs_referral
);
8692 case TRANSACT2_IOCTL
:
8694 START_PROFILE(Trans2_ioctl
);
8695 call_trans2ioctl(conn
, req
,
8696 &state
->param
, state
->total_param
,
8697 &state
->data
, state
->total_data
,
8698 state
->max_data_return
);
8699 END_PROFILE(Trans2_ioctl
);
8704 /* Error in request */
8705 DEBUG(2,("Unknown request %d in trans2 call\n", state
->call
));
8706 reply_nterror(req
, NT_STATUS_NOT_IMPLEMENTED
);
8710 /****************************************************************************
8711 Reply to a SMBtrans2.
8712 ****************************************************************************/
8714 void reply_trans2(struct smb_request
*req
)
8716 connection_struct
*conn
= req
->conn
;
8721 unsigned int tran_call
;
8722 struct trans_state
*state
;
8725 START_PROFILE(SMBtrans2
);
8727 if (req
->wct
< 14) {
8728 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8729 END_PROFILE(SMBtrans2
);
8733 dsoff
= SVAL(req
->vwv
+12, 0);
8734 dscnt
= SVAL(req
->vwv
+11, 0);
8735 psoff
= SVAL(req
->vwv
+10, 0);
8736 pscnt
= SVAL(req
->vwv
+9, 0);
8737 tran_call
= SVAL(req
->vwv
+14, 0);
8739 result
= allow_new_trans(conn
->pending_trans
, req
->mid
);
8740 if (!NT_STATUS_IS_OK(result
)) {
8741 DEBUG(2, ("Got invalid trans2 request: %s\n",
8742 nt_errstr(result
)));
8743 reply_nterror(req
, result
);
8744 END_PROFILE(SMBtrans2
);
8749 switch (tran_call
) {
8750 /* List the allowed trans2 calls on IPC$ */
8751 case TRANSACT2_OPEN
:
8752 case TRANSACT2_GET_DFS_REFERRAL
:
8753 case TRANSACT2_QFILEINFO
:
8754 case TRANSACT2_QFSINFO
:
8755 case TRANSACT2_SETFSINFO
:
8758 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
8759 END_PROFILE(SMBtrans2
);
8764 if ((state
= talloc(conn
, struct trans_state
)) == NULL
) {
8765 DEBUG(0, ("talloc failed\n"));
8766 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8767 END_PROFILE(SMBtrans2
);
8771 state
->cmd
= SMBtrans2
;
8773 state
->mid
= req
->mid
;
8774 state
->vuid
= req
->vuid
;
8775 state
->setup_count
= SVAL(req
->vwv
+13, 0);
8776 state
->setup
= NULL
;
8777 state
->total_param
= SVAL(req
->vwv
+0, 0);
8778 state
->param
= NULL
;
8779 state
->total_data
= SVAL(req
->vwv
+1, 0);
8781 state
->max_param_return
= SVAL(req
->vwv
+2, 0);
8782 state
->max_data_return
= SVAL(req
->vwv
+3, 0);
8783 state
->max_setup_return
= SVAL(req
->vwv
+4, 0);
8784 state
->close_on_completion
= BITSETW(req
->vwv
+5, 0);
8785 state
->one_way
= BITSETW(req
->vwv
+5, 1);
8787 state
->call
= tran_call
;
8789 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
8790 is so as a sanity check */
8791 if (state
->setup_count
!= 1) {
8793 * Need to have rc=0 for ioctl to get job id for OS/2.
8794 * Network printing will fail if function is not successful.
8795 * Similar function in reply.c will be used if protocol
8796 * is LANMAN1.0 instead of LM1.2X002.
8797 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
8798 * outbuf doesn't have to be set(only job id is used).
8800 if ( (state
->setup_count
== 4)
8801 && (tran_call
== TRANSACT2_IOCTL
)
8802 && (SVAL(req
->vwv
+16, 0) == LMCAT_SPL
)
8803 && (SVAL(req
->vwv
+17, 0) == LMFUNC_GETJOBID
)) {
8804 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
8806 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state
->setup_count
));
8807 DEBUG(2,("Transaction is %d\n",tran_call
));
8809 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8810 END_PROFILE(SMBtrans2
);
8815 if ((dscnt
> state
->total_data
) || (pscnt
> state
->total_param
))
8818 if (state
->total_data
) {
8820 if (trans_oob(state
->total_data
, 0, dscnt
)
8821 || trans_oob(smb_len(req
->inbuf
), dsoff
, dscnt
)) {
8825 /* Can't use talloc here, the core routines do realloc on the
8826 * params and data. */
8827 state
->data
= (char *)SMB_MALLOC(state
->total_data
);
8828 if (state
->data
== NULL
) {
8829 DEBUG(0,("reply_trans2: data malloc fail for %u "
8830 "bytes !\n", (unsigned int)state
->total_data
));
8832 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8833 END_PROFILE(SMBtrans2
);
8837 memcpy(state
->data
,smb_base(req
->inbuf
)+dsoff
,dscnt
);
8840 if (state
->total_param
) {
8842 if (trans_oob(state
->total_param
, 0, pscnt
)
8843 || trans_oob(smb_len(req
->inbuf
), psoff
, pscnt
)) {
8847 /* Can't use talloc here, the core routines do realloc on the
8848 * params and data. */
8849 state
->param
= (char *)SMB_MALLOC(state
->total_param
);
8850 if (state
->param
== NULL
) {
8851 DEBUG(0,("reply_trans: param malloc fail for %u "
8852 "bytes !\n", (unsigned int)state
->total_param
));
8853 SAFE_FREE(state
->data
);
8855 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8856 END_PROFILE(SMBtrans2
);
8860 memcpy(state
->param
,smb_base(req
->inbuf
)+psoff
,pscnt
);
8863 state
->received_data
= dscnt
;
8864 state
->received_param
= pscnt
;
8866 if ((state
->received_param
== state
->total_param
) &&
8867 (state
->received_data
== state
->total_data
)) {
8869 handle_trans2(conn
, req
, state
);
8871 SAFE_FREE(state
->data
);
8872 SAFE_FREE(state
->param
);
8874 END_PROFILE(SMBtrans2
);
8878 DLIST_ADD(conn
->pending_trans
, state
);
8880 /* We need to send an interim response then receive the rest
8881 of the parameter/data bytes */
8882 reply_outbuf(req
, 0, 0);
8883 show_msg((char *)req
->outbuf
);
8884 END_PROFILE(SMBtrans2
);
8889 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
8890 SAFE_FREE(state
->data
);
8891 SAFE_FREE(state
->param
);
8893 END_PROFILE(SMBtrans2
);
8894 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8898 /****************************************************************************
8899 Reply to a SMBtranss2
8900 ****************************************************************************/
8902 void reply_transs2(struct smb_request
*req
)
8904 connection_struct
*conn
= req
->conn
;
8905 unsigned int pcnt
,poff
,dcnt
,doff
,pdisp
,ddisp
;
8906 struct trans_state
*state
;
8908 START_PROFILE(SMBtranss2
);
8910 show_msg((const char *)req
->inbuf
);
8912 /* Windows clients expect all replies to
8913 a transact secondary (SMBtranss2 0x33)
8914 to have a command code of transact
8915 (SMBtrans2 0x32). See bug #8989
8916 and also [MS-CIFS] section 2.2.4.47.2
8919 req
->cmd
= SMBtrans2
;
8922 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8923 END_PROFILE(SMBtranss2
);
8927 for (state
= conn
->pending_trans
; state
!= NULL
;
8928 state
= state
->next
) {
8929 if (state
->mid
== req
->mid
) {
8934 if ((state
== NULL
) || (state
->cmd
!= SMBtrans2
)) {
8935 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8936 END_PROFILE(SMBtranss2
);
8940 /* Revise state->total_param and state->total_data in case they have
8941 changed downwards */
8943 if (SVAL(req
->vwv
+0, 0) < state
->total_param
)
8944 state
->total_param
= SVAL(req
->vwv
+0, 0);
8945 if (SVAL(req
->vwv
+1, 0) < state
->total_data
)
8946 state
->total_data
= SVAL(req
->vwv
+1, 0);
8948 pcnt
= SVAL(req
->vwv
+2, 0);
8949 poff
= SVAL(req
->vwv
+3, 0);
8950 pdisp
= SVAL(req
->vwv
+4, 0);
8952 dcnt
= SVAL(req
->vwv
+5, 0);
8953 doff
= SVAL(req
->vwv
+6, 0);
8954 ddisp
= SVAL(req
->vwv
+7, 0);
8956 state
->received_param
+= pcnt
;
8957 state
->received_data
+= dcnt
;
8959 if ((state
->received_data
> state
->total_data
) ||
8960 (state
->received_param
> state
->total_param
))
8964 if (trans_oob(state
->total_param
, pdisp
, pcnt
)
8965 || trans_oob(smb_len(req
->inbuf
), poff
, pcnt
)) {
8968 memcpy(state
->param
+pdisp
,smb_base(req
->inbuf
)+poff
,pcnt
);
8972 if (trans_oob(state
->total_data
, ddisp
, dcnt
)
8973 || trans_oob(smb_len(req
->inbuf
), doff
, dcnt
)) {
8976 memcpy(state
->data
+ddisp
, smb_base(req
->inbuf
)+doff
,dcnt
);
8979 if ((state
->received_param
< state
->total_param
) ||
8980 (state
->received_data
< state
->total_data
)) {
8981 END_PROFILE(SMBtranss2
);
8985 handle_trans2(conn
, req
, state
);
8987 DLIST_REMOVE(conn
->pending_trans
, state
);
8988 SAFE_FREE(state
->data
);
8989 SAFE_FREE(state
->param
);
8992 END_PROFILE(SMBtranss2
);
8997 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
8998 DLIST_REMOVE(conn
->pending_trans
, state
);
8999 SAFE_FREE(state
->data
);
9000 SAFE_FREE(state
->param
);
9002 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
9003 END_PROFILE(SMBtranss2
);