2 Unix SMB/CIFS implementation.
3 SMB transaction2 handling
4 Copyright (C) Jeremy Allison 1994-2007
5 Copyright (C) Stefan (metze) Metzmacher 2003
6 Copyright (C) Volker Lendecke 2005-2007
7 Copyright (C) Steve French 2005
8 Copyright (C) James Peach 2006-2007
10 Extensively modified by Andrew Tridgell, 1995
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 3 of the License, or
15 (at your option) any later version.
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with this program. If not, see <http://www.gnu.org/licenses/>.
28 #include "system/filesys.h"
30 #include "smbd/smbd.h"
31 #include "smbd/globals.h"
32 #include "../libcli/auth/libcli_auth.h"
33 #include "../librpc/gen_ndr/xattr.h"
34 #include "../librpc/gen_ndr/ndr_security.h"
35 #include "../librpc/gen_ndr/open_files.h"
36 #include "libcli/security/security.h"
39 #include "smbprofile.h"
40 #include "rpc_server/srv_pipe_hnd.h"
43 #define DIR_ENTRY_SAFETY_MARGIN 4096
45 static char *store_file_unix_basic(connection_struct
*conn
,
48 const SMB_STRUCT_STAT
*psbuf
);
50 static char *store_file_unix_basic_info2(connection_struct
*conn
,
53 const SMB_STRUCT_STAT
*psbuf
);
55 /********************************************************************
56 The canonical "check access" based on object handle or path function.
57 ********************************************************************/
59 NTSTATUS
check_access(connection_struct
*conn
,
61 const struct smb_filename
*smb_fname
,
65 if (!(fsp
->access_mask
& access_mask
)) {
66 return NT_STATUS_ACCESS_DENIED
;
69 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
;
328 status
= get_ea_names_from_file(talloc_tos(), conn
, fsp
, fname
,
331 if (!NT_STATUS_IS_OK(status
)) {
335 if (num_names
== 0) {
340 for (i
=0; i
<num_names
; i
++) {
341 struct ea_list
*listp
;
344 if (strnequal(names
[i
], "system.", 7)
345 || samba_private_attr_name(names
[i
]))
349 * Filter out any underlying POSIX EA names
350 * that a Windows client can't handle.
352 if (!lp_posix_pathnames() &&
353 is_invalid_windows_ea_name(names
[i
])) {
357 listp
= talloc(mem_ctx
, struct ea_list
);
359 return NT_STATUS_NO_MEMORY
;
362 status
= get_ea_value(listp
, conn
, fsp
,
366 if (!NT_STATUS_IS_OK(status
)) {
371 if (listp
->ea
.value
.length
== 0) {
373 * We can never return a zero length EA.
374 * Windows reports the EA's as corrupted.
380 push_ascii_fstring(dos_ea_name
, listp
->ea
.name
);
383 4 + strlen(dos_ea_name
) + 1 + listp
->ea
.value
.length
;
385 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
386 "= %u\n", (unsigned int)*pea_total_len
, dos_ea_name
,
387 (unsigned int)listp
->ea
.value
.length
));
389 DLIST_ADD_END(ea_list_head
, listp
, struct ea_list
*);
393 /* Add on 4 for total length. */
394 if (*pea_total_len
) {
398 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
399 (unsigned int)*pea_total_len
));
401 *ea_list
= ea_list_head
;
405 static NTSTATUS
get_ea_list_from_file(TALLOC_CTX
*mem_ctx
, connection_struct
*conn
, files_struct
*fsp
,
406 const struct smb_filename
*smb_fname
, size_t *pea_total_len
, struct ea_list
**ea_list
)
411 if (!lp_ea_support(SNUM(conn
))) {
415 if (is_ntfs_stream_smb_fname(smb_fname
)) {
416 return NT_STATUS_INVALID_PARAMETER
;
419 return get_ea_list_from_file_path(mem_ctx
, conn
, fsp
, smb_fname
->base_name
, pea_total_len
, ea_list
);
422 /****************************************************************************
423 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
425 ****************************************************************************/
427 static unsigned int fill_ea_buffer(TALLOC_CTX
*mem_ctx
, char *pdata
, unsigned int total_data_size
,
428 connection_struct
*conn
, struct ea_list
*ea_list
)
430 unsigned int ret_data_size
= 4;
433 SMB_ASSERT(total_data_size
>= 4);
435 if (!lp_ea_support(SNUM(conn
))) {
440 for (p
= pdata
+ 4; ea_list
; ea_list
= ea_list
->next
) {
443 push_ascii_fstring(dos_ea_name
, ea_list
->ea
.name
);
444 dos_namelen
= strlen(dos_ea_name
);
445 if (dos_namelen
> 255 || dos_namelen
== 0) {
448 if (ea_list
->ea
.value
.length
> 65535) {
451 if (4 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
> total_data_size
) {
455 /* We know we have room. */
456 SCVAL(p
,0,ea_list
->ea
.flags
);
457 SCVAL(p
,1,dos_namelen
);
458 SSVAL(p
,2,ea_list
->ea
.value
.length
);
459 strlcpy(p
+4, dos_ea_name
, dos_namelen
+1);
460 memcpy( p
+ 4 + dos_namelen
+ 1, ea_list
->ea
.value
.data
, ea_list
->ea
.value
.length
);
462 total_data_size
-= 4 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
;
463 p
+= 4 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
;
466 ret_data_size
= PTR_DIFF(p
, pdata
);
467 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size
));
468 SIVAL(pdata
,0,ret_data_size
);
469 return ret_data_size
;
472 static NTSTATUS
fill_ea_chained_buffer(TALLOC_CTX
*mem_ctx
,
474 unsigned int total_data_size
,
475 unsigned int *ret_data_size
,
476 connection_struct
*conn
,
477 struct ea_list
*ea_list
)
479 uint8_t *p
= (uint8_t *)pdata
;
480 uint8_t *last_start
= NULL
;
481 bool do_store_data
= (pdata
!= NULL
);
485 if (!lp_ea_support(SNUM(conn
))) {
486 return NT_STATUS_NO_EAS_ON_FILE
;
489 for (; ea_list
; ea_list
= ea_list
->next
) {
495 if (last_start
!= NULL
&& do_store_data
) {
496 SIVAL(last_start
, 0, PTR_DIFF(p
, last_start
));
500 push_ascii_fstring(dos_ea_name
, ea_list
->ea
.name
);
501 dos_namelen
= strlen(dos_ea_name
);
502 if (dos_namelen
> 255 || dos_namelen
== 0) {
503 return NT_STATUS_INTERNAL_ERROR
;
505 if (ea_list
->ea
.value
.length
> 65535) {
506 return NT_STATUS_INTERNAL_ERROR
;
509 this_size
= 0x08 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
;
512 pad
= (4 - (this_size
% 4)) % 4;
517 if (this_size
> total_data_size
) {
518 return NT_STATUS_INFO_LENGTH_MISMATCH
;
521 /* We know we have room. */
522 SIVAL(p
, 0x00, 0); /* next offset */
523 SCVAL(p
, 0x04, ea_list
->ea
.flags
);
524 SCVAL(p
, 0x05, dos_namelen
);
525 SSVAL(p
, 0x06, ea_list
->ea
.value
.length
);
526 strlcpy((char *)(p
+0x08), dos_ea_name
, dos_namelen
+1);
527 memcpy(p
+ 0x08 + dos_namelen
+ 1, ea_list
->ea
.value
.data
, ea_list
->ea
.value
.length
);
529 memset(p
+ 0x08 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
,
533 total_data_size
-= this_size
;
539 *ret_data_size
= PTR_DIFF(p
, pdata
);
540 DEBUG(10,("fill_ea_chained_buffer: data_size = %u\n", *ret_data_size
));
544 static unsigned int estimate_ea_size(connection_struct
*conn
, files_struct
*fsp
, const struct smb_filename
*smb_fname
)
546 size_t total_ea_len
= 0;
548 struct ea_list
*ea_list
= NULL
;
550 if (!lp_ea_support(SNUM(conn
))) {
553 mem_ctx
= talloc_stackframe();
555 /* If this is a stream fsp, then we need to instead find the
556 * estimated ea len from the main file, not the stream
557 * (streams cannot have EAs), but the estimate isn't just 0 in
559 if (is_ntfs_stream_smb_fname(smb_fname
)) {
562 (void)get_ea_list_from_file_path(mem_ctx
, conn
, fsp
, smb_fname
->base_name
, &total_ea_len
, &ea_list
);
563 if(conn
->sconn
->using_smb2
) {
565 unsigned int ret_data_size
;
567 * We're going to be using fill_ea_chained_buffer() to
568 * marshall EA's - this size is significantly larger
569 * than the SMB1 buffer. Re-calculate the size without
572 status
= fill_ea_chained_buffer(mem_ctx
,
578 if (!NT_STATUS_IS_OK(status
)) {
581 total_ea_len
= ret_data_size
;
583 TALLOC_FREE(mem_ctx
);
587 /****************************************************************************
588 Ensure the EA name is case insensitive by matching any existing EA name.
589 ****************************************************************************/
591 static void canonicalize_ea_name(connection_struct
*conn
, files_struct
*fsp
, const char *fname
, fstring unix_ea_name
)
594 TALLOC_CTX
*mem_ctx
= talloc_tos();
595 struct ea_list
*ea_list
;
596 NTSTATUS status
= get_ea_list_from_file_path(mem_ctx
, conn
, fsp
, fname
, &total_ea_len
, &ea_list
);
597 if (!NT_STATUS_IS_OK(status
)) {
601 for (; ea_list
; ea_list
= ea_list
->next
) {
602 if (strequal(&unix_ea_name
[5], ea_list
->ea
.name
)) {
603 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
604 &unix_ea_name
[5], ea_list
->ea
.name
));
605 strlcpy(&unix_ea_name
[5], ea_list
->ea
.name
, sizeof(fstring
)-5);
611 /****************************************************************************
612 Set or delete an extended attribute.
613 ****************************************************************************/
615 NTSTATUS
set_ea(connection_struct
*conn
, files_struct
*fsp
,
616 const struct smb_filename
*smb_fname
, struct ea_list
*ea_list
)
621 if (!lp_ea_support(SNUM(conn
))) {
622 return NT_STATUS_EAS_NOT_SUPPORTED
;
625 status
= check_access(conn
, fsp
, smb_fname
, FILE_WRITE_EA
);
626 if (!NT_STATUS_IS_OK(status
)) {
630 /* Setting EAs on streams isn't supported. */
631 if (is_ntfs_stream_smb_fname(smb_fname
)) {
632 return NT_STATUS_INVALID_PARAMETER
;
636 * Filter out invalid Windows EA names - before
637 * we set *any* of them.
640 if (ea_list_has_invalid_name(ea_list
)) {
641 return STATUS_INVALID_EA_NAME
;
644 fname
= smb_fname
->base_name
;
646 for (;ea_list
; ea_list
= ea_list
->next
) {
648 fstring unix_ea_name
;
650 fstrcpy(unix_ea_name
, "user."); /* All EA's must start with user. */
651 fstrcat(unix_ea_name
, ea_list
->ea
.name
);
653 canonicalize_ea_name(conn
, fsp
, fname
, unix_ea_name
);
655 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name
, (unsigned int)ea_list
->ea
.value
.length
));
657 if (samba_private_attr_name(unix_ea_name
)) {
658 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name
));
659 return NT_STATUS_ACCESS_DENIED
;
662 if (ea_list
->ea
.value
.length
== 0) {
663 /* Remove the attribute. */
664 if (fsp
&& (fsp
->fh
->fd
!= -1)) {
665 DEBUG(10,("set_ea: deleting ea name %s on "
666 "file %s by file descriptor.\n",
667 unix_ea_name
, fsp_str_dbg(fsp
)));
668 ret
= SMB_VFS_FREMOVEXATTR(fsp
, unix_ea_name
);
670 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
671 unix_ea_name
, fname
));
672 ret
= SMB_VFS_REMOVEXATTR(conn
, fname
, unix_ea_name
);
675 /* Removing a non existent attribute always succeeds. */
676 if (ret
== -1 && errno
== ENOATTR
) {
677 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
683 if (fsp
&& (fsp
->fh
->fd
!= -1)) {
684 DEBUG(10,("set_ea: setting ea name %s on file "
685 "%s by file descriptor.\n",
686 unix_ea_name
, fsp_str_dbg(fsp
)));
687 ret
= SMB_VFS_FSETXATTR(fsp
, unix_ea_name
,
688 ea_list
->ea
.value
.data
, ea_list
->ea
.value
.length
, 0);
690 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
691 unix_ea_name
, fname
));
692 ret
= SMB_VFS_SETXATTR(conn
, fname
, unix_ea_name
,
693 ea_list
->ea
.value
.data
, ea_list
->ea
.value
.length
, 0);
699 if (errno
== ENOTSUP
) {
700 return NT_STATUS_EAS_NOT_SUPPORTED
;
703 return map_nt_error_from_unix(errno
);
709 /****************************************************************************
710 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
711 ****************************************************************************/
713 static struct ea_list
*read_ea_name_list(TALLOC_CTX
*ctx
, const char *pdata
, size_t data_size
)
715 struct ea_list
*ea_list_head
= NULL
;
716 size_t converted_size
, offset
= 0;
718 while (offset
+ 2 < data_size
) {
719 struct ea_list
*eal
= talloc_zero(ctx
, struct ea_list
);
720 unsigned int namelen
= CVAL(pdata
,offset
);
722 offset
++; /* Go past the namelen byte. */
724 /* integer wrap paranioa. */
725 if ((offset
+ namelen
< offset
) || (offset
+ namelen
< namelen
) ||
726 (offset
> data_size
) || (namelen
> data_size
) ||
727 (offset
+ namelen
>= data_size
)) {
730 /* Ensure the name is null terminated. */
731 if (pdata
[offset
+ namelen
] != '\0') {
734 if (!pull_ascii_talloc(ctx
, &eal
->ea
.name
, &pdata
[offset
],
736 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
737 "failed: %s", strerror(errno
)));
743 offset
+= (namelen
+ 1); /* Go past the name + terminating zero. */
744 DLIST_ADD_END(ea_list_head
, eal
, struct ea_list
*);
745 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal
->ea
.name
));
751 /****************************************************************************
752 Read one EA list entry from the buffer.
753 ****************************************************************************/
755 struct ea_list
*read_ea_list_entry(TALLOC_CTX
*ctx
, const char *pdata
, size_t data_size
, size_t *pbytes_used
)
757 struct ea_list
*eal
= talloc_zero(ctx
, struct ea_list
);
759 unsigned int namelen
;
760 size_t converted_size
;
770 eal
->ea
.flags
= CVAL(pdata
,0);
771 namelen
= CVAL(pdata
,1);
772 val_len
= SVAL(pdata
,2);
774 if (4 + namelen
+ 1 + val_len
> data_size
) {
778 /* Ensure the name is null terminated. */
779 if (pdata
[namelen
+ 4] != '\0') {
782 if (!pull_ascii_talloc(ctx
, &eal
->ea
.name
, pdata
+ 4, &converted_size
)) {
783 DEBUG(0,("read_ea_list_entry: pull_ascii_talloc failed: %s",
790 eal
->ea
.value
= data_blob_talloc(eal
, NULL
, (size_t)val_len
+ 1);
791 if (!eal
->ea
.value
.data
) {
795 memcpy(eal
->ea
.value
.data
, pdata
+ 4 + namelen
+ 1, val_len
);
797 /* Ensure we're null terminated just in case we print the value. */
798 eal
->ea
.value
.data
[val_len
] = '\0';
799 /* But don't count the null. */
800 eal
->ea
.value
.length
--;
803 *pbytes_used
= 4 + namelen
+ 1 + val_len
;
806 DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal
->ea
.name
));
807 dump_data(10, eal
->ea
.value
.data
, eal
->ea
.value
.length
);
812 /****************************************************************************
813 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
814 ****************************************************************************/
816 static struct ea_list
*read_ea_list(TALLOC_CTX
*ctx
, const char *pdata
, size_t data_size
)
818 struct ea_list
*ea_list_head
= NULL
;
820 size_t bytes_used
= 0;
822 while (offset
< data_size
) {
823 struct ea_list
*eal
= read_ea_list_entry(ctx
, pdata
+ offset
, data_size
- offset
, &bytes_used
);
829 DLIST_ADD_END(ea_list_head
, eal
, struct ea_list
*);
830 offset
+= bytes_used
;
836 /****************************************************************************
837 Count the total EA size needed.
838 ****************************************************************************/
840 static size_t ea_list_size(struct ea_list
*ealist
)
843 struct ea_list
*listp
;
846 for (listp
= ealist
; listp
; listp
= listp
->next
) {
847 push_ascii_fstring(dos_ea_name
, listp
->ea
.name
);
848 ret
+= 4 + strlen(dos_ea_name
) + 1 + listp
->ea
.value
.length
;
850 /* Add on 4 for total length. */
858 /****************************************************************************
859 Return a union of EA's from a file list and a list of names.
860 The TALLOC context for the two lists *MUST* be identical as we steal
861 memory from one list to add to another. JRA.
862 ****************************************************************************/
864 static struct ea_list
*ea_list_union(struct ea_list
*name_list
, struct ea_list
*file_list
, size_t *total_ea_len
)
866 struct ea_list
*nlistp
, *flistp
;
868 for (nlistp
= name_list
; nlistp
; nlistp
= nlistp
->next
) {
869 for (flistp
= file_list
; flistp
; flistp
= flistp
->next
) {
870 if (strequal(nlistp
->ea
.name
, flistp
->ea
.name
)) {
876 /* Copy the data from this entry. */
877 nlistp
->ea
.flags
= flistp
->ea
.flags
;
878 nlistp
->ea
.value
= flistp
->ea
.value
;
881 nlistp
->ea
.flags
= 0;
882 ZERO_STRUCT(nlistp
->ea
.value
);
886 *total_ea_len
= ea_list_size(name_list
);
890 /****************************************************************************
891 Send the required number of replies back.
892 We assume all fields other than the data fields are
893 set correctly for the type of call.
894 HACK ! Always assumes smb_setup field is zero.
895 ****************************************************************************/
897 void send_trans2_replies(connection_struct
*conn
,
898 struct smb_request
*req
,
906 /* As we are using a protocol > LANMAN1 then the max_send
907 variable must have been set in the sessetupX call.
908 This takes precedence over the max_xmit field in the
909 global struct. These different max_xmit variables should
910 be merged as this is now too confusing */
912 int data_to_send
= datasize
;
913 int params_to_send
= paramsize
;
915 const char *pp
= params
;
916 const char *pd
= pdata
;
917 int params_sent_thistime
, data_sent_thistime
, total_sent_thistime
;
918 int alignment_offset
= 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
919 int data_alignment_offset
= 0;
920 bool overflow
= False
;
921 struct smbd_server_connection
*sconn
= req
->sconn
;
922 int max_send
= sconn
->smb1
.sessions
.max_send
;
924 /* Modify the data_to_send and datasize and set the error if
925 we're trying to send more than max_data_bytes. We still send
926 the part of the packet(s) that fit. Strange, but needed
929 if (max_data_bytes
> 0 && datasize
> max_data_bytes
) {
930 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
931 max_data_bytes
, datasize
));
932 datasize
= data_to_send
= max_data_bytes
;
936 /* If there genuinely are no parameters or data to send just send the empty packet */
938 if(params_to_send
== 0 && data_to_send
== 0) {
939 reply_outbuf(req
, 10, 0);
940 if (NT_STATUS_V(status
)) {
943 ntstatus_to_dos(status
, &eclass
, &ecode
);
944 error_packet_set((char *)req
->outbuf
,
945 eclass
, ecode
, status
,
948 show_msg((char *)req
->outbuf
);
949 if (!srv_send_smb(sconn
,
952 IS_CONN_ENCRYPTED(conn
),
954 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
956 TALLOC_FREE(req
->outbuf
);
960 /* When sending params and data ensure that both are nicely aligned */
961 /* Only do this alignment when there is also data to send - else
962 can cause NT redirector problems. */
964 if (((params_to_send
% 4) != 0) && (data_to_send
!= 0))
965 data_alignment_offset
= 4 - (params_to_send
% 4);
967 /* Space is bufsize minus Netbios over TCP header minus SMB header */
968 /* The alignment_offset is to align the param bytes on an even byte
969 boundary. NT 4.0 Beta needs this to work correctly. */
971 useable_space
= max_send
- (smb_size
974 + data_alignment_offset
);
976 if (useable_space
< 0) {
977 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
978 "= %d!!!", useable_space
));
979 exit_server_cleanly("send_trans2_replies: Not enough space");
982 while (params_to_send
|| data_to_send
) {
983 /* Calculate whether we will totally or partially fill this packet */
985 total_sent_thistime
= params_to_send
+ data_to_send
;
987 /* We can never send more than useable_space */
989 * Note that 'useable_space' does not include the alignment offsets,
990 * but we must include the alignment offsets in the calculation of
991 * the length of the data we send over the wire, as the alignment offsets
992 * are sent here. Fix from Marc_Jacobsen@hp.com.
995 total_sent_thistime
= MIN(total_sent_thistime
, useable_space
);
997 reply_outbuf(req
, 10, total_sent_thistime
+ alignment_offset
998 + data_alignment_offset
);
1000 /* Set total params and data to be sent */
1001 SSVAL(req
->outbuf
,smb_tprcnt
,paramsize
);
1002 SSVAL(req
->outbuf
,smb_tdrcnt
,datasize
);
1004 /* Calculate how many parameters and data we can fit into
1005 * this packet. Parameters get precedence
1008 params_sent_thistime
= MIN(params_to_send
,useable_space
);
1009 data_sent_thistime
= useable_space
- params_sent_thistime
;
1010 data_sent_thistime
= MIN(data_sent_thistime
,data_to_send
);
1012 SSVAL(req
->outbuf
,smb_prcnt
, params_sent_thistime
);
1014 /* smb_proff is the offset from the start of the SMB header to the
1015 parameter bytes, however the first 4 bytes of outbuf are
1016 the Netbios over TCP header. Thus use smb_base() to subtract
1017 them from the calculation */
1019 SSVAL(req
->outbuf
,smb_proff
,
1020 ((smb_buf(req
->outbuf
)+alignment_offset
)
1021 - smb_base(req
->outbuf
)));
1023 if(params_sent_thistime
== 0)
1024 SSVAL(req
->outbuf
,smb_prdisp
,0);
1026 /* Absolute displacement of param bytes sent in this packet */
1027 SSVAL(req
->outbuf
,smb_prdisp
,pp
- params
);
1029 SSVAL(req
->outbuf
,smb_drcnt
, data_sent_thistime
);
1030 if(data_sent_thistime
== 0) {
1031 SSVAL(req
->outbuf
,smb_droff
,0);
1032 SSVAL(req
->outbuf
,smb_drdisp
, 0);
1034 /* The offset of the data bytes is the offset of the
1035 parameter bytes plus the number of parameters being sent this time */
1036 SSVAL(req
->outbuf
, smb_droff
,
1037 ((smb_buf(req
->outbuf
)+alignment_offset
)
1038 - smb_base(req
->outbuf
))
1039 + params_sent_thistime
+ data_alignment_offset
);
1040 SSVAL(req
->outbuf
,smb_drdisp
, pd
- pdata
);
1043 /* Initialize the padding for alignment */
1045 if (alignment_offset
!= 0) {
1046 memset(smb_buf(req
->outbuf
), 0, alignment_offset
);
1049 /* Copy the param bytes into the packet */
1051 if(params_sent_thistime
) {
1052 memcpy((smb_buf(req
->outbuf
)+alignment_offset
), pp
,
1053 params_sent_thistime
);
1056 /* Copy in the data bytes */
1057 if(data_sent_thistime
) {
1058 if (data_alignment_offset
!= 0) {
1059 memset((smb_buf(req
->outbuf
)+alignment_offset
+
1060 params_sent_thistime
), 0,
1061 data_alignment_offset
);
1063 memcpy(smb_buf(req
->outbuf
)+alignment_offset
1064 +params_sent_thistime
+data_alignment_offset
,
1065 pd
,data_sent_thistime
);
1068 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
1069 params_sent_thistime
, data_sent_thistime
, useable_space
));
1070 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
1071 params_to_send
, data_to_send
, paramsize
, datasize
));
1074 error_packet_set((char *)req
->outbuf
,
1075 ERRDOS
,ERRbufferoverflow
,
1076 STATUS_BUFFER_OVERFLOW
,
1078 } else if (NT_STATUS_V(status
)) {
1081 ntstatus_to_dos(status
, &eclass
, &ecode
);
1082 error_packet_set((char *)req
->outbuf
,
1083 eclass
, ecode
, status
,
1087 /* Send the packet */
1088 show_msg((char *)req
->outbuf
);
1089 if (!srv_send_smb(sconn
,
1090 (char *)req
->outbuf
,
1091 true, req
->seqnum
+1,
1092 IS_CONN_ENCRYPTED(conn
),
1094 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
1096 TALLOC_FREE(req
->outbuf
);
1098 pp
+= params_sent_thistime
;
1099 pd
+= data_sent_thistime
;
1101 params_to_send
-= params_sent_thistime
;
1102 data_to_send
-= data_sent_thistime
;
1105 if(params_to_send
< 0 || data_to_send
< 0) {
1106 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
1107 params_to_send
, data_to_send
));
1115 /****************************************************************************
1116 Reply to a TRANSACT2_OPEN.
1117 ****************************************************************************/
1119 static void call_trans2open(connection_struct
*conn
,
1120 struct smb_request
*req
,
1121 char **pparams
, int total_params
,
1122 char **ppdata
, int total_data
,
1123 unsigned int max_data_bytes
)
1125 struct smb_filename
*smb_fname
= NULL
;
1126 char *params
= *pparams
;
1127 char *pdata
= *ppdata
;
1130 bool oplock_request
;
1132 bool return_additional_info
;
1141 int fattr
=0,mtime
=0;
1142 SMB_INO_T inode
= 0;
1145 struct ea_list
*ea_list
= NULL
;
1150 uint32 create_disposition
;
1151 uint32 create_options
= 0;
1152 uint32_t private_flags
= 0;
1153 TALLOC_CTX
*ctx
= talloc_tos();
1156 * Ensure we have enough parameters to perform the operation.
1159 if (total_params
< 29) {
1160 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1164 flags
= SVAL(params
, 0);
1165 deny_mode
= SVAL(params
, 2);
1166 open_attr
= SVAL(params
,6);
1167 oplock_request
= (flags
& REQUEST_OPLOCK
) ? EXCLUSIVE_OPLOCK
: 0;
1168 if (oplock_request
) {
1169 oplock_request
|= (flags
& REQUEST_BATCH_OPLOCK
) ? BATCH_OPLOCK
: 0;
1173 return_additional_info
= BITSETW(params
,0);
1174 open_sattr
= SVAL(params
, 4);
1175 open_time
= make_unix_date3(params
+8);
1177 open_ofun
= SVAL(params
,12);
1178 open_size
= IVAL(params
,14);
1179 pname
= ¶ms
[28];
1182 reply_nterror(req
, NT_STATUS_NETWORK_ACCESS_DENIED
);
1186 srvstr_get_path(ctx
, params
, req
->flags2
, &fname
, pname
,
1187 total_params
- 28, STR_TERMINATE
,
1189 if (!NT_STATUS_IS_OK(status
)) {
1190 reply_nterror(req
, status
);
1194 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
1195 fname
, (unsigned int)deny_mode
, (unsigned int)open_attr
,
1196 (unsigned int)open_ofun
, open_size
));
1198 status
= filename_convert(ctx
,
1200 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
1205 if (!NT_STATUS_IS_OK(status
)) {
1206 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
1207 reply_botherror(req
,
1208 NT_STATUS_PATH_NOT_COVERED
,
1209 ERRSRV
, ERRbadpath
);
1212 reply_nterror(req
, status
);
1216 if (open_ofun
== 0) {
1217 reply_nterror(req
, NT_STATUS_OBJECT_NAME_COLLISION
);
1221 if (!map_open_params_to_ntcreate(smb_fname
->base_name
, deny_mode
,
1223 &access_mask
, &share_mode
,
1224 &create_disposition
,
1227 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
1231 /* Any data in this call is an EA list. */
1232 if (total_data
&& (total_data
!= 4)) {
1233 if (total_data
< 10) {
1234 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1238 if (IVAL(pdata
,0) > total_data
) {
1239 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
1240 IVAL(pdata
,0), (unsigned int)total_data
));
1241 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1245 ea_list
= read_ea_list(talloc_tos(), pdata
+ 4,
1248 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1252 if (!lp_ea_support(SNUM(conn
))) {
1253 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
1257 if (ea_list_has_invalid_name(ea_list
)) {
1259 *pparams
= (char *)SMB_REALLOC(*pparams
, param_len
);
1260 if(*pparams
== NULL
) {
1261 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1265 memset(params
, '\0', param_len
);
1266 send_trans2_replies(conn
, req
, STATUS_INVALID_EA_NAME
,
1267 params
, param_len
, NULL
, 0, max_data_bytes
);
1272 status
= SMB_VFS_CREATE_FILE(
1275 0, /* root_dir_fid */
1276 smb_fname
, /* fname */
1277 access_mask
, /* access_mask */
1278 share_mode
, /* share_access */
1279 create_disposition
, /* create_disposition*/
1280 create_options
, /* create_options */
1281 open_attr
, /* file_attributes */
1282 oplock_request
, /* oplock_request */
1283 open_size
, /* allocation_size */
1286 ea_list
, /* ea_list */
1288 &smb_action
); /* psbuf */
1290 if (!NT_STATUS_IS_OK(status
)) {
1291 if (open_was_deferred(req
->sconn
, req
->mid
)) {
1292 /* We have re-scheduled this call. */
1295 reply_openerror(req
, status
);
1299 size
= get_file_size_stat(&smb_fname
->st
);
1300 fattr
= dos_mode(conn
, smb_fname
);
1301 mtime
= convert_timespec_to_time_t(smb_fname
->st
.st_ex_mtime
);
1302 inode
= smb_fname
->st
.st_ex_ino
;
1303 if (fattr
& FILE_ATTRIBUTE_DIRECTORY
) {
1304 close_file(req
, fsp
, ERROR_CLOSE
);
1305 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
1309 /* Realloc the size of parameters and data we will return */
1310 *pparams
= (char *)SMB_REALLOC(*pparams
, 30);
1311 if(*pparams
== NULL
) {
1312 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1317 SSVAL(params
,0,fsp
->fnum
);
1318 SSVAL(params
,2,fattr
);
1319 srv_put_dos_date2(params
,4, mtime
);
1320 SIVAL(params
,8, (uint32
)size
);
1321 SSVAL(params
,12,deny_mode
);
1322 SSVAL(params
,14,0); /* open_type - file or directory. */
1323 SSVAL(params
,16,0); /* open_state - only valid for IPC device. */
1325 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
1326 smb_action
|= EXTENDED_OPLOCK_GRANTED
;
1329 SSVAL(params
,18,smb_action
);
1332 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1334 SIVAL(params
,20,inode
);
1335 SSVAL(params
,24,0); /* Padding. */
1337 uint32 ea_size
= estimate_ea_size(conn
, fsp
,
1339 SIVAL(params
, 26, ea_size
);
1341 SIVAL(params
, 26, 0);
1344 /* Send the required number of replies */
1345 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 30, *ppdata
, 0, max_data_bytes
);
1347 TALLOC_FREE(smb_fname
);
1350 /*********************************************************
1351 Routine to check if a given string matches exactly.
1352 as a special case a mask of "." does NOT match. That
1353 is required for correct wildcard semantics
1354 Case can be significant or not.
1355 **********************************************************/
1357 static bool exact_match(bool has_wild
,
1358 bool case_sensitive
,
1362 if (mask
[0] == '.' && mask
[1] == 0) {
1370 if (case_sensitive
) {
1371 return strcmp(str
,mask
)==0;
1373 return strcasecmp_m(str
,mask
) == 0;
1377 /****************************************************************************
1378 Return the filetype for UNIX extensions.
1379 ****************************************************************************/
1381 static uint32
unix_filetype(mode_t mode
)
1384 return UNIX_TYPE_FILE
;
1385 else if(S_ISDIR(mode
))
1386 return UNIX_TYPE_DIR
;
1388 else if(S_ISLNK(mode
))
1389 return UNIX_TYPE_SYMLINK
;
1392 else if(S_ISCHR(mode
))
1393 return UNIX_TYPE_CHARDEV
;
1396 else if(S_ISBLK(mode
))
1397 return UNIX_TYPE_BLKDEV
;
1400 else if(S_ISFIFO(mode
))
1401 return UNIX_TYPE_FIFO
;
1404 else if(S_ISSOCK(mode
))
1405 return UNIX_TYPE_SOCKET
;
1408 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode
));
1409 return UNIX_TYPE_UNKNOWN
;
1412 /****************************************************************************
1413 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1414 ****************************************************************************/
1416 enum perm_type
{ PERM_NEW_FILE
, PERM_NEW_DIR
, PERM_EXISTING_FILE
, PERM_EXISTING_DIR
};
1418 static NTSTATUS
unix_perms_from_wire( connection_struct
*conn
,
1419 const SMB_STRUCT_STAT
*psbuf
,
1421 enum perm_type ptype
,
1426 if (perms
== SMB_MODE_NO_CHANGE
) {
1427 if (!VALID_STAT(*psbuf
)) {
1428 return NT_STATUS_INVALID_PARAMETER
;
1430 *ret_perms
= psbuf
->st_ex_mode
;
1431 return NT_STATUS_OK
;
1435 ret
|= ((perms
& UNIX_X_OTH
) ? S_IXOTH
: 0);
1436 ret
|= ((perms
& UNIX_W_OTH
) ? S_IWOTH
: 0);
1437 ret
|= ((perms
& UNIX_R_OTH
) ? S_IROTH
: 0);
1438 ret
|= ((perms
& UNIX_X_GRP
) ? S_IXGRP
: 0);
1439 ret
|= ((perms
& UNIX_W_GRP
) ? S_IWGRP
: 0);
1440 ret
|= ((perms
& UNIX_R_GRP
) ? S_IRGRP
: 0);
1441 ret
|= ((perms
& UNIX_X_USR
) ? S_IXUSR
: 0);
1442 ret
|= ((perms
& UNIX_W_USR
) ? S_IWUSR
: 0);
1443 ret
|= ((perms
& UNIX_R_USR
) ? S_IRUSR
: 0);
1445 ret
|= ((perms
& UNIX_STICKY
) ? S_ISVTX
: 0);
1448 ret
|= ((perms
& UNIX_SET_GID
) ? S_ISGID
: 0);
1451 ret
|= ((perms
& UNIX_SET_UID
) ? S_ISUID
: 0);
1454 if (ptype
== PERM_NEW_FILE
) {
1456 * "create mask"/"force create mode" are
1457 * only applied to new files, not existing ones.
1459 ret
&= lp_create_mask(SNUM(conn
));
1460 /* Add in force bits */
1461 ret
|= lp_force_create_mode(SNUM(conn
));
1462 } else if (ptype
== PERM_NEW_DIR
) {
1464 * "directory mask"/"force directory mode" are
1465 * only applied to new directories, not existing ones.
1467 ret
&= lp_dir_mask(SNUM(conn
));
1468 /* Add in force bits */
1469 ret
|= lp_force_dir_mode(SNUM(conn
));
1473 return NT_STATUS_OK
;
1476 /****************************************************************************
1477 Needed to show the msdfs symlinks as directories. Modifies psbuf
1478 to be a directory if it's a msdfs link.
1479 ****************************************************************************/
1481 static bool check_msdfs_link(connection_struct
*conn
,
1482 const char *pathname
,
1483 SMB_STRUCT_STAT
*psbuf
)
1485 int saved_errno
= errno
;
1486 if(lp_host_msdfs() &&
1487 lp_msdfs_root(SNUM(conn
)) &&
1488 is_msdfs_link(conn
, pathname
, psbuf
)) {
1490 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1493 psbuf
->st_ex_mode
= (psbuf
->st_ex_mode
& 0xFFF) | S_IFDIR
;
1494 errno
= saved_errno
;
1497 errno
= saved_errno
;
1502 /****************************************************************************
1503 Get a level dependent lanman2 dir entry.
1504 ****************************************************************************/
1506 struct smbd_dirptr_lanman2_state
{
1507 connection_struct
*conn
;
1508 uint32_t info_level
;
1509 bool check_mangled_names
;
1511 bool got_exact_match
;
1514 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX
*ctx
,
1520 struct smbd_dirptr_lanman2_state
*state
=
1521 (struct smbd_dirptr_lanman2_state
*)private_data
;
1523 char mangled_name
[13]; /* mangled 8.3 name. */
1527 /* Mangle fname if it's an illegal name. */
1528 if (mangle_must_mangle(dname
, state
->conn
->params
)) {
1529 ok
= name_to_8_3(dname
, mangled_name
,
1530 true, state
->conn
->params
);
1534 fname
= mangled_name
;
1539 got_match
= exact_match(state
->has_wild
,
1540 state
->conn
->case_sensitive
,
1542 state
->got_exact_match
= got_match
;
1544 got_match
= mask_match(fname
, mask
,
1545 state
->conn
->case_sensitive
);
1548 if(!got_match
&& state
->check_mangled_names
&&
1549 !mangle_is_8_3(fname
, false, state
->conn
->params
)) {
1551 * It turns out that NT matches wildcards against
1552 * both long *and* short names. This may explain some
1553 * of the wildcard wierdness from old DOS clients
1554 * that some people have been seeing.... JRA.
1556 /* Force the mangling into 8.3. */
1557 ok
= name_to_8_3(fname
, mangled_name
,
1558 false, state
->conn
->params
);
1563 got_match
= exact_match(state
->has_wild
,
1564 state
->conn
->case_sensitive
,
1565 mangled_name
, mask
);
1566 state
->got_exact_match
= got_match
;
1568 got_match
= mask_match(mangled_name
, mask
,
1569 state
->conn
->case_sensitive
);
1577 *_fname
= talloc_strdup(ctx
, fname
);
1578 if (*_fname
== NULL
) {
1585 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX
*ctx
,
1587 struct smb_filename
*smb_fname
,
1590 struct smbd_dirptr_lanman2_state
*state
=
1591 (struct smbd_dirptr_lanman2_state
*)private_data
;
1592 bool ms_dfs_link
= false;
1595 if (INFO_LEVEL_IS_UNIX(state
->info_level
)) {
1596 if (SMB_VFS_LSTAT(state
->conn
, smb_fname
) != 0) {
1597 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1598 "Couldn't lstat [%s] (%s)\n",
1599 smb_fname_str_dbg(smb_fname
),
1603 } else if (!VALID_STAT(smb_fname
->st
) &&
1604 SMB_VFS_STAT(state
->conn
, smb_fname
) != 0) {
1605 /* Needed to show the msdfs symlinks as
1608 ms_dfs_link
= check_msdfs_link(state
->conn
,
1609 smb_fname
->base_name
,
1612 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1613 "Couldn't stat [%s] (%s)\n",
1614 smb_fname_str_dbg(smb_fname
),
1621 mode
= dos_mode_msdfs(state
->conn
, smb_fname
);
1623 mode
= dos_mode(state
->conn
, smb_fname
);
1630 static bool smbd_marshall_dir_entry(TALLOC_CTX
*ctx
,
1631 connection_struct
*conn
,
1633 uint32_t info_level
,
1634 struct ea_list
*name_list
,
1635 bool check_mangled_names
,
1636 bool requires_resume_key
,
1639 const struct smb_filename
*smb_fname
,
1640 int space_remaining
,
1647 uint64_t *last_entry_off
)
1649 char *p
, *q
, *pdata
= *ppdata
;
1651 uint64_t file_size
= 0;
1652 uint64_t allocation_size
= 0;
1653 uint64_t file_index
= 0;
1655 struct timespec mdate_ts
, adate_ts
, cdate_ts
, create_date_ts
;
1656 time_t mdate
= (time_t)0, adate
= (time_t)0, create_date
= (time_t)0;
1658 char *last_entry_ptr
;
1663 *out_of_space
= false;
1665 ZERO_STRUCT(mdate_ts
);
1666 ZERO_STRUCT(adate_ts
);
1667 ZERO_STRUCT(create_date_ts
);
1668 ZERO_STRUCT(cdate_ts
);
1670 if (!(mode
& FILE_ATTRIBUTE_DIRECTORY
)) {
1671 file_size
= get_file_size_stat(&smb_fname
->st
);
1673 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
, NULL
, &smb_fname
->st
);
1675 file_index
= get_FileIndex(conn
, &smb_fname
->st
);
1677 mdate_ts
= smb_fname
->st
.st_ex_mtime
;
1678 adate_ts
= smb_fname
->st
.st_ex_atime
;
1679 create_date_ts
= get_create_timespec(conn
, NULL
, smb_fname
);
1680 cdate_ts
= get_change_timespec(conn
, NULL
, smb_fname
);
1682 if (lp_dos_filetime_resolution(SNUM(conn
))) {
1683 dos_filetime_timespec(&create_date_ts
);
1684 dos_filetime_timespec(&mdate_ts
);
1685 dos_filetime_timespec(&adate_ts
);
1686 dos_filetime_timespec(&cdate_ts
);
1689 create_date
= convert_timespec_to_time_t(create_date_ts
);
1690 mdate
= convert_timespec_to_time_t(mdate_ts
);
1691 adate
= convert_timespec_to_time_t(adate_ts
);
1693 /* align the record */
1694 SMB_ASSERT(align
>= 1);
1696 off
= (int)PTR_DIFF(pdata
, base_data
);
1697 pad
= (off
+ (align
-1)) & ~(align
-1);
1700 if (pad
&& pad
> space_remaining
) {
1701 *out_of_space
= true;
1702 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1703 "for padding (wanted %u, had %d)\n",
1706 return false; /* Not finished - just out of space */
1710 /* initialize padding to 0 */
1712 memset(pdata
, 0, pad
);
1714 space_remaining
-= pad
;
1716 DEBUG(10,("smbd_marshall_dir_entry: space_remaining = %d\n",
1726 switch (info_level
) {
1727 case SMB_FIND_INFO_STANDARD
:
1728 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1729 if(requires_resume_key
) {
1733 srv_put_dos_date2(p
,0,create_date
);
1734 srv_put_dos_date2(p
,4,adate
);
1735 srv_put_dos_date2(p
,8,mdate
);
1736 SIVAL(p
,12,(uint32
)file_size
);
1737 SIVAL(p
,16,(uint32
)allocation_size
);
1741 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1742 p
+= ucs2_align(base_data
, p
, 0);
1744 len
= srvstr_push(base_data
, flags2
, p
,
1745 fname
, PTR_DIFF(end_data
, p
),
1747 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1749 SCVAL(nameptr
, -1, len
- 2);
1751 SCVAL(nameptr
, -1, 0);
1755 SCVAL(nameptr
, -1, len
- 1);
1757 SCVAL(nameptr
, -1, 0);
1763 case SMB_FIND_EA_SIZE
:
1764 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
1765 if (requires_resume_key
) {
1769 srv_put_dos_date2(p
,0,create_date
);
1770 srv_put_dos_date2(p
,4,adate
);
1771 srv_put_dos_date2(p
,8,mdate
);
1772 SIVAL(p
,12,(uint32
)file_size
);
1773 SIVAL(p
,16,(uint32
)allocation_size
);
1776 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
1778 SIVAL(p
,22,ea_size
); /* Extended attributes */
1782 len
= srvstr_push(base_data
, flags2
,
1783 p
, fname
, PTR_DIFF(end_data
, p
),
1784 STR_TERMINATE
| STR_NOALIGN
);
1785 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1798 SCVAL(nameptr
,0,len
);
1800 SCVAL(p
,0,0); p
+= 1; /* Extra zero byte ? - why.. */
1803 case SMB_FIND_EA_LIST
:
1805 struct ea_list
*file_list
= NULL
;
1809 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
1813 if (requires_resume_key
) {
1817 srv_put_dos_date2(p
,0,create_date
);
1818 srv_put_dos_date2(p
,4,adate
);
1819 srv_put_dos_date2(p
,8,mdate
);
1820 SIVAL(p
,12,(uint32
)file_size
);
1821 SIVAL(p
,16,(uint32
)allocation_size
);
1823 p
+= 22; /* p now points to the EA area. */
1825 status
= get_ea_list_from_file(ctx
, conn
, NULL
,
1827 &ea_len
, &file_list
);
1828 if (!NT_STATUS_IS_OK(status
)) {
1831 name_list
= ea_list_union(name_list
, file_list
, &ea_len
);
1833 /* We need to determine if this entry will fit in the space available. */
1834 /* Max string size is 255 bytes. */
1835 if (PTR_DIFF(p
+ 255 + ea_len
,pdata
) > space_remaining
) {
1836 *out_of_space
= true;
1837 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1838 "(wanted %u, had %d)\n",
1839 (unsigned int)PTR_DIFF(p
+ 255 + ea_len
,pdata
),
1841 return False
; /* Not finished - just out of space */
1844 /* Push the ea_data followed by the name. */
1845 p
+= fill_ea_buffer(ctx
, p
, space_remaining
, conn
, name_list
);
1847 len
= srvstr_push(base_data
, flags2
,
1848 p
+ 1, fname
, PTR_DIFF(end_data
, p
+1),
1849 STR_TERMINATE
| STR_NOALIGN
);
1850 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1863 SCVAL(nameptr
,0,len
);
1865 SCVAL(p
,0,0); p
+= 1; /* Extra zero byte ? - why.. */
1869 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
1870 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1871 was_8_3
= mangle_is_8_3(fname
, True
, conn
->params
);
1873 SIVAL(p
,0,reskey
); p
+= 4;
1874 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
1875 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
1876 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
1877 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
1878 SOFF_T(p
,0,file_size
); p
+= 8;
1879 SOFF_T(p
,0,allocation_size
); p
+= 8;
1880 SIVAL(p
,0,mode
); p
+= 4;
1881 q
= p
; p
+= 4; /* q is placeholder for name length. */
1882 if (mode
& FILE_ATTRIBUTE_REPARSE_POINT
) {
1883 SIVAL(p
, 0, IO_REPARSE_TAG_DFS
);
1885 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
1887 SIVAL(p
,0,ea_size
); /* Extended attributes */
1890 /* Clear the short name buffer. This is
1891 * IMPORTANT as not doing so will trigger
1892 * a Win2k client bug. JRA.
1894 if (!was_8_3
&& check_mangled_names
) {
1895 char mangled_name
[13]; /* mangled 8.3 name. */
1896 if (!name_to_8_3(fname
,mangled_name
,True
,
1898 /* Error - mangle failed ! */
1899 memset(mangled_name
,'\0',12);
1901 mangled_name
[12] = 0;
1902 len
= srvstr_push(base_data
, flags2
,
1903 p
+2, mangled_name
, 24,
1904 STR_UPPER
|STR_UNICODE
);
1906 memset(p
+ 2 + len
,'\0',24 - len
);
1913 len
= srvstr_push(base_data
, flags2
, p
,
1914 fname
, PTR_DIFF(end_data
, p
),
1915 STR_TERMINATE_ASCII
);
1919 len
= PTR_DIFF(p
, pdata
);
1920 pad
= (len
+ (align
-1)) & ~(align
-1);
1922 * offset to the next entry, the caller
1923 * will overwrite it for the last entry
1924 * that's why we always include the padding
1928 * set padding to zero
1931 memset(p
, 0, pad
- len
);
1938 case SMB_FIND_FILE_DIRECTORY_INFO
:
1939 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1941 SIVAL(p
,0,reskey
); p
+= 4;
1942 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
1943 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
1944 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
1945 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
1946 SOFF_T(p
,0,file_size
); p
+= 8;
1947 SOFF_T(p
,0,allocation_size
); p
+= 8;
1948 SIVAL(p
,0,mode
); p
+= 4;
1949 len
= srvstr_push(base_data
, flags2
,
1950 p
+ 4, fname
, PTR_DIFF(end_data
, p
+4),
1951 STR_TERMINATE_ASCII
);
1955 len
= PTR_DIFF(p
, pdata
);
1956 pad
= (len
+ (align
-1)) & ~(align
-1);
1958 * offset to the next entry, the caller
1959 * will overwrite it for the last entry
1960 * that's why we always include the padding
1964 * set padding to zero
1967 memset(p
, 0, pad
- len
);
1974 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
1975 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1977 SIVAL(p
,0,reskey
); p
+= 4;
1978 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
1979 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
1980 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
1981 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
1982 SOFF_T(p
,0,file_size
); p
+= 8;
1983 SOFF_T(p
,0,allocation_size
); p
+= 8;
1984 SIVAL(p
,0,mode
); p
+= 4;
1985 q
= p
; p
+= 4; /* q is placeholder for name length. */
1987 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
1989 SIVAL(p
,0,ea_size
); /* Extended attributes */
1992 len
= srvstr_push(base_data
, flags2
, p
,
1993 fname
, PTR_DIFF(end_data
, p
),
1994 STR_TERMINATE_ASCII
);
1998 len
= PTR_DIFF(p
, pdata
);
1999 pad
= (len
+ (align
-1)) & ~(align
-1);
2001 * offset to the next entry, the caller
2002 * will overwrite it for the last entry
2003 * that's why we always include the padding
2007 * set padding to zero
2010 memset(p
, 0, pad
- len
);
2017 case SMB_FIND_FILE_NAMES_INFO
:
2018 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
2020 SIVAL(p
,0,reskey
); p
+= 4;
2022 /* this must *not* be null terminated or w2k gets in a loop trying to set an
2023 acl on a dir (tridge) */
2024 len
= srvstr_push(base_data
, flags2
, p
,
2025 fname
, PTR_DIFF(end_data
, p
),
2026 STR_TERMINATE_ASCII
);
2030 len
= PTR_DIFF(p
, pdata
);
2031 pad
= (len
+ (align
-1)) & ~(align
-1);
2033 * offset to the next entry, the caller
2034 * will overwrite it for the last entry
2035 * that's why we always include the padding
2039 * set padding to zero
2042 memset(p
, 0, pad
- len
);
2049 case SMB_FIND_ID_FULL_DIRECTORY_INFO
:
2050 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
2052 SIVAL(p
,0,reskey
); p
+= 4;
2053 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
2054 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
2055 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
2056 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
2057 SOFF_T(p
,0,file_size
); p
+= 8;
2058 SOFF_T(p
,0,allocation_size
); p
+= 8;
2059 SIVAL(p
,0,mode
); p
+= 4;
2060 q
= p
; p
+= 4; /* q is placeholder for name length. */
2061 if (mode
& FILE_ATTRIBUTE_REPARSE_POINT
) {
2062 SIVAL(p
, 0, IO_REPARSE_TAG_DFS
);
2064 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
2066 SIVAL(p
,0,ea_size
); /* Extended attributes */
2069 SIVAL(p
,0,0); p
+= 4; /* Unknown - reserved ? */
2070 SBVAL(p
,0,file_index
); p
+= 8;
2071 len
= srvstr_push(base_data
, flags2
, p
,
2072 fname
, PTR_DIFF(end_data
, p
),
2073 STR_TERMINATE_ASCII
);
2077 len
= PTR_DIFF(p
, pdata
);
2078 pad
= (len
+ (align
-1)) & ~(align
-1);
2080 * offset to the next entry, the caller
2081 * will overwrite it for the last entry
2082 * that's why we always include the padding
2086 * set padding to zero
2089 memset(p
, 0, pad
- len
);
2096 case SMB_FIND_ID_BOTH_DIRECTORY_INFO
:
2097 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
2098 was_8_3
= mangle_is_8_3(fname
, True
, conn
->params
);
2100 SIVAL(p
,0,reskey
); p
+= 4;
2101 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
2102 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
2103 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
2104 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
2105 SOFF_T(p
,0,file_size
); p
+= 8;
2106 SOFF_T(p
,0,allocation_size
); p
+= 8;
2107 SIVAL(p
,0,mode
); p
+= 4;
2108 q
= p
; p
+= 4; /* q is placeholder for name length */
2109 if (mode
& FILE_ATTRIBUTE_REPARSE_POINT
) {
2110 SIVAL(p
, 0, IO_REPARSE_TAG_DFS
);
2112 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
2114 SIVAL(p
,0,ea_size
); /* Extended attributes */
2117 /* Clear the short name buffer. This is
2118 * IMPORTANT as not doing so will trigger
2119 * a Win2k client bug. JRA.
2121 if (!was_8_3
&& check_mangled_names
) {
2122 char mangled_name
[13]; /* mangled 8.3 name. */
2123 if (!name_to_8_3(fname
,mangled_name
,True
,
2125 /* Error - mangle failed ! */
2126 memset(mangled_name
,'\0',12);
2128 mangled_name
[12] = 0;
2129 len
= srvstr_push(base_data
, flags2
,
2130 p
+2, mangled_name
, 24,
2131 STR_UPPER
|STR_UNICODE
);
2134 memset(p
+ 2 + len
,'\0',24 - len
);
2141 SSVAL(p
,0,0); p
+= 2; /* Reserved ? */
2142 SBVAL(p
,0,file_index
); p
+= 8;
2143 len
= srvstr_push(base_data
, flags2
, p
,
2144 fname
, PTR_DIFF(end_data
, p
),
2145 STR_TERMINATE_ASCII
);
2149 len
= PTR_DIFF(p
, pdata
);
2150 pad
= (len
+ (align
-1)) & ~(align
-1);
2152 * offset to the next entry, the caller
2153 * will overwrite it for the last entry
2154 * that's why we always include the padding
2158 * set padding to zero
2161 memset(p
, 0, pad
- len
);
2168 /* CIFS UNIX Extension. */
2170 case SMB_FIND_FILE_UNIX
:
2171 case SMB_FIND_FILE_UNIX_INFO2
:
2173 SIVAL(p
,0,reskey
); p
+= 4; /* Used for continuing search. */
2175 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
2177 if (info_level
== SMB_FIND_FILE_UNIX
) {
2178 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
2179 p
= store_file_unix_basic(conn
, p
,
2180 NULL
, &smb_fname
->st
);
2181 len
= srvstr_push(base_data
, flags2
, p
,
2182 fname
, PTR_DIFF(end_data
, p
),
2185 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
2186 p
= store_file_unix_basic_info2(conn
, p
,
2187 NULL
, &smb_fname
->st
);
2190 len
= srvstr_push(base_data
, flags2
, p
, fname
,
2191 PTR_DIFF(end_data
, p
), 0);
2192 SIVAL(nameptr
, 0, len
);
2197 len
= PTR_DIFF(p
, pdata
);
2198 pad
= (len
+ (align
-1)) & ~(align
-1);
2200 * offset to the next entry, the caller
2201 * will overwrite it for the last entry
2202 * that's why we always include the padding
2206 * set padding to zero
2209 memset(p
, 0, pad
- len
);
2214 /* End of SMB_QUERY_FILE_UNIX_BASIC */
2222 if (PTR_DIFF(p
,pdata
) > space_remaining
) {
2223 *out_of_space
= true;
2224 DEBUG(9,("smbd_marshall_dir_entry: out of space "
2225 "(wanted %u, had %d)\n",
2226 (unsigned int)PTR_DIFF(p
,pdata
),
2228 return false; /* Not finished - just out of space */
2231 /* Setup the last entry pointer, as an offset from base_data */
2232 *last_entry_off
= PTR_DIFF(last_entry_ptr
,base_data
);
2233 /* Advance the data pointer to the next slot */
2239 bool smbd_dirptr_lanman2_entry(TALLOC_CTX
*ctx
,
2240 connection_struct
*conn
,
2241 struct dptr_struct
*dirptr
,
2243 const char *path_mask
,
2246 int requires_resume_key
,
2254 int space_remaining
,
2256 bool *got_exact_match
,
2257 int *_last_entry_off
,
2258 struct ea_list
*name_list
)
2261 const char *mask
= NULL
;
2262 long prev_dirpos
= 0;
2265 struct smb_filename
*smb_fname
= NULL
;
2266 struct smbd_dirptr_lanman2_state state
;
2268 uint64_t last_entry_off
= 0;
2272 state
.info_level
= info_level
;
2273 state
.check_mangled_names
= lp_manglednames(conn
->params
);
2274 state
.has_wild
= dptr_has_wild(dirptr
);
2275 state
.got_exact_match
= false;
2277 *out_of_space
= false;
2278 *got_exact_match
= false;
2280 p
= strrchr_m(path_mask
,'/');
2291 ok
= smbd_dirptr_get_entry(ctx
,
2297 smbd_dirptr_lanman2_match_fn
,
2298 smbd_dirptr_lanman2_mode_fn
,
2308 *got_exact_match
= state
.got_exact_match
;
2310 ok
= smbd_marshall_dir_entry(ctx
,
2315 state
.check_mangled_names
,
2316 requires_resume_key
,
2329 TALLOC_FREE(smb_fname
);
2330 if (*out_of_space
) {
2331 dptr_SeekDir(dirptr
, prev_dirpos
);
2338 *_last_entry_off
= last_entry_off
;
2342 static bool get_lanman2_dir_entry(TALLOC_CTX
*ctx
,
2343 connection_struct
*conn
,
2344 struct dptr_struct
*dirptr
,
2346 const char *path_mask
,
2349 bool requires_resume_key
,
2355 int space_remaining
,
2357 bool *got_exact_match
,
2358 int *last_entry_off
,
2359 struct ea_list
*name_list
)
2362 const bool do_pad
= true;
2364 if (info_level
>= 1 && info_level
<= 3) {
2365 /* No alignment on earlier info levels. */
2369 return smbd_dirptr_lanman2_entry(ctx
, conn
, dirptr
, flags2
,
2370 path_mask
, dirtype
, info_level
,
2371 requires_resume_key
, dont_descend
, ask_sharemode
,
2373 ppdata
, base_data
, end_data
,
2375 out_of_space
, got_exact_match
,
2376 last_entry_off
, name_list
);
2379 /****************************************************************************
2380 Reply to a TRANS2_FINDFIRST.
2381 ****************************************************************************/
2383 static void call_trans2findfirst(connection_struct
*conn
,
2384 struct smb_request
*req
,
2385 char **pparams
, int total_params
,
2386 char **ppdata
, int total_data
,
2387 unsigned int max_data_bytes
)
2389 /* We must be careful here that we don't return more than the
2390 allowed number of data bytes. If this means returning fewer than
2391 maxentries then so be it. We assume that the redirector has
2392 enough room for the fixed number of parameter bytes it has
2394 struct smb_filename
*smb_dname
= NULL
;
2395 char *params
= *pparams
;
2396 char *pdata
= *ppdata
;
2400 uint16 findfirst_flags
;
2401 bool close_after_first
;
2403 bool requires_resume_key
;
2405 char *directory
= NULL
;
2408 int last_entry_off
=0;
2412 bool finished
= False
;
2413 bool dont_descend
= False
;
2414 bool out_of_space
= False
;
2415 int space_remaining
;
2416 bool mask_contains_wcard
= False
;
2417 struct ea_list
*ea_list
= NULL
;
2418 NTSTATUS ntstatus
= NT_STATUS_OK
;
2419 bool ask_sharemode
= lp_parm_bool(SNUM(conn
), "smbd", "search ask sharemode", true);
2420 TALLOC_CTX
*ctx
= talloc_tos();
2421 struct dptr_struct
*dirptr
= NULL
;
2422 struct smbd_server_connection
*sconn
= req
->sconn
;
2423 uint32_t ucf_flags
= (UCF_SAVE_LCOMP
| UCF_ALWAYS_ALLOW_WCARD_LCOMP
);
2424 bool backup_priv
= false;
2426 if (total_params
< 13) {
2427 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2431 dirtype
= SVAL(params
,0);
2432 maxentries
= SVAL(params
,2);
2433 findfirst_flags
= SVAL(params
,4);
2434 close_after_first
= (findfirst_flags
& FLAG_TRANS2_FIND_CLOSE
);
2435 close_if_end
= (findfirst_flags
& FLAG_TRANS2_FIND_CLOSE_IF_END
);
2436 requires_resume_key
= (findfirst_flags
& FLAG_TRANS2_FIND_REQUIRE_RESUME
);
2437 backup_priv
= ((findfirst_flags
& FLAG_TRANS2_FIND_BACKUP_INTENT
) &&
2438 security_token_has_privilege(get_current_nttok(conn
),
2441 info_level
= SVAL(params
,6);
2443 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2444 close_if_end = %d requires_resume_key = %d backup_priv = %d level = 0x%x, max_data_bytes = %d\n",
2445 (unsigned int)dirtype
, maxentries
, close_after_first
, close_if_end
, requires_resume_key
,
2447 info_level
, max_data_bytes
));
2450 /* W2K3 seems to treat zero as 1. */
2454 switch (info_level
) {
2455 case SMB_FIND_INFO_STANDARD
:
2456 case SMB_FIND_EA_SIZE
:
2457 case SMB_FIND_EA_LIST
:
2458 case SMB_FIND_FILE_DIRECTORY_INFO
:
2459 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
2460 case SMB_FIND_FILE_NAMES_INFO
:
2461 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
2462 case SMB_FIND_ID_FULL_DIRECTORY_INFO
:
2463 case SMB_FIND_ID_BOTH_DIRECTORY_INFO
:
2465 case SMB_FIND_FILE_UNIX
:
2466 case SMB_FIND_FILE_UNIX_INFO2
:
2467 /* Always use filesystem for UNIX mtime query. */
2468 ask_sharemode
= false;
2469 if (!lp_unix_extensions()) {
2470 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2473 ucf_flags
|= UCF_UNIX_NAME_LOOKUP
;
2476 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2480 srvstr_get_path_wcard(ctx
, params
, req
->flags2
, &directory
,
2481 params
+12, total_params
- 12,
2482 STR_TERMINATE
, &ntstatus
, &mask_contains_wcard
);
2483 if (!NT_STATUS_IS_OK(ntstatus
)) {
2484 reply_nterror(req
, ntstatus
);
2490 ntstatus
= filename_convert_with_privilege(ctx
,
2495 &mask_contains_wcard
,
2498 ntstatus
= filename_convert(ctx
, conn
,
2499 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
2502 &mask_contains_wcard
,
2506 if (!NT_STATUS_IS_OK(ntstatus
)) {
2507 if (NT_STATUS_EQUAL(ntstatus
,NT_STATUS_PATH_NOT_COVERED
)) {
2508 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
2509 ERRSRV
, ERRbadpath
);
2512 reply_nterror(req
, ntstatus
);
2516 mask
= smb_dname
->original_lcomp
;
2518 directory
= smb_dname
->base_name
;
2520 p
= strrchr_m(directory
,'/');
2522 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2523 if((directory
[0] == '.') && (directory
[1] == '\0')) {
2524 mask
= talloc_strdup(ctx
,"*");
2526 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2529 mask_contains_wcard
= True
;
2535 if (p
== NULL
|| p
== directory
) {
2536 /* Ensure we don't have a directory name of "". */
2537 directory
= talloc_strdup(talloc_tos(), ".");
2539 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2544 DEBUG(5,("dir=%s, mask = %s\n",directory
, mask
));
2546 if (info_level
== SMB_FIND_EA_LIST
) {
2549 if (total_data
< 4) {
2550 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2554 ea_size
= IVAL(pdata
,0);
2555 if (ea_size
!= total_data
) {
2556 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2557 total_data=%u (should be %u)\n", (unsigned int)total_data
, (unsigned int)IVAL(pdata
,0) ));
2558 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2562 if (!lp_ea_support(SNUM(conn
))) {
2563 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
2567 /* Pull out the list of names. */
2568 ea_list
= read_ea_name_list(ctx
, pdata
+ 4, ea_size
- 4);
2570 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2575 *ppdata
= (char *)SMB_REALLOC(
2576 *ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
2577 if(*ppdata
== NULL
) {
2578 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2582 data_end
= pdata
+ max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
- 1;
2584 /* Realloc the params space */
2585 *pparams
= (char *)SMB_REALLOC(*pparams
, 10);
2586 if (*pparams
== NULL
) {
2587 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2592 /* Save the wildcard match and attribs we are using on this directory -
2593 needed as lanman2 assumes these are being saved between calls */
2595 ntstatus
= dptr_create(conn
,
2603 mask_contains_wcard
,
2607 if (!NT_STATUS_IS_OK(ntstatus
)) {
2608 reply_nterror(req
, ntstatus
);
2613 /* Remember this in case we have
2614 to do a findnext. */
2615 dptr_set_priv(dirptr
);
2618 dptr_num
= dptr_dnum(dirptr
);
2619 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num
, mask
, dirtype
));
2621 /* Initialize per TRANS2_FIND_FIRST operation data */
2622 dptr_init_search_op(dirptr
);
2624 /* We don't need to check for VOL here as this is returned by
2625 a different TRANS2 call. */
2627 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2628 directory
,lp_dontdescend(ctx
, SNUM(conn
))));
2629 if (in_list(directory
,lp_dontdescend(ctx
, SNUM(conn
)),conn
->case_sensitive
))
2630 dont_descend
= True
;
2633 space_remaining
= max_data_bytes
;
2634 out_of_space
= False
;
2636 for (i
=0;(i
<maxentries
) && !finished
&& !out_of_space
;i
++) {
2637 bool got_exact_match
= False
;
2639 /* this is a heuristic to avoid seeking the dirptr except when
2640 absolutely necessary. It allows for a filename of about 40 chars */
2641 if (space_remaining
< DIRLEN_GUESS
&& numentries
> 0) {
2642 out_of_space
= True
;
2645 finished
= !get_lanman2_dir_entry(ctx
,
2649 mask
,dirtype
,info_level
,
2650 requires_resume_key
,dont_descend
,
2653 space_remaining
, &out_of_space
,
2655 &last_entry_off
, ea_list
);
2658 if (finished
&& out_of_space
)
2661 if (!finished
&& !out_of_space
)
2665 * As an optimisation if we know we aren't looking
2666 * for a wildcard name (ie. the name matches the wildcard exactly)
2667 * then we can finish on any (first) match.
2668 * This speeds up large directory searches. JRA.
2674 /* Ensure space_remaining never goes -ve. */
2675 if (PTR_DIFF(p
,pdata
) > max_data_bytes
) {
2676 space_remaining
= 0;
2677 out_of_space
= true;
2679 space_remaining
= max_data_bytes
- PTR_DIFF(p
,pdata
);
2683 /* Check if we can close the dirptr */
2684 if(close_after_first
|| (finished
&& close_if_end
)) {
2685 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num
));
2686 dptr_close(sconn
, &dptr_num
);
2690 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2691 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2692 * the protocol level is less than NT1. Tested with smbclient. JRA.
2693 * This should fix the OS/2 client bug #2335.
2696 if(numentries
== 0) {
2697 dptr_close(sconn
, &dptr_num
);
2698 if (get_Protocol() < PROTOCOL_NT1
) {
2699 reply_force_doserror(req
, ERRDOS
, ERRnofiles
);
2702 reply_botherror(req
, NT_STATUS_NO_SUCH_FILE
,
2703 ERRDOS
, ERRbadfile
);
2708 /* At this point pdata points to numentries directory entries. */
2710 /* Set up the return parameter block */
2711 SSVAL(params
,0,dptr_num
);
2712 SSVAL(params
,2,numentries
);
2713 SSVAL(params
,4,finished
);
2714 SSVAL(params
,6,0); /* Never an EA error */
2715 SSVAL(params
,8,last_entry_off
);
2717 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 10, pdata
, PTR_DIFF(p
,pdata
),
2720 if ((! *directory
) && dptr_path(sconn
, dptr_num
)) {
2721 directory
= talloc_strdup(talloc_tos(),dptr_path(sconn
, dptr_num
));
2723 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2727 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2728 smb_fn_name(req
->cmd
),
2729 mask
, directory
, dirtype
, numentries
) );
2732 * Force a name mangle here to ensure that the
2733 * mask as an 8.3 name is top of the mangled cache.
2734 * The reasons for this are subtle. Don't remove
2735 * this code unless you know what you are doing
2736 * (see PR#13758). JRA.
2739 if(!mangle_is_8_3_wildcards( mask
, False
, conn
->params
)) {
2740 char mangled_name
[13];
2741 name_to_8_3(mask
, mangled_name
, True
, conn
->params
);
2749 TALLOC_FREE(smb_dname
);
2753 /****************************************************************************
2754 Reply to a TRANS2_FINDNEXT.
2755 ****************************************************************************/
2757 static void call_trans2findnext(connection_struct
*conn
,
2758 struct smb_request
*req
,
2759 char **pparams
, int total_params
,
2760 char **ppdata
, int total_data
,
2761 unsigned int max_data_bytes
)
2763 /* We must be careful here that we don't return more than the
2764 allowed number of data bytes. If this means returning fewer than
2765 maxentries then so be it. We assume that the redirector has
2766 enough room for the fixed number of parameter bytes it has
2768 char *params
= *pparams
;
2769 char *pdata
= *ppdata
;
2775 uint16 findnext_flags
;
2776 bool close_after_request
;
2778 bool requires_resume_key
;
2780 bool mask_contains_wcard
= False
;
2781 char *resume_name
= NULL
;
2782 const char *mask
= NULL
;
2783 const char *directory
= NULL
;
2787 int i
, last_entry_off
=0;
2788 bool finished
= False
;
2789 bool dont_descend
= False
;
2790 bool out_of_space
= False
;
2791 int space_remaining
;
2792 struct ea_list
*ea_list
= NULL
;
2793 NTSTATUS ntstatus
= NT_STATUS_OK
;
2794 bool ask_sharemode
= lp_parm_bool(SNUM(conn
), "smbd", "search ask sharemode", true);
2795 TALLOC_CTX
*ctx
= talloc_tos();
2796 struct dptr_struct
*dirptr
;
2797 struct smbd_server_connection
*sconn
= req
->sconn
;
2798 bool backup_priv
= false;
2800 if (total_params
< 13) {
2801 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2805 dptr_num
= SVAL(params
,0);
2806 maxentries
= SVAL(params
,2);
2807 info_level
= SVAL(params
,4);
2808 resume_key
= IVAL(params
,6);
2809 findnext_flags
= SVAL(params
,10);
2810 close_after_request
= (findnext_flags
& FLAG_TRANS2_FIND_CLOSE
);
2811 close_if_end
= (findnext_flags
& FLAG_TRANS2_FIND_CLOSE_IF_END
);
2812 requires_resume_key
= (findnext_flags
& FLAG_TRANS2_FIND_REQUIRE_RESUME
);
2813 continue_bit
= (findnext_flags
& FLAG_TRANS2_FIND_CONTINUE
);
2815 if (!continue_bit
) {
2816 /* We only need resume_name if continue_bit is zero. */
2817 srvstr_get_path_wcard(ctx
, params
, req
->flags2
, &resume_name
,
2819 total_params
- 12, STR_TERMINATE
, &ntstatus
,
2820 &mask_contains_wcard
);
2821 if (!NT_STATUS_IS_OK(ntstatus
)) {
2822 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2823 complain (it thinks we're asking for the directory above the shared
2824 path or an invalid name). Catch this as the resume name is only compared, never used in
2825 a file access. JRA. */
2826 srvstr_pull_talloc(ctx
, params
, req
->flags2
,
2827 &resume_name
, params
+12,
2831 if (!resume_name
|| !(ISDOT(resume_name
) || ISDOTDOT(resume_name
))) {
2832 reply_nterror(req
, ntstatus
);
2838 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2839 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2840 resume_key = %d resume name = %s continue=%d level = %d\n",
2841 dptr_num
, max_data_bytes
, maxentries
, close_after_request
, close_if_end
,
2842 requires_resume_key
, resume_key
,
2843 resume_name
? resume_name
: "(NULL)", continue_bit
, info_level
));
2846 /* W2K3 seems to treat zero as 1. */
2850 switch (info_level
) {
2851 case SMB_FIND_INFO_STANDARD
:
2852 case SMB_FIND_EA_SIZE
:
2853 case SMB_FIND_EA_LIST
:
2854 case SMB_FIND_FILE_DIRECTORY_INFO
:
2855 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
2856 case SMB_FIND_FILE_NAMES_INFO
:
2857 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
2858 case SMB_FIND_ID_FULL_DIRECTORY_INFO
:
2859 case SMB_FIND_ID_BOTH_DIRECTORY_INFO
:
2861 case SMB_FIND_FILE_UNIX
:
2862 case SMB_FIND_FILE_UNIX_INFO2
:
2863 /* Always use filesystem for UNIX mtime query. */
2864 ask_sharemode
= false;
2865 if (!lp_unix_extensions()) {
2866 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2871 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2875 if (info_level
== SMB_FIND_EA_LIST
) {
2878 if (total_data
< 4) {
2879 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2883 ea_size
= IVAL(pdata
,0);
2884 if (ea_size
!= total_data
) {
2885 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2886 total_data=%u (should be %u)\n", (unsigned int)total_data
, (unsigned int)IVAL(pdata
,0) ));
2887 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2891 if (!lp_ea_support(SNUM(conn
))) {
2892 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
2896 /* Pull out the list of names. */
2897 ea_list
= read_ea_name_list(ctx
, pdata
+ 4, ea_size
- 4);
2899 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2904 *ppdata
= (char *)SMB_REALLOC(
2905 *ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
2906 if(*ppdata
== NULL
) {
2907 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2912 data_end
= pdata
+ max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
- 1;
2914 /* Realloc the params space */
2915 *pparams
= (char *)SMB_REALLOC(*pparams
, 6*SIZEOFWORD
);
2916 if(*pparams
== NULL
) {
2917 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2923 /* Check that the dptr is valid */
2924 if(!(dirptr
= dptr_fetch_lanman2(sconn
, dptr_num
))) {
2925 reply_nterror(req
, STATUS_NO_MORE_FILES
);
2929 directory
= dptr_path(sconn
, dptr_num
);
2931 /* Get the wildcard mask from the dptr */
2932 if((mask
= dptr_wcard(sconn
, dptr_num
))== NULL
) {
2933 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num
));
2934 reply_nterror(req
, STATUS_NO_MORE_FILES
);
2938 /* Get the attr mask from the dptr */
2939 dirtype
= dptr_attr(sconn
, dptr_num
);
2941 backup_priv
= dptr_get_priv(dirptr
);
2943 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld) "
2944 "backup_priv = %d\n",
2945 dptr_num
, mask
, dirtype
,
2947 dptr_TellDir(dirptr
),
2950 /* Initialize per TRANS2_FIND_NEXT operation data */
2951 dptr_init_search_op(dirptr
);
2953 /* We don't need to check for VOL here as this is returned by
2954 a different TRANS2 call. */
2956 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2957 directory
,lp_dontdescend(ctx
, SNUM(conn
))));
2958 if (in_list(directory
,lp_dontdescend(ctx
, SNUM(conn
)),conn
->case_sensitive
))
2959 dont_descend
= True
;
2962 space_remaining
= max_data_bytes
;
2963 out_of_space
= False
;
2970 * Seek to the correct position. We no longer use the resume key but
2971 * depend on the last file name instead.
2974 if(!continue_bit
&& resume_name
&& *resume_name
) {
2977 long current_pos
= 0;
2979 * Remember, name_to_8_3 is called by
2980 * get_lanman2_dir_entry(), so the resume name
2981 * could be mangled. Ensure we check the unmangled name.
2984 if (mangle_is_mangled(resume_name
, conn
->params
)) {
2985 char *new_resume_name
= NULL
;
2986 mangle_lookup_name_from_8_3(ctx
,
2990 if (new_resume_name
) {
2991 resume_name
= new_resume_name
;
2996 * Fix for NT redirector problem triggered by resume key indexes
2997 * changing between directory scans. We now return a resume key of 0
2998 * and instead look for the filename to continue from (also given
2999 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
3000 * findfirst/findnext (as is usual) then the directory pointer
3001 * should already be at the correct place.
3004 finished
= !dptr_SearchDir(dirptr
, resume_name
, ¤t_pos
, &st
);
3005 } /* end if resume_name && !continue_bit */
3007 for (i
=0;(i
<(int)maxentries
) && !finished
&& !out_of_space
;i
++) {
3008 bool got_exact_match
= False
;
3010 /* this is a heuristic to avoid seeking the dirptr except when
3011 absolutely necessary. It allows for a filename of about 40 chars */
3012 if (space_remaining
< DIRLEN_GUESS
&& numentries
> 0) {
3013 out_of_space
= True
;
3016 finished
= !get_lanman2_dir_entry(ctx
,
3020 mask
,dirtype
,info_level
,
3021 requires_resume_key
,dont_descend
,
3024 space_remaining
, &out_of_space
,
3026 &last_entry_off
, ea_list
);
3029 if (finished
&& out_of_space
)
3032 if (!finished
&& !out_of_space
)
3036 * As an optimisation if we know we aren't looking
3037 * for a wildcard name (ie. the name matches the wildcard exactly)
3038 * then we can finish on any (first) match.
3039 * This speeds up large directory searches. JRA.
3045 space_remaining
= max_data_bytes
- PTR_DIFF(p
,pdata
);
3048 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
3049 smb_fn_name(req
->cmd
),
3050 mask
, directory
, dirtype
, numentries
) );
3052 /* Check if we can close the dirptr */
3053 if(close_after_request
|| (finished
&& close_if_end
)) {
3054 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num
));
3055 dptr_close(sconn
, &dptr_num
); /* This frees up the saved mask */
3062 /* Set up the return parameter block */
3063 SSVAL(params
,0,numentries
);
3064 SSVAL(params
,2,finished
);
3065 SSVAL(params
,4,0); /* Never an EA error */
3066 SSVAL(params
,6,last_entry_off
);
3068 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 8, pdata
, PTR_DIFF(p
,pdata
),
3074 unsigned char *create_volume_objectid(connection_struct
*conn
, unsigned char objid
[16])
3076 E_md4hash(lp_servicename(talloc_tos(), SNUM(conn
)),objid
);
3080 static void samba_extended_info_version(struct smb_extended_info
*extended_info
)
3082 SMB_ASSERT(extended_info
!= NULL
);
3084 extended_info
->samba_magic
= SAMBA_EXTENDED_INFO_MAGIC
;
3085 extended_info
->samba_version
= ((SAMBA_VERSION_MAJOR
& 0xff) << 24)
3086 | ((SAMBA_VERSION_MINOR
& 0xff) << 16)
3087 | ((SAMBA_VERSION_RELEASE
& 0xff) << 8);
3088 #ifdef SAMBA_VERSION_REVISION
3089 extended_info
->samba_version
|= (tolower(*SAMBA_VERSION_REVISION
) - 'a' + 1) & 0xff;
3091 extended_info
->samba_subversion
= 0;
3092 #ifdef SAMBA_VERSION_RC_RELEASE
3093 extended_info
->samba_subversion
|= (SAMBA_VERSION_RC_RELEASE
& 0xff) << 24;
3095 #ifdef SAMBA_VERSION_PRE_RELEASE
3096 extended_info
->samba_subversion
|= (SAMBA_VERSION_PRE_RELEASE
& 0xff) << 16;
3099 #ifdef SAMBA_VERSION_VENDOR_PATCH
3100 extended_info
->samba_subversion
|= (SAMBA_VERSION_VENDOR_PATCH
& 0xffff);
3102 extended_info
->samba_gitcommitdate
= 0;
3103 #ifdef SAMBA_VERSION_COMMIT_TIME
3104 unix_to_nt_time(&extended_info
->samba_gitcommitdate
, SAMBA_VERSION_COMMIT_TIME
);
3107 memset(extended_info
->samba_version_string
, 0,
3108 sizeof(extended_info
->samba_version_string
));
3110 snprintf (extended_info
->samba_version_string
,
3111 sizeof(extended_info
->samba_version_string
),
3112 "%s", samba_version_string());
3115 NTSTATUS
smbd_do_qfsinfo(connection_struct
*conn
,
3116 TALLOC_CTX
*mem_ctx
,
3117 uint16_t info_level
,
3119 unsigned int max_data_bytes
,
3120 struct smb_filename
*fname
,
3124 char *pdata
, *end_data
;
3125 int data_len
= 0, len
;
3126 const char *vname
= volume_label(talloc_tos(), SNUM(conn
));
3127 int snum
= SNUM(conn
);
3128 char *fstype
= lp_fstype(talloc_tos(), SNUM(conn
));
3129 char *filename
= NULL
;
3130 uint32 additional_flags
= 0;
3131 struct smb_filename smb_fname
;
3133 NTSTATUS status
= NT_STATUS_OK
;
3135 if (fname
== NULL
|| fname
->base_name
== NULL
) {
3138 filename
= fname
->base_name
;
3142 if (info_level
!= SMB_QUERY_CIFS_UNIX_INFO
) {
3143 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
3144 "info level (0x%x) on IPC$.\n",
3145 (unsigned int)info_level
));
3146 return NT_STATUS_ACCESS_DENIED
;
3150 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level
));
3152 ZERO_STRUCT(smb_fname
);
3153 smb_fname
.base_name
= discard_const_p(char, filename
);
3155 if(SMB_VFS_STAT(conn
, &smb_fname
) != 0) {
3156 DEBUG(2,("stat of . failed (%s)\n", strerror(errno
)));
3157 return map_nt_error_from_unix(errno
);
3162 *ppdata
= (char *)SMB_REALLOC(
3163 *ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
3164 if (*ppdata
== NULL
) {
3165 return NT_STATUS_NO_MEMORY
;
3169 memset((char *)pdata
,'\0',max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
3170 end_data
= pdata
+ max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
- 1;
3172 switch (info_level
) {
3173 case SMB_INFO_ALLOCATION
:
3175 uint64_t dfree
,dsize
,bsize
,block_size
,sectors_per_unit
,bytes_per_sector
;
3177 if (get_dfree_info(conn
,filename
,False
,&bsize
,&dfree
,&dsize
) == (uint64_t)-1) {
3178 return map_nt_error_from_unix(errno
);
3181 block_size
= lp_block_size(snum
);
3182 if (bsize
< block_size
) {
3183 uint64_t factor
= block_size
/bsize
;
3188 if (bsize
> block_size
) {
3189 uint64_t factor
= bsize
/block_size
;
3194 bytes_per_sector
= 512;
3195 sectors_per_unit
= bsize
/bytes_per_sector
;
3197 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
3198 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st
.st_ex_dev
, (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
3199 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
3201 SIVAL(pdata
,l1_idFileSystem
,st
.st_ex_dev
);
3202 SIVAL(pdata
,l1_cSectorUnit
,sectors_per_unit
);
3203 SIVAL(pdata
,l1_cUnit
,dsize
);
3204 SIVAL(pdata
,l1_cUnitAvail
,dfree
);
3205 SSVAL(pdata
,l1_cbSector
,bytes_per_sector
);
3209 case SMB_INFO_VOLUME
:
3210 /* Return volume name */
3212 * Add volume serial number - hash of a combination of
3213 * the called hostname and the service name.
3215 SIVAL(pdata
,0,str_checksum(lp_servicename(talloc_tos(), snum
)) ^ (str_checksum(get_local_machine_name())<<16) );
3217 * Win2k3 and previous mess this up by sending a name length
3218 * one byte short. I believe only older clients (OS/2 Win9x) use
3219 * this call so try fixing this by adding a terminating null to
3220 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
3224 pdata
+l2_vol_szVolLabel
, vname
,
3225 PTR_DIFF(end_data
, pdata
+l2_vol_szVolLabel
),
3226 STR_NOALIGN
|STR_TERMINATE
);
3227 SCVAL(pdata
,l2_vol_cch
,len
);
3228 data_len
= l2_vol_szVolLabel
+ len
;
3229 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %d, name = %s\n",
3230 (unsigned)convert_timespec_to_time_t(st
.st_ex_ctime
),
3234 case SMB_QUERY_FS_ATTRIBUTE_INFO
:
3235 case SMB_FS_ATTRIBUTE_INFORMATION
:
3237 additional_flags
= 0;
3238 #if defined(HAVE_SYS_QUOTAS)
3239 additional_flags
|= FILE_VOLUME_QUOTAS
;
3242 if(lp_nt_acl_support(SNUM(conn
))) {
3243 additional_flags
|= FILE_PERSISTENT_ACLS
;
3246 /* Capabilities are filled in at connection time through STATVFS call */
3247 additional_flags
|= conn
->fs_capabilities
;
3248 additional_flags
|= lp_parm_int(conn
->params
->service
,
3249 "share", "fake_fscaps",
3252 SIVAL(pdata
,0,FILE_CASE_PRESERVED_NAMES
|FILE_CASE_SENSITIVE_SEARCH
|
3253 FILE_SUPPORTS_OBJECT_IDS
|FILE_UNICODE_ON_DISK
|
3254 additional_flags
); /* FS ATTRIBUTES */
3256 SIVAL(pdata
,4,255); /* Max filename component length */
3257 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
3258 and will think we can't do long filenames */
3259 len
= srvstr_push(pdata
, flags2
, pdata
+12, fstype
,
3260 PTR_DIFF(end_data
, pdata
+12),
3263 data_len
= 12 + len
;
3266 case SMB_QUERY_FS_LABEL_INFO
:
3267 case SMB_FS_LABEL_INFORMATION
:
3268 len
= srvstr_push(pdata
, flags2
, pdata
+4, vname
,
3269 PTR_DIFF(end_data
, pdata
+4), 0);
3274 case SMB_QUERY_FS_VOLUME_INFO
:
3275 case SMB_FS_VOLUME_INFORMATION
:
3278 * Add volume serial number - hash of a combination of
3279 * the called hostname and the service name.
3281 SIVAL(pdata
,8,str_checksum(lp_servicename(talloc_tos(), snum
)) ^
3282 (str_checksum(get_local_machine_name())<<16));
3284 /* Max label len is 32 characters. */
3285 len
= srvstr_push(pdata
, flags2
, pdata
+18, vname
,
3286 PTR_DIFF(end_data
, pdata
+18),
3288 SIVAL(pdata
,12,len
);
3291 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3292 (int)strlen(vname
),vname
,
3293 lp_servicename(talloc_tos(), snum
)));
3296 case SMB_QUERY_FS_SIZE_INFO
:
3297 case SMB_FS_SIZE_INFORMATION
:
3299 uint64_t dfree
,dsize
,bsize
,block_size
,sectors_per_unit
,bytes_per_sector
;
3301 if (get_dfree_info(conn
,filename
,False
,&bsize
,&dfree
,&dsize
) == (uint64_t)-1) {
3302 return map_nt_error_from_unix(errno
);
3304 block_size
= lp_block_size(snum
);
3305 if (bsize
< block_size
) {
3306 uint64_t factor
= block_size
/bsize
;
3311 if (bsize
> block_size
) {
3312 uint64_t factor
= bsize
/block_size
;
3317 bytes_per_sector
= 512;
3318 sectors_per_unit
= bsize
/bytes_per_sector
;
3319 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3320 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
3321 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
3322 SBIG_UINT(pdata
,0,dsize
);
3323 SBIG_UINT(pdata
,8,dfree
);
3324 SIVAL(pdata
,16,sectors_per_unit
);
3325 SIVAL(pdata
,20,bytes_per_sector
);
3329 case SMB_FS_FULL_SIZE_INFORMATION
:
3331 uint64_t dfree
,dsize
,bsize
,block_size
,sectors_per_unit
,bytes_per_sector
;
3333 if (get_dfree_info(conn
,filename
,False
,&bsize
,&dfree
,&dsize
) == (uint64_t)-1) {
3334 return map_nt_error_from_unix(errno
);
3336 block_size
= lp_block_size(snum
);
3337 if (bsize
< block_size
) {
3338 uint64_t factor
= block_size
/bsize
;
3343 if (bsize
> block_size
) {
3344 uint64_t factor
= bsize
/block_size
;
3349 bytes_per_sector
= 512;
3350 sectors_per_unit
= bsize
/bytes_per_sector
;
3351 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3352 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
3353 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
3354 SBIG_UINT(pdata
,0,dsize
); /* Total Allocation units. */
3355 SBIG_UINT(pdata
,8,dfree
); /* Caller available allocation units. */
3356 SBIG_UINT(pdata
,16,dfree
); /* Actual available allocation units. */
3357 SIVAL(pdata
,24,sectors_per_unit
); /* Sectors per allocation unit. */
3358 SIVAL(pdata
,28,bytes_per_sector
); /* Bytes per sector. */
3362 case SMB_QUERY_FS_DEVICE_INFO
:
3363 case SMB_FS_DEVICE_INFORMATION
:
3365 uint32_t characteristics
= FILE_DEVICE_IS_MOUNTED
;
3367 if (!CAN_WRITE(conn
)) {
3368 characteristics
|= FILE_READ_ONLY_DEVICE
;
3371 SIVAL(pdata
,0,FILE_DEVICE_DISK
); /* dev type */
3372 SIVAL(pdata
,4,characteristics
);
3376 #ifdef HAVE_SYS_QUOTAS
3377 case SMB_FS_QUOTA_INFORMATION
:
3379 * what we have to send --metze:
3381 * Unknown1: 24 NULL bytes
3382 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3383 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3384 * Quota Flags: 2 byte :
3385 * Unknown3: 6 NULL bytes
3389 * details for Quota Flags:
3391 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3392 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3393 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3394 * 0x0001 Enable Quotas: enable quota for this fs
3398 /* we need to fake up a fsp here,
3399 * because its not send in this call
3402 SMB_NTQUOTA_STRUCT quotas
;
3405 ZERO_STRUCT(quotas
);
3408 fsp
.fnum
= FNUM_FIELD_INVALID
;
3411 if (get_current_uid(conn
) != 0) {
3412 DEBUG(0,("set_user_quota: access_denied "
3413 "service [%s] user [%s]\n",
3414 lp_servicename(talloc_tos(), SNUM(conn
)),
3415 conn
->session_info
->unix_info
->unix_name
));
3416 return NT_STATUS_ACCESS_DENIED
;
3419 if (vfs_get_ntquota(&fsp
, SMB_USER_FS_QUOTA_TYPE
, NULL
, "as
)!=0) {
3420 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn
))));
3421 return map_nt_error_from_unix(errno
);
3426 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3427 lp_servicename(talloc_tos(), SNUM(conn
))));
3429 /* Unknown1 24 NULL bytes*/
3430 SBIG_UINT(pdata
,0,(uint64_t)0);
3431 SBIG_UINT(pdata
,8,(uint64_t)0);
3432 SBIG_UINT(pdata
,16,(uint64_t)0);
3434 /* Default Soft Quota 8 bytes */
3435 SBIG_UINT(pdata
,24,quotas
.softlim
);
3437 /* Default Hard Quota 8 bytes */
3438 SBIG_UINT(pdata
,32,quotas
.hardlim
);
3440 /* Quota flag 2 bytes */
3441 SSVAL(pdata
,40,quotas
.qflags
);
3443 /* Unknown3 6 NULL bytes */
3449 #endif /* HAVE_SYS_QUOTAS */
3450 case SMB_FS_OBJECTID_INFORMATION
:
3452 unsigned char objid
[16];
3453 struct smb_extended_info extended_info
;
3454 memcpy(pdata
,create_volume_objectid(conn
, objid
),16);
3455 samba_extended_info_version (&extended_info
);
3456 SIVAL(pdata
,16,extended_info
.samba_magic
);
3457 SIVAL(pdata
,20,extended_info
.samba_version
);
3458 SIVAL(pdata
,24,extended_info
.samba_subversion
);
3459 SBIG_UINT(pdata
,28,extended_info
.samba_gitcommitdate
);
3460 memcpy(pdata
+36,extended_info
.samba_version_string
,28);
3466 * Query the version and capabilities of the CIFS UNIX extensions
3470 case SMB_QUERY_CIFS_UNIX_INFO
:
3472 bool large_write
= lp_min_receive_file_size() &&
3473 !srv_is_signing_active(conn
->sconn
);
3474 bool large_read
= !srv_is_signing_active(conn
->sconn
);
3475 int encrypt_caps
= 0;
3477 if (!lp_unix_extensions()) {
3478 return NT_STATUS_INVALID_LEVEL
;
3481 switch (conn
->encrypt_level
) {
3482 case SMB_SIGNING_OFF
:
3485 case SMB_SIGNING_IF_REQUIRED
:
3486 case SMB_SIGNING_DEFAULT
:
3487 encrypt_caps
= CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP
;
3489 case SMB_SIGNING_REQUIRED
:
3490 encrypt_caps
= CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP
|
3491 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP
;
3492 large_write
= false;
3498 SSVAL(pdata
,0,CIFS_UNIX_MAJOR_VERSION
);
3499 SSVAL(pdata
,2,CIFS_UNIX_MINOR_VERSION
);
3501 /* We have POSIX ACLs, pathname, encryption,
3502 * large read/write, and locking capability. */
3504 SBIG_UINT(pdata
,4,((uint64_t)(
3505 CIFS_UNIX_POSIX_ACLS_CAP
|
3506 CIFS_UNIX_POSIX_PATHNAMES_CAP
|
3507 CIFS_UNIX_FCNTL_LOCKS_CAP
|
3508 CIFS_UNIX_EXTATTR_CAP
|
3509 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP
|
3511 (large_read
? CIFS_UNIX_LARGE_READ_CAP
: 0) |
3513 CIFS_UNIX_LARGE_WRITE_CAP
: 0))));
3517 case SMB_QUERY_POSIX_FS_INFO
:
3520 vfs_statvfs_struct svfs
;
3522 if (!lp_unix_extensions()) {
3523 return NT_STATUS_INVALID_LEVEL
;
3526 rc
= SMB_VFS_STATVFS(conn
, filename
, &svfs
);
3530 SIVAL(pdata
,0,svfs
.OptimalTransferSize
);
3531 SIVAL(pdata
,4,svfs
.BlockSize
);
3532 SBIG_UINT(pdata
,8,svfs
.TotalBlocks
);
3533 SBIG_UINT(pdata
,16,svfs
.BlocksAvail
);
3534 SBIG_UINT(pdata
,24,svfs
.UserBlocksAvail
);
3535 SBIG_UINT(pdata
,32,svfs
.TotalFileNodes
);
3536 SBIG_UINT(pdata
,40,svfs
.FreeFileNodes
);
3537 SBIG_UINT(pdata
,48,svfs
.FsIdentifier
);
3538 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3540 } else if (rc
== EOPNOTSUPP
) {
3541 return NT_STATUS_INVALID_LEVEL
;
3542 #endif /* EOPNOTSUPP */
3544 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn
))));
3545 return NT_STATUS_DOS(ERRSRV
, ERRerror
);
3550 case SMB_QUERY_POSIX_WHOAMI
:
3556 if (!lp_unix_extensions()) {
3557 return NT_STATUS_INVALID_LEVEL
;
3560 if (max_data_bytes
< 40) {
3561 return NT_STATUS_BUFFER_TOO_SMALL
;
3564 if (security_session_user_level(conn
->session_info
, NULL
) < SECURITY_USER
) {
3565 flags
|= SMB_WHOAMI_GUEST
;
3568 /* NOTE: 8 bytes for UID/GID, irrespective of native
3569 * platform size. This matches
3570 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3572 data_len
= 4 /* flags */
3579 + 4 /* pad/reserved */
3580 + (conn
->session_info
->unix_token
->ngroups
* 8)
3582 + (conn
->session_info
->security_token
->num_sids
*
3586 SIVAL(pdata
, 0, flags
);
3587 SIVAL(pdata
, 4, SMB_WHOAMI_MASK
);
3589 (uint64_t)conn
->session_info
->unix_token
->uid
);
3590 SBIG_UINT(pdata
, 16,
3591 (uint64_t)conn
->session_info
->unix_token
->gid
);
3594 if (data_len
>= max_data_bytes
) {
3595 /* Potential overflow, skip the GIDs and SIDs. */
3597 SIVAL(pdata
, 24, 0); /* num_groups */
3598 SIVAL(pdata
, 28, 0); /* num_sids */
3599 SIVAL(pdata
, 32, 0); /* num_sid_bytes */
3600 SIVAL(pdata
, 36, 0); /* reserved */
3606 SIVAL(pdata
, 24, conn
->session_info
->unix_token
->ngroups
);
3607 SIVAL(pdata
, 28, conn
->session_info
->security_token
->num_sids
);
3609 /* We walk the SID list twice, but this call is fairly
3610 * infrequent, and I don't expect that it's performance
3611 * sensitive -- jpeach
3613 for (i
= 0, sid_bytes
= 0;
3614 i
< conn
->session_info
->security_token
->num_sids
; ++i
) {
3615 sid_bytes
+= ndr_size_dom_sid(
3616 &conn
->session_info
->security_token
->sids
[i
],
3620 /* SID list byte count */
3621 SIVAL(pdata
, 32, sid_bytes
);
3623 /* 4 bytes pad/reserved - must be zero */
3624 SIVAL(pdata
, 36, 0);
3628 for (i
= 0; i
< conn
->session_info
->unix_token
->ngroups
; ++i
) {
3629 SBIG_UINT(pdata
, data_len
,
3630 (uint64_t)conn
->session_info
->unix_token
->groups
[i
]);
3636 i
< conn
->session_info
->security_token
->num_sids
; ++i
) {
3637 int sid_len
= ndr_size_dom_sid(
3638 &conn
->session_info
->security_token
->sids
[i
],
3641 sid_linearize(pdata
+ data_len
, sid_len
,
3642 &conn
->session_info
->security_token
->sids
[i
]);
3643 data_len
+= sid_len
;
3649 case SMB_MAC_QUERY_FS_INFO
:
3651 * Thursby MAC extension... ONLY on NTFS filesystems
3652 * once we do streams then we don't need this
3654 if (strequal(lp_fstype(talloc_tos(), SNUM(conn
)),"NTFS")) {
3656 SIVAL(pdata
,84,0x100); /* Don't support mac... */
3661 return NT_STATUS_INVALID_LEVEL
;
3664 *ret_data_len
= data_len
;
3668 /****************************************************************************
3669 Reply to a TRANS2_QFSINFO (query filesystem info).
3670 ****************************************************************************/
3672 static void call_trans2qfsinfo(connection_struct
*conn
,
3673 struct smb_request
*req
,
3674 char **pparams
, int total_params
,
3675 char **ppdata
, int total_data
,
3676 unsigned int max_data_bytes
)
3678 char *params
= *pparams
;
3679 uint16_t info_level
;
3683 if (total_params
< 2) {
3684 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3688 info_level
= SVAL(params
,0);
3690 if (ENCRYPTION_REQUIRED(conn
) && !req
->encrypted
) {
3691 if (info_level
!= SMB_QUERY_CIFS_UNIX_INFO
) {
3692 DEBUG(0,("call_trans2qfsinfo: encryption required "
3693 "and info level 0x%x sent.\n",
3694 (unsigned int)info_level
));
3695 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3700 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level
));
3702 status
= smbd_do_qfsinfo(conn
, req
,
3708 if (!NT_STATUS_IS_OK(status
)) {
3709 reply_nterror(req
, status
);
3713 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 0, *ppdata
, data_len
,
3716 DEBUG( 4, ( "%s info_level = %d\n",
3717 smb_fn_name(req
->cmd
), info_level
) );
3722 /****************************************************************************
3723 Reply to a TRANS2_SETFSINFO (set filesystem info).
3724 ****************************************************************************/
3726 static void call_trans2setfsinfo(connection_struct
*conn
,
3727 struct smb_request
*req
,
3728 char **pparams
, int total_params
,
3729 char **ppdata
, int total_data
,
3730 unsigned int max_data_bytes
)
3732 struct smbd_server_connection
*sconn
= req
->sconn
;
3733 char *pdata
= *ppdata
;
3734 char *params
= *pparams
;
3737 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",
3738 lp_servicename(talloc_tos(), SNUM(conn
))));
3741 if (total_params
< 4) {
3742 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3744 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3748 info_level
= SVAL(params
,2);
3751 if (info_level
!= SMB_REQUEST_TRANSPORT_ENCRYPTION
&&
3752 info_level
!= SMB_SET_CIFS_UNIX_INFO
) {
3753 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3754 "info level (0x%x) on IPC$.\n",
3755 (unsigned int)info_level
));
3756 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3761 if (ENCRYPTION_REQUIRED(conn
) && !req
->encrypted
) {
3762 if (info_level
!= SMB_REQUEST_TRANSPORT_ENCRYPTION
) {
3763 DEBUG(0,("call_trans2setfsinfo: encryption required "
3764 "and info level 0x%x sent.\n",
3765 (unsigned int)info_level
));
3766 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3771 switch(info_level
) {
3772 case SMB_SET_CIFS_UNIX_INFO
:
3773 if (!lp_unix_extensions()) {
3774 DEBUG(2,("call_trans2setfsinfo: "
3775 "SMB_SET_CIFS_UNIX_INFO is invalid with "
3776 "unix extensions off\n"));
3778 NT_STATUS_INVALID_LEVEL
);
3782 /* There should be 12 bytes of capabilities set. */
3783 if (total_data
< 12) {
3786 NT_STATUS_INVALID_PARAMETER
);
3789 sconn
->smb1
.unix_info
.client_major
= SVAL(pdata
,0);
3790 sconn
->smb1
.unix_info
.client_minor
= SVAL(pdata
,2);
3791 sconn
->smb1
.unix_info
.client_cap_low
= IVAL(pdata
,4);
3792 sconn
->smb1
.unix_info
.client_cap_high
= IVAL(pdata
,8);
3793 /* Just print these values for now. */
3794 DEBUG(10, ("call_trans2setfsinfo: set unix_info info. "
3795 "major = %u, minor = %u cap_low = 0x%x, "
3797 (unsigned int)sconn
->
3798 smb1
.unix_info
.client_major
,
3799 (unsigned int)sconn
->
3800 smb1
.unix_info
.client_minor
,
3801 (unsigned int)sconn
->
3802 smb1
.unix_info
.client_cap_low
,
3803 (unsigned int)sconn
->
3804 smb1
.unix_info
.client_cap_high
));
3806 /* Here is where we must switch to posix pathname processing... */
3807 if (sconn
->smb1
.unix_info
.client_cap_low
& CIFS_UNIX_POSIX_PATHNAMES_CAP
) {
3808 lp_set_posix_pathnames();
3809 mangle_change_to_posix();
3812 if ((sconn
->smb1
.unix_info
.client_cap_low
& CIFS_UNIX_FCNTL_LOCKS_CAP
) &&
3813 !(sconn
->smb1
.unix_info
.client_cap_low
& CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP
)) {
3814 /* Client that knows how to do posix locks,
3815 * but not posix open/mkdir operations. Set a
3816 * default type for read/write checks. */
3818 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK
);
3823 case SMB_REQUEST_TRANSPORT_ENCRYPTION
:
3826 size_t param_len
= 0;
3827 size_t data_len
= total_data
;
3829 if (!lp_unix_extensions()) {
3832 NT_STATUS_INVALID_LEVEL
);
3836 if (lp_smb_encrypt(SNUM(conn
)) == SMB_SIGNING_OFF
) {
3839 NT_STATUS_NOT_SUPPORTED
);
3843 if (req
->sconn
->smb1
.echo_handler
.trusted_fde
) {
3844 DEBUG( 2,("call_trans2setfsinfo: "
3845 "request transport encryption disabled"
3846 "with 'fork echo handler = yes'\n"));
3849 NT_STATUS_NOT_SUPPORTED
);
3853 DEBUG( 4,("call_trans2setfsinfo: "
3854 "request transport encryption.\n"));
3856 status
= srv_request_encryption_setup(conn
,
3857 (unsigned char **)ppdata
,
3859 (unsigned char **)pparams
,
3862 if (!NT_STATUS_EQUAL(status
, NT_STATUS_MORE_PROCESSING_REQUIRED
) &&
3863 !NT_STATUS_IS_OK(status
)) {
3864 reply_nterror(req
, status
);
3868 send_trans2_replies(conn
, req
,
3876 if (NT_STATUS_IS_OK(status
)) {
3877 /* Server-side transport
3878 * encryption is now *on*. */
3879 status
= srv_encryption_start(conn
);
3880 if (!NT_STATUS_IS_OK(status
)) {
3881 char *reason
= talloc_asprintf(talloc_tos(),
3882 "Failure in setting "
3883 "up encrypted transport: %s",
3885 exit_server_cleanly(reason
);
3891 case SMB_FS_QUOTA_INFORMATION
:
3893 files_struct
*fsp
= NULL
;
3894 SMB_NTQUOTA_STRUCT quotas
;
3896 ZERO_STRUCT(quotas
);
3899 if ((get_current_uid(conn
) != 0) || !CAN_WRITE(conn
)) {
3900 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3901 lp_servicename(talloc_tos(), SNUM(conn
)),
3902 conn
->session_info
->unix_info
->unix_name
));
3903 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3907 /* note: normaly there're 48 bytes,
3908 * but we didn't use the last 6 bytes for now
3911 fsp
= file_fsp(req
, SVAL(params
,0));
3913 if (!check_fsp_ntquota_handle(conn
, req
,
3915 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3917 req
, NT_STATUS_INVALID_HANDLE
);
3921 if (total_data
< 42) {
3922 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3926 NT_STATUS_INVALID_PARAMETER
);
3930 /* unknown_1 24 NULL bytes in pdata*/
3932 /* the soft quotas 8 bytes (uint64_t)*/
3933 quotas
.softlim
= BVAL(pdata
,24);
3935 /* the hard quotas 8 bytes (uint64_t)*/
3936 quotas
.hardlim
= BVAL(pdata
,32);
3938 /* quota_flags 2 bytes **/
3939 quotas
.qflags
= SVAL(pdata
,40);
3941 /* unknown_2 6 NULL bytes follow*/
3943 /* now set the quotas */
3944 if (vfs_set_ntquota(fsp
, SMB_USER_FS_QUOTA_TYPE
, NULL
, "as
)!=0) {
3945 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn
))));
3946 reply_nterror(req
, map_nt_error_from_unix(errno
));
3953 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3955 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
3961 * sending this reply works fine,
3962 * but I'm not sure it's the same
3963 * like windows do...
3966 reply_outbuf(req
, 10, 0);
3969 #if defined(HAVE_POSIX_ACLS)
3970 /****************************************************************************
3971 Utility function to count the number of entries in a POSIX acl.
3972 ****************************************************************************/
3974 static unsigned int count_acl_entries(connection_struct
*conn
, SMB_ACL_T posix_acl
)
3976 unsigned int ace_count
= 0;
3977 int entry_id
= SMB_ACL_FIRST_ENTRY
;
3978 SMB_ACL_ENTRY_T entry
;
3980 while ( posix_acl
&& (sys_acl_get_entry(posix_acl
, entry_id
, &entry
) == 1)) {
3982 if (entry_id
== SMB_ACL_FIRST_ENTRY
) {
3983 entry_id
= SMB_ACL_NEXT_ENTRY
;
3990 /****************************************************************************
3991 Utility function to marshall a POSIX acl into wire format.
3992 ****************************************************************************/
3994 static bool marshall_posix_acl(connection_struct
*conn
, char *pdata
, SMB_STRUCT_STAT
*pst
, SMB_ACL_T posix_acl
)
3996 int entry_id
= SMB_ACL_FIRST_ENTRY
;
3997 SMB_ACL_ENTRY_T entry
;
3999 while ( posix_acl
&& (sys_acl_get_entry(posix_acl
, entry_id
, &entry
) == 1)) {
4000 SMB_ACL_TAG_T tagtype
;
4001 SMB_ACL_PERMSET_T permset
;
4002 unsigned char perms
= 0;
4003 unsigned int own_grp
;
4006 if (entry_id
== SMB_ACL_FIRST_ENTRY
) {
4007 entry_id
= SMB_ACL_NEXT_ENTRY
;
4010 if (sys_acl_get_tag_type(entry
, &tagtype
) == -1) {
4011 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
4015 if (sys_acl_get_permset(entry
, &permset
) == -1) {
4016 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
4020 perms
|= (sys_acl_get_perm(permset
, SMB_ACL_READ
) ? SMB_POSIX_ACL_READ
: 0);
4021 perms
|= (sys_acl_get_perm(permset
, SMB_ACL_WRITE
) ? SMB_POSIX_ACL_WRITE
: 0);
4022 perms
|= (sys_acl_get_perm(permset
, SMB_ACL_EXECUTE
) ? SMB_POSIX_ACL_EXECUTE
: 0);
4024 SCVAL(pdata
,1,perms
);
4027 case SMB_ACL_USER_OBJ
:
4028 SCVAL(pdata
,0,SMB_POSIX_ACL_USER_OBJ
);
4029 own_grp
= (unsigned int)pst
->st_ex_uid
;
4030 SIVAL(pdata
,2,own_grp
);
4035 uid_t
*puid
= (uid_t
*)sys_acl_get_qualifier(entry
);
4037 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
4040 own_grp
= (unsigned int)*puid
;
4041 SCVAL(pdata
,0,SMB_POSIX_ACL_USER
);
4042 SIVAL(pdata
,2,own_grp
);
4046 case SMB_ACL_GROUP_OBJ
:
4047 SCVAL(pdata
,0,SMB_POSIX_ACL_GROUP_OBJ
);
4048 own_grp
= (unsigned int)pst
->st_ex_gid
;
4049 SIVAL(pdata
,2,own_grp
);
4054 gid_t
*pgid
= (gid_t
*)sys_acl_get_qualifier(entry
);
4056 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
4059 own_grp
= (unsigned int)*pgid
;
4060 SCVAL(pdata
,0,SMB_POSIX_ACL_GROUP
);
4061 SIVAL(pdata
,2,own_grp
);
4066 SCVAL(pdata
,0,SMB_POSIX_ACL_MASK
);
4067 SIVAL(pdata
,2,0xFFFFFFFF);
4068 SIVAL(pdata
,6,0xFFFFFFFF);
4071 SCVAL(pdata
,0,SMB_POSIX_ACL_OTHER
);
4072 SIVAL(pdata
,2,0xFFFFFFFF);
4073 SIVAL(pdata
,6,0xFFFFFFFF);
4076 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
4079 pdata
+= SMB_POSIX_ACL_ENTRY_SIZE
;
4086 /****************************************************************************
4087 Store the FILE_UNIX_BASIC info.
4088 ****************************************************************************/
4090 static char *store_file_unix_basic(connection_struct
*conn
,
4093 const SMB_STRUCT_STAT
*psbuf
)
4095 uint64_t file_index
= get_FileIndex(conn
, psbuf
);
4098 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
4099 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf
->st_ex_mode
));
4101 SOFF_T(pdata
,0,get_file_size_stat(psbuf
)); /* File size 64 Bit */
4104 SOFF_T(pdata
,0,SMB_VFS_GET_ALLOC_SIZE(conn
,fsp
,psbuf
)); /* Number of bytes used on disk - 64 Bit */
4107 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER
, pdata
, psbuf
->st_ex_ctime
); /* Change Time 64 Bit */
4108 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER
,pdata
+8, psbuf
->st_ex_atime
); /* Last access time 64 Bit */
4109 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER
, pdata
+16, psbuf
->st_ex_mtime
); /* Last modification time 64 Bit */
4112 SIVAL(pdata
,0,psbuf
->st_ex_uid
); /* user id for the owner */
4116 SIVAL(pdata
,0,psbuf
->st_ex_gid
); /* group id of owner */
4120 SIVAL(pdata
,0,unix_filetype(psbuf
->st_ex_mode
));
4123 if (S_ISBLK(psbuf
->st_ex_mode
) || S_ISCHR(psbuf
->st_ex_mode
)) {
4124 devno
= psbuf
->st_ex_rdev
;
4126 devno
= psbuf
->st_ex_dev
;
4129 SIVAL(pdata
,0,unix_dev_major(devno
)); /* Major device number if type is device */
4133 SIVAL(pdata
,0,unix_dev_minor(devno
)); /* Minor device number if type is device */
4137 SINO_T_VAL(pdata
,0,(SMB_INO_T
)file_index
); /* inode number */
4140 SIVAL(pdata
,0, unix_perms_to_wire(psbuf
->st_ex_mode
)); /* Standard UNIX file permissions */
4144 SIVAL(pdata
,0,psbuf
->st_ex_nlink
); /* number of hard links */
4151 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
4152 * the chflags(2) (or equivalent) flags.
4154 * XXX: this really should be behind the VFS interface. To do this, we would
4155 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
4156 * Each VFS module could then implement its own mapping as appropriate for the
4157 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
4159 static const struct {unsigned stat_fflag
; unsigned smb_fflag
;}
4163 { UF_NODUMP
, EXT_DO_NOT_BACKUP
},
4167 { UF_IMMUTABLE
, EXT_IMMUTABLE
},
4171 { UF_APPEND
, EXT_OPEN_APPEND_ONLY
},
4175 { UF_HIDDEN
, EXT_HIDDEN
},
4178 /* Do not remove. We need to guarantee that this array has at least one
4179 * entry to build on HP-UX.
4185 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT
*psbuf
,
4186 uint32
*smb_fflags
, uint32
*smb_fmask
)
4190 for (i
= 0; i
< ARRAY_SIZE(info2_flags_map
); ++i
) {
4191 *smb_fmask
|= info2_flags_map
[i
].smb_fflag
;
4192 if (psbuf
->st_ex_flags
& info2_flags_map
[i
].stat_fflag
) {
4193 *smb_fflags
|= info2_flags_map
[i
].smb_fflag
;
4198 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT
*psbuf
,
4199 const uint32 smb_fflags
,
4200 const uint32 smb_fmask
,
4203 uint32 max_fmask
= 0;
4206 *stat_fflags
= psbuf
->st_ex_flags
;
4208 /* For each flags requested in smb_fmask, check the state of the
4209 * corresponding flag in smb_fflags and set or clear the matching
4213 for (i
= 0; i
< ARRAY_SIZE(info2_flags_map
); ++i
) {
4214 max_fmask
|= info2_flags_map
[i
].smb_fflag
;
4215 if (smb_fmask
& info2_flags_map
[i
].smb_fflag
) {
4216 if (smb_fflags
& info2_flags_map
[i
].smb_fflag
) {
4217 *stat_fflags
|= info2_flags_map
[i
].stat_fflag
;
4219 *stat_fflags
&= ~info2_flags_map
[i
].stat_fflag
;
4224 /* If smb_fmask is asking to set any bits that are not supported by
4225 * our flag mappings, we should fail.
4227 if ((smb_fmask
& max_fmask
) != smb_fmask
) {
4235 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
4236 * of file flags and birth (create) time.
4238 static char *store_file_unix_basic_info2(connection_struct
*conn
,
4241 const SMB_STRUCT_STAT
*psbuf
)
4243 uint32 file_flags
= 0;
4244 uint32 flags_mask
= 0;
4246 pdata
= store_file_unix_basic(conn
, pdata
, fsp
, psbuf
);
4248 /* Create (birth) time 64 bit */
4249 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER
,pdata
, psbuf
->st_ex_btime
);
4252 map_info2_flags_from_sbuf(psbuf
, &file_flags
, &flags_mask
);
4253 SIVAL(pdata
, 0, file_flags
); /* flags */
4254 SIVAL(pdata
, 4, flags_mask
); /* mask */
4260 static NTSTATUS
marshall_stream_info(unsigned int num_streams
,
4261 const struct stream_struct
*streams
,
4263 unsigned int max_data_bytes
,
4264 unsigned int *data_size
)
4267 unsigned int ofs
= 0;
4269 for (i
= 0; i
< num_streams
; i
++) {
4270 unsigned int next_offset
;
4272 smb_ucs2_t
*namebuf
;
4274 if (!push_ucs2_talloc(talloc_tos(), &namebuf
,
4275 streams
[i
].name
, &namelen
) ||
4278 return NT_STATUS_INVALID_PARAMETER
;
4282 * name_buf is now null-terminated, we need to marshall as not
4289 * We cannot overflow ...
4291 if ((ofs
+ 24 + namelen
) > max_data_bytes
) {
4292 DEBUG(10, ("refusing to overflow reply at stream %u\n",
4294 TALLOC_FREE(namebuf
);
4295 return STATUS_BUFFER_OVERFLOW
;
4298 SIVAL(data
, ofs
+4, namelen
);
4299 SOFF_T(data
, ofs
+8, streams
[i
].size
);
4300 SOFF_T(data
, ofs
+16, streams
[i
].alloc_size
);
4301 memcpy(data
+ofs
+24, namebuf
, namelen
);
4302 TALLOC_FREE(namebuf
);
4304 next_offset
= ofs
+ 24 + namelen
;
4306 if (i
== num_streams
-1) {
4307 SIVAL(data
, ofs
, 0);
4310 unsigned int align
= ndr_align_size(next_offset
, 8);
4312 if ((next_offset
+ align
) > max_data_bytes
) {
4313 DEBUG(10, ("refusing to overflow align "
4314 "reply at stream %u\n",
4316 TALLOC_FREE(namebuf
);
4317 return STATUS_BUFFER_OVERFLOW
;
4320 memset(data
+next_offset
, 0, align
);
4321 next_offset
+= align
;
4323 SIVAL(data
, ofs
, next_offset
- ofs
);
4330 DEBUG(10, ("max_data: %u, data_size: %u\n", max_data_bytes
, ofs
));
4334 return NT_STATUS_OK
;
4337 /****************************************************************************
4338 Reply to a TRANSACT2_QFILEINFO on a PIPE !
4339 ****************************************************************************/
4341 static void call_trans2qpipeinfo(connection_struct
*conn
,
4342 struct smb_request
*req
,
4343 unsigned int tran_call
,
4344 char **pparams
, int total_params
,
4345 char **ppdata
, int total_data
,
4346 unsigned int max_data_bytes
)
4348 char *params
= *pparams
;
4349 char *pdata
= *ppdata
;
4350 unsigned int data_size
= 0;
4351 unsigned int param_size
= 2;
4356 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4360 if (total_params
< 4) {
4361 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4365 fsp
= file_fsp(req
, SVAL(params
,0));
4366 if (!fsp_is_np(fsp
)) {
4367 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
4371 info_level
= SVAL(params
,2);
4373 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
4374 if (*pparams
== NULL
) {
4375 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
4380 data_size
= max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
;
4381 *ppdata
= (char *)SMB_REALLOC(*ppdata
, data_size
);
4382 if (*ppdata
== NULL
) {
4383 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
4388 switch (info_level
) {
4389 case SMB_FILE_STANDARD_INFORMATION
:
4391 SOFF_T(pdata
,0,4096LL);
4398 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
4402 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, param_size
, *ppdata
, data_size
,
4408 NTSTATUS
smbd_do_qfilepathinfo(connection_struct
*conn
,
4409 TALLOC_CTX
*mem_ctx
,
4410 uint16_t info_level
,
4412 struct smb_filename
*smb_fname
,
4413 bool delete_pending
,
4414 struct timespec write_time_ts
,
4415 struct ea_list
*ea_list
,
4416 int lock_data_count
,
4419 unsigned int max_data_bytes
,
4421 unsigned int *pdata_size
)
4423 char *pdata
= *ppdata
;
4424 char *dstart
, *dend
;
4425 unsigned int data_size
;
4426 struct timespec create_time_ts
, mtime_ts
, atime_ts
, ctime_ts
;
4427 time_t create_time
, mtime
, atime
, c_time
;
4428 SMB_STRUCT_STAT
*psbuf
= &smb_fname
->st
;
4435 uint64_t file_size
= 0;
4437 uint64_t allocation_size
= 0;
4438 uint64_t file_index
= 0;
4439 uint32_t access_mask
= 0;
4441 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
4442 return NT_STATUS_INVALID_LEVEL
;
4445 DEBUG(5,("smbd_do_qfilepathinfo: %s (%s) level=%d max_data=%u\n",
4446 smb_fname_str_dbg(smb_fname
),
4448 info_level
, max_data_bytes
));
4450 mode
= dos_mode(conn
, smb_fname
);
4451 nlink
= psbuf
->st_ex_nlink
;
4453 if (nlink
&& (mode
&FILE_ATTRIBUTE_DIRECTORY
)) {
4457 if ((nlink
> 0) && delete_pending
) {
4461 data_size
= max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
;
4462 *ppdata
= (char *)SMB_REALLOC(*ppdata
, data_size
);
4463 if (*ppdata
== NULL
) {
4464 return NT_STATUS_NO_MEMORY
;
4468 dend
= dstart
+ data_size
- 1;
4470 if (!null_timespec(write_time_ts
) && !INFO_LEVEL_IS_UNIX(info_level
)) {
4471 update_stat_ex_mtime(psbuf
, write_time_ts
);
4474 create_time_ts
= get_create_timespec(conn
, fsp
, smb_fname
);
4475 mtime_ts
= psbuf
->st_ex_mtime
;
4476 atime_ts
= psbuf
->st_ex_atime
;
4477 ctime_ts
= get_change_timespec(conn
, fsp
, smb_fname
);
4479 if (lp_dos_filetime_resolution(SNUM(conn
))) {
4480 dos_filetime_timespec(&create_time_ts
);
4481 dos_filetime_timespec(&mtime_ts
);
4482 dos_filetime_timespec(&atime_ts
);
4483 dos_filetime_timespec(&ctime_ts
);
4486 create_time
= convert_timespec_to_time_t(create_time_ts
);
4487 mtime
= convert_timespec_to_time_t(mtime_ts
);
4488 atime
= convert_timespec_to_time_t(atime_ts
);
4489 c_time
= convert_timespec_to_time_t(ctime_ts
);
4491 p
= strrchr_m(smb_fname
->base_name
,'/');
4493 base_name
= smb_fname
->base_name
;
4497 /* NT expects the name to be in an exact form of the *full*
4498 filename. See the trans2 torture test */
4499 if (ISDOT(base_name
)) {
4500 dos_fname
= talloc_strdup(mem_ctx
, "\\");
4502 return NT_STATUS_NO_MEMORY
;
4505 dos_fname
= talloc_asprintf(mem_ctx
,
4507 smb_fname
->base_name
);
4509 return NT_STATUS_NO_MEMORY
;
4511 if (is_ntfs_stream_smb_fname(smb_fname
)) {
4512 dos_fname
= talloc_asprintf(dos_fname
, "%s",
4513 smb_fname
->stream_name
);
4515 return NT_STATUS_NO_MEMORY
;
4519 string_replace(dos_fname
, '/', '\\');
4522 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
, fsp
, psbuf
);
4525 /* Do we have this path open ? */
4527 struct file_id fileid
= vfs_file_id_from_sbuf(conn
, psbuf
);
4528 fsp1
= file_find_di_first(conn
->sconn
, fileid
);
4529 if (fsp1
&& fsp1
->initial_allocation_size
) {
4530 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
, fsp1
, psbuf
);
4534 if (!(mode
& FILE_ATTRIBUTE_DIRECTORY
)) {
4535 file_size
= get_file_size_stat(psbuf
);
4539 pos
= fsp
->fh
->position_information
;
4543 access_mask
= fsp
->access_mask
;
4545 /* GENERIC_EXECUTE mapping from Windows */
4546 access_mask
= 0x12019F;
4549 /* This should be an index number - looks like
4552 I think this causes us to fail the IFSKIT
4553 BasicFileInformationTest. -tpot */
4554 file_index
= get_FileIndex(conn
, psbuf
);
4556 switch (info_level
) {
4557 case SMB_INFO_STANDARD
:
4558 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4560 srv_put_dos_date2(pdata
,l1_fdateCreation
,create_time
);
4561 srv_put_dos_date2(pdata
,l1_fdateLastAccess
,atime
);
4562 srv_put_dos_date2(pdata
,l1_fdateLastWrite
,mtime
); /* write time */
4563 SIVAL(pdata
,l1_cbFile
,(uint32
)file_size
);
4564 SIVAL(pdata
,l1_cbFileAlloc
,(uint32
)allocation_size
);
4565 SSVAL(pdata
,l1_attrFile
,mode
);
4568 case SMB_INFO_QUERY_EA_SIZE
:
4570 unsigned int ea_size
=
4571 estimate_ea_size(conn
, fsp
,
4573 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4575 srv_put_dos_date2(pdata
,0,create_time
);
4576 srv_put_dos_date2(pdata
,4,atime
);
4577 srv_put_dos_date2(pdata
,8,mtime
); /* write time */
4578 SIVAL(pdata
,12,(uint32
)file_size
);
4579 SIVAL(pdata
,16,(uint32
)allocation_size
);
4580 SSVAL(pdata
,20,mode
);
4581 SIVAL(pdata
,22,ea_size
);
4585 case SMB_INFO_IS_NAME_VALID
:
4586 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4588 /* os/2 needs this ? really ?*/
4589 return NT_STATUS_DOS(ERRDOS
, ERRbadfunc
);
4591 /* This is only reached for qpathinfo */
4595 case SMB_INFO_QUERY_EAS_FROM_LIST
:
4597 size_t total_ea_len
= 0;
4598 struct ea_list
*ea_file_list
= NULL
;
4599 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4602 get_ea_list_from_file(mem_ctx
, conn
, fsp
,
4604 &total_ea_len
, &ea_file_list
);
4605 if (!NT_STATUS_IS_OK(status
)) {
4609 ea_list
= ea_list_union(ea_list
, ea_file_list
, &total_ea_len
);
4611 if (!ea_list
|| (total_ea_len
> data_size
)) {
4613 SIVAL(pdata
,0,4); /* EA List Length must be set to 4 if no EA's. */
4617 data_size
= fill_ea_buffer(mem_ctx
, pdata
, data_size
, conn
, ea_list
);
4621 case SMB_INFO_QUERY_ALL_EAS
:
4623 /* We have data_size bytes to put EA's into. */
4624 size_t total_ea_len
= 0;
4625 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4627 status
= get_ea_list_from_file(mem_ctx
, conn
, fsp
,
4629 &total_ea_len
, &ea_list
);
4630 if (!NT_STATUS_IS_OK(status
)) {
4634 if (!ea_list
|| (total_ea_len
> data_size
)) {
4636 SIVAL(pdata
,0,4); /* EA List Length must be set to 4 if no EA's. */
4640 data_size
= fill_ea_buffer(mem_ctx
, pdata
, data_size
, conn
, ea_list
);
4644 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
4646 /* This is FileFullEaInformation - 0xF which maps to
4647 * 1015 (decimal) in smbd_do_setfilepathinfo. */
4649 /* We have data_size bytes to put EA's into. */
4650 size_t total_ea_len
= 0;
4651 struct ea_list
*ea_file_list
= NULL
;
4653 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
4655 /*TODO: add filtering and index handling */
4658 get_ea_list_from_file(mem_ctx
, conn
, fsp
,
4660 &total_ea_len
, &ea_file_list
);
4661 if (!NT_STATUS_IS_OK(status
)) {
4664 if (!ea_file_list
) {
4665 return NT_STATUS_NO_EAS_ON_FILE
;
4668 status
= fill_ea_chained_buffer(mem_ctx
,
4672 conn
, ea_file_list
);
4673 if (!NT_STATUS_IS_OK(status
)) {
4679 case SMB_FILE_BASIC_INFORMATION
:
4680 case SMB_QUERY_FILE_BASIC_INFO
:
4682 if (info_level
== SMB_QUERY_FILE_BASIC_INFO
) {
4683 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4684 data_size
= 36; /* w95 returns 40 bytes not 36 - why ?. */
4686 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4690 put_long_date_timespec(conn
->ts_res
,pdata
,create_time_ts
);
4691 put_long_date_timespec(conn
->ts_res
,pdata
+8,atime_ts
);
4692 put_long_date_timespec(conn
->ts_res
,pdata
+16,mtime_ts
); /* write time */
4693 put_long_date_timespec(conn
->ts_res
,pdata
+24,ctime_ts
); /* change time */
4694 SIVAL(pdata
,32,mode
);
4696 DEBUG(5,("SMB_QFBI - "));
4697 DEBUG(5,("create: %s ", ctime(&create_time
)));
4698 DEBUG(5,("access: %s ", ctime(&atime
)));
4699 DEBUG(5,("write: %s ", ctime(&mtime
)));
4700 DEBUG(5,("change: %s ", ctime(&c_time
)));
4701 DEBUG(5,("mode: %x\n", mode
));
4704 case SMB_FILE_STANDARD_INFORMATION
:
4705 case SMB_QUERY_FILE_STANDARD_INFO
:
4707 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4709 SOFF_T(pdata
,0,allocation_size
);
4710 SOFF_T(pdata
,8,file_size
);
4711 SIVAL(pdata
,16,nlink
);
4712 SCVAL(pdata
,20,delete_pending
?1:0);
4713 SCVAL(pdata
,21,(mode
&FILE_ATTRIBUTE_DIRECTORY
)?1:0);
4714 SSVAL(pdata
,22,0); /* Padding. */
4717 case SMB_FILE_EA_INFORMATION
:
4718 case SMB_QUERY_FILE_EA_INFO
:
4720 unsigned int ea_size
=
4721 estimate_ea_size(conn
, fsp
, smb_fname
);
4722 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4724 SIVAL(pdata
,0,ea_size
);
4728 /* Get the 8.3 name - used if NT SMB was negotiated. */
4729 case SMB_QUERY_FILE_ALT_NAME_INFO
:
4730 case SMB_FILE_ALTERNATE_NAME_INFORMATION
:
4733 char mangled_name
[13];
4734 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4735 if (!name_to_8_3(base_name
,mangled_name
,
4736 True
,conn
->params
)) {
4737 return NT_STATUS_NO_MEMORY
;
4739 len
= srvstr_push(dstart
, flags2
,
4740 pdata
+4, mangled_name
,
4741 PTR_DIFF(dend
, pdata
+4),
4743 data_size
= 4 + len
;
4748 case SMB_QUERY_FILE_NAME_INFO
:
4752 this must be *exactly* right for ACLs on mapped drives to work
4754 len
= srvstr_push(dstart
, flags2
,
4756 PTR_DIFF(dend
, pdata
+4),
4758 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4759 data_size
= 4 + len
;
4764 case SMB_FILE_ALLOCATION_INFORMATION
:
4765 case SMB_QUERY_FILE_ALLOCATION_INFO
:
4766 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4768 SOFF_T(pdata
,0,allocation_size
);
4771 case SMB_FILE_END_OF_FILE_INFORMATION
:
4772 case SMB_QUERY_FILE_END_OF_FILEINFO
:
4773 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4775 SOFF_T(pdata
,0,file_size
);
4778 case SMB_QUERY_FILE_ALL_INFO
:
4779 case SMB_FILE_ALL_INFORMATION
:
4782 unsigned int ea_size
=
4783 estimate_ea_size(conn
, fsp
, smb_fname
);
4784 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4785 put_long_date_timespec(conn
->ts_res
,pdata
,create_time_ts
);
4786 put_long_date_timespec(conn
->ts_res
,pdata
+8,atime_ts
);
4787 put_long_date_timespec(conn
->ts_res
,pdata
+16,mtime_ts
); /* write time */
4788 put_long_date_timespec(conn
->ts_res
,pdata
+24,ctime_ts
); /* change time */
4789 SIVAL(pdata
,32,mode
);
4790 SIVAL(pdata
,36,0); /* padding. */
4792 SOFF_T(pdata
,0,allocation_size
);
4793 SOFF_T(pdata
,8,file_size
);
4794 SIVAL(pdata
,16,nlink
);
4795 SCVAL(pdata
,20,delete_pending
);
4796 SCVAL(pdata
,21,(mode
&FILE_ATTRIBUTE_DIRECTORY
)?1:0);
4799 SIVAL(pdata
,0,ea_size
);
4800 pdata
+= 4; /* EA info */
4801 len
= srvstr_push(dstart
, flags2
,
4803 PTR_DIFF(dend
, pdata
+4),
4807 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4811 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
4814 unsigned int ea_size
=
4815 estimate_ea_size(conn
, fsp
, smb_fname
);
4816 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
4817 put_long_date_timespec(conn
->ts_res
,pdata
+0x00,create_time_ts
);
4818 put_long_date_timespec(conn
->ts_res
,pdata
+0x08,atime_ts
);
4819 put_long_date_timespec(conn
->ts_res
,pdata
+0x10,mtime_ts
); /* write time */
4820 put_long_date_timespec(conn
->ts_res
,pdata
+0x18,ctime_ts
); /* change time */
4821 SIVAL(pdata
, 0x20, mode
);
4822 SIVAL(pdata
, 0x24, 0); /* padding. */
4823 SBVAL(pdata
, 0x28, allocation_size
);
4824 SBVAL(pdata
, 0x30, file_size
);
4825 SIVAL(pdata
, 0x38, nlink
);
4826 SCVAL(pdata
, 0x3C, delete_pending
);
4827 SCVAL(pdata
, 0x3D, (mode
&FILE_ATTRIBUTE_DIRECTORY
)?1:0);
4828 SSVAL(pdata
, 0x3E, 0); /* padding */
4829 SBVAL(pdata
, 0x40, file_index
);
4830 SIVAL(pdata
, 0x48, ea_size
);
4831 SIVAL(pdata
, 0x4C, access_mask
);
4832 SBVAL(pdata
, 0x50, pos
);
4833 SIVAL(pdata
, 0x58, mode
); /*TODO: mode != mode fix this!!! */
4834 SIVAL(pdata
, 0x5C, 0); /* No alignment needed. */
4838 len
= srvstr_push(dstart
, flags2
,
4840 PTR_DIFF(dend
, pdata
+4),
4844 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4847 case SMB_FILE_INTERNAL_INFORMATION
:
4849 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4850 SBVAL(pdata
, 0, file_index
);
4854 case SMB_FILE_ACCESS_INFORMATION
:
4855 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4856 SIVAL(pdata
, 0, access_mask
);
4860 case SMB_FILE_NAME_INFORMATION
:
4861 /* Pathname with leading '\'. */
4864 byte_len
= dos_PutUniCode(pdata
+4,dos_fname
,(size_t)max_data_bytes
,False
);
4865 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4866 SIVAL(pdata
,0,byte_len
);
4867 data_size
= 4 + byte_len
;
4871 case SMB_FILE_DISPOSITION_INFORMATION
:
4872 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4874 SCVAL(pdata
,0,delete_pending
);
4877 case SMB_FILE_POSITION_INFORMATION
:
4878 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4880 SOFF_T(pdata
,0,pos
);
4883 case SMB_FILE_MODE_INFORMATION
:
4884 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4885 SIVAL(pdata
,0,mode
);
4889 case SMB_FILE_ALIGNMENT_INFORMATION
:
4890 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4891 SIVAL(pdata
,0,0); /* No alignment needed. */
4896 * NT4 server just returns "invalid query" to this - if we try
4897 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4900 /* The first statement above is false - verified using Thursby
4901 * client against NT4 -- gcolley.
4903 case SMB_QUERY_FILE_STREAM_INFO
:
4904 case SMB_FILE_STREAM_INFORMATION
: {
4905 unsigned int num_streams
= 0;
4906 struct stream_struct
*streams
= NULL
;
4908 DEBUG(10,("smbd_do_qfilepathinfo: "
4909 "SMB_FILE_STREAM_INFORMATION\n"));
4911 if (is_ntfs_stream_smb_fname(smb_fname
)) {
4912 return NT_STATUS_INVALID_PARAMETER
;
4915 status
= vfs_streaminfo(conn
, fsp
, smb_fname
->base_name
,
4916 talloc_tos(), &num_streams
, &streams
);
4918 if (!NT_STATUS_IS_OK(status
)) {
4919 DEBUG(10, ("could not get stream info: %s\n",
4920 nt_errstr(status
)));
4924 status
= marshall_stream_info(num_streams
, streams
,
4925 pdata
, max_data_bytes
,
4928 if (!NT_STATUS_IS_OK(status
)) {
4929 DEBUG(10, ("marshall_stream_info failed: %s\n",
4930 nt_errstr(status
)));
4931 TALLOC_FREE(streams
);
4935 TALLOC_FREE(streams
);
4939 case SMB_QUERY_COMPRESSION_INFO
:
4940 case SMB_FILE_COMPRESSION_INFORMATION
:
4941 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4942 SOFF_T(pdata
,0,file_size
);
4943 SIVAL(pdata
,8,0); /* ??? */
4944 SIVAL(pdata
,12,0); /* ??? */
4948 case SMB_FILE_NETWORK_OPEN_INFORMATION
:
4949 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4950 put_long_date_timespec(conn
->ts_res
,pdata
,create_time_ts
);
4951 put_long_date_timespec(conn
->ts_res
,pdata
+8,atime_ts
);
4952 put_long_date_timespec(conn
->ts_res
,pdata
+16,mtime_ts
); /* write time */
4953 put_long_date_timespec(conn
->ts_res
,pdata
+24,ctime_ts
); /* change time */
4954 SOFF_T(pdata
,32,allocation_size
);
4955 SOFF_T(pdata
,40,file_size
);
4956 SIVAL(pdata
,48,mode
);
4957 SIVAL(pdata
,52,0); /* ??? */
4961 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION
:
4962 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4963 SIVAL(pdata
,0,mode
);
4969 * CIFS UNIX Extensions.
4972 case SMB_QUERY_FILE_UNIX_BASIC
:
4974 pdata
= store_file_unix_basic(conn
, pdata
, fsp
, psbuf
);
4975 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4977 DEBUG(4,("smbd_do_qfilepathinfo: "
4978 "SMB_QUERY_FILE_UNIX_BASIC\n"));
4979 dump_data(4, (uint8_t *)(*ppdata
), data_size
);
4983 case SMB_QUERY_FILE_UNIX_INFO2
:
4985 pdata
= store_file_unix_basic_info2(conn
, pdata
, fsp
, psbuf
);
4986 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4990 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4992 for (i
=0; i
<100; i
++)
4993 DEBUG(4,("%d=%x, ",i
, (*ppdata
)[i
]));
4999 case SMB_QUERY_FILE_UNIX_LINK
:
5002 char *buffer
= talloc_array(mem_ctx
, char, PATH_MAX
+1);
5005 return NT_STATUS_NO_MEMORY
;
5008 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
5010 if(!S_ISLNK(psbuf
->st_ex_mode
)) {
5011 return NT_STATUS_DOS(ERRSRV
, ERRbadlink
);
5014 return NT_STATUS_DOS(ERRDOS
, ERRbadlink
);
5016 len
= SMB_VFS_READLINK(conn
,
5017 smb_fname
->base_name
,
5020 return map_nt_error_from_unix(errno
);
5023 len
= srvstr_push(dstart
, flags2
,
5025 PTR_DIFF(dend
, pdata
),
5028 data_size
= PTR_DIFF(pdata
,(*ppdata
));
5033 #if defined(HAVE_POSIX_ACLS)
5034 case SMB_QUERY_POSIX_ACL
:
5036 SMB_ACL_T file_acl
= NULL
;
5037 SMB_ACL_T def_acl
= NULL
;
5038 uint16 num_file_acls
= 0;
5039 uint16 num_def_acls
= 0;
5041 if (fsp
&& fsp
->fh
->fd
!= -1) {
5042 file_acl
= SMB_VFS_SYS_ACL_GET_FD(fsp
,
5046 SMB_VFS_SYS_ACL_GET_FILE(conn
,
5047 smb_fname
->base_name
,
5048 SMB_ACL_TYPE_ACCESS
,
5052 if (file_acl
== NULL
&& no_acl_syscall_error(errno
)) {
5053 DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
5054 "not implemented on "
5055 "filesystem containing %s\n",
5056 smb_fname
->base_name
));
5057 return NT_STATUS_NOT_IMPLEMENTED
;
5060 if (S_ISDIR(psbuf
->st_ex_mode
)) {
5061 if (fsp
&& fsp
->is_directory
) {
5063 SMB_VFS_SYS_ACL_GET_FILE(
5065 fsp
->fsp_name
->base_name
,
5066 SMB_ACL_TYPE_DEFAULT
,
5070 SMB_VFS_SYS_ACL_GET_FILE(
5072 smb_fname
->base_name
,
5073 SMB_ACL_TYPE_DEFAULT
,
5076 def_acl
= free_empty_sys_acl(conn
, def_acl
);
5079 num_file_acls
= count_acl_entries(conn
, file_acl
);
5080 num_def_acls
= count_acl_entries(conn
, def_acl
);
5082 if ( data_size
< (num_file_acls
+ num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
+ SMB_POSIX_ACL_HEADER_SIZE
) {
5083 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
5085 (unsigned int)((num_file_acls
+ num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
+
5086 SMB_POSIX_ACL_HEADER_SIZE
) ));
5088 TALLOC_FREE(file_acl
);
5091 TALLOC_FREE(def_acl
);
5093 return NT_STATUS_BUFFER_TOO_SMALL
;
5096 SSVAL(pdata
,0,SMB_POSIX_ACL_VERSION
);
5097 SSVAL(pdata
,2,num_file_acls
);
5098 SSVAL(pdata
,4,num_def_acls
);
5099 if (!marshall_posix_acl(conn
, pdata
+ SMB_POSIX_ACL_HEADER_SIZE
, psbuf
, file_acl
)) {
5101 TALLOC_FREE(file_acl
);
5104 TALLOC_FREE(def_acl
);
5106 return NT_STATUS_INTERNAL_ERROR
;
5108 if (!marshall_posix_acl(conn
, pdata
+ SMB_POSIX_ACL_HEADER_SIZE
+ (num_file_acls
*SMB_POSIX_ACL_ENTRY_SIZE
), psbuf
, def_acl
)) {
5110 TALLOC_FREE(file_acl
);
5113 TALLOC_FREE(def_acl
);
5115 return NT_STATUS_INTERNAL_ERROR
;
5119 TALLOC_FREE(file_acl
);
5122 TALLOC_FREE(def_acl
);
5124 data_size
= (num_file_acls
+ num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
+ SMB_POSIX_ACL_HEADER_SIZE
;
5130 case SMB_QUERY_POSIX_LOCK
:
5135 enum brl_type lock_type
;
5137 /* We need an open file with a real fd for this. */
5138 if (!fsp
|| fsp
->fh
->fd
== -1) {
5139 return NT_STATUS_INVALID_LEVEL
;
5142 if (lock_data_count
!= POSIX_LOCK_DATA_SIZE
) {
5143 return NT_STATUS_INVALID_PARAMETER
;
5146 switch (SVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
)) {
5147 case POSIX_LOCK_TYPE_READ
:
5148 lock_type
= READ_LOCK
;
5150 case POSIX_LOCK_TYPE_WRITE
:
5151 lock_type
= WRITE_LOCK
;
5153 case POSIX_LOCK_TYPE_UNLOCK
:
5155 /* There's no point in asking for an unlock... */
5156 return NT_STATUS_INVALID_PARAMETER
;
5159 smblctx
= (uint64_t)IVAL(pdata
, POSIX_LOCK_PID_OFFSET
);
5160 #if defined(HAVE_LONGLONG)
5161 offset
= (((uint64_t) IVAL(pdata
,(POSIX_LOCK_START_OFFSET
+4))) << 32) |
5162 ((uint64_t) IVAL(pdata
,POSIX_LOCK_START_OFFSET
));
5163 count
= (((uint64_t) IVAL(pdata
,(POSIX_LOCK_LEN_OFFSET
+4))) << 32) |
5164 ((uint64_t) IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
));
5165 #else /* HAVE_LONGLONG */
5166 offset
= (uint64_t)IVAL(pdata
,POSIX_LOCK_START_OFFSET
);
5167 count
= (uint64_t)IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
);
5168 #endif /* HAVE_LONGLONG */
5170 status
= query_lock(fsp
,
5177 if (ERROR_WAS_LOCK_DENIED(status
)) {
5178 /* Here we need to report who has it locked... */
5179 data_size
= POSIX_LOCK_DATA_SIZE
;
5181 SSVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
, lock_type
);
5182 SSVAL(pdata
, POSIX_LOCK_FLAGS_OFFSET
, 0);
5183 SIVAL(pdata
, POSIX_LOCK_PID_OFFSET
, (uint32_t)smblctx
);
5184 #if defined(HAVE_LONGLONG)
5185 SIVAL(pdata
, POSIX_LOCK_START_OFFSET
, (uint32
)(offset
& 0xFFFFFFFF));
5186 SIVAL(pdata
, POSIX_LOCK_START_OFFSET
+ 4, (uint32
)((offset
>> 32) & 0xFFFFFFFF));
5187 SIVAL(pdata
, POSIX_LOCK_LEN_OFFSET
, (uint32
)(count
& 0xFFFFFFFF));
5188 SIVAL(pdata
, POSIX_LOCK_LEN_OFFSET
+ 4, (uint32
)((count
>> 32) & 0xFFFFFFFF));
5189 #else /* HAVE_LONGLONG */
5190 SIVAL(pdata
, POSIX_LOCK_START_OFFSET
, offset
);
5191 SIVAL(pdata
, POSIX_LOCK_LEN_OFFSET
, count
);
5192 #endif /* HAVE_LONGLONG */
5194 } else if (NT_STATUS_IS_OK(status
)) {
5195 /* For success we just return a copy of what we sent
5196 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
5197 data_size
= POSIX_LOCK_DATA_SIZE
;
5198 memcpy(pdata
, lock_data
, POSIX_LOCK_DATA_SIZE
);
5199 SSVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
, POSIX_LOCK_TYPE_UNLOCK
);
5207 return NT_STATUS_INVALID_LEVEL
;
5210 *pdata_size
= data_size
;
5211 return NT_STATUS_OK
;
5214 /****************************************************************************
5215 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
5216 file name or file id).
5217 ****************************************************************************/
5219 static void call_trans2qfilepathinfo(connection_struct
*conn
,
5220 struct smb_request
*req
,
5221 unsigned int tran_call
,
5222 char **pparams
, int total_params
,
5223 char **ppdata
, int total_data
,
5224 unsigned int max_data_bytes
)
5226 char *params
= *pparams
;
5227 char *pdata
= *ppdata
;
5229 unsigned int data_size
= 0;
5230 unsigned int param_size
= 2;
5231 struct smb_filename
*smb_fname
= NULL
;
5232 bool delete_pending
= False
;
5233 struct timespec write_time_ts
;
5234 files_struct
*fsp
= NULL
;
5235 struct file_id fileid
;
5236 struct ea_list
*ea_list
= NULL
;
5237 int lock_data_count
= 0;
5238 char *lock_data
= NULL
;
5239 NTSTATUS status
= NT_STATUS_OK
;
5242 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5246 ZERO_STRUCT(write_time_ts
);
5248 if (tran_call
== TRANSACT2_QFILEINFO
) {
5249 if (total_params
< 4) {
5250 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5255 call_trans2qpipeinfo(conn
, req
, tran_call
,
5256 pparams
, total_params
,
5262 fsp
= file_fsp(req
, SVAL(params
,0));
5263 info_level
= SVAL(params
,2);
5265 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level
));
5267 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
5268 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
5272 /* Initial check for valid fsp ptr. */
5273 if (!check_fsp_open(conn
, req
, fsp
)) {
5277 status
= copy_smb_filename(talloc_tos(), fsp
->fsp_name
,
5279 if (!NT_STATUS_IS_OK(status
)) {
5280 reply_nterror(req
, status
);
5284 if(fsp
->fake_file_handle
) {
5286 * This is actually for the QUOTA_FAKE_FILE --metze
5289 /* We know this name is ok, it's already passed the checks. */
5291 } else if(fsp
->fh
->fd
== -1) {
5293 * This is actually a QFILEINFO on a directory
5294 * handle (returned from an NT SMB). NT5.0 seems
5295 * to do this call. JRA.
5298 if (INFO_LEVEL_IS_UNIX(info_level
)) {
5299 /* Always do lstat for UNIX calls. */
5300 if (SMB_VFS_LSTAT(conn
, smb_fname
)) {
5301 DEBUG(3,("call_trans2qfilepathinfo: "
5302 "SMB_VFS_LSTAT of %s failed "
5304 smb_fname_str_dbg(smb_fname
),
5307 map_nt_error_from_unix(errno
));
5310 } else if (SMB_VFS_STAT(conn
, smb_fname
)) {
5311 DEBUG(3,("call_trans2qfilepathinfo: "
5312 "SMB_VFS_STAT of %s failed (%s)\n",
5313 smb_fname_str_dbg(smb_fname
),
5316 map_nt_error_from_unix(errno
));
5320 fileid
= vfs_file_id_from_sbuf(conn
, &smb_fname
->st
);
5321 get_file_infos(fileid
, fsp
->name_hash
, &delete_pending
, &write_time_ts
);
5324 * Original code - this is an open file.
5326 if (SMB_VFS_FSTAT(fsp
, &smb_fname
->st
) != 0) {
5327 DEBUG(3, ("fstat of %s failed (%s)\n",
5328 fsp_fnum_dbg(fsp
), strerror(errno
)));
5330 map_nt_error_from_unix(errno
));
5333 fileid
= vfs_file_id_from_sbuf(conn
, &smb_fname
->st
);
5334 get_file_infos(fileid
, fsp
->name_hash
, &delete_pending
, &write_time_ts
);
5340 uint32_t ucf_flags
= 0;
5343 if (total_params
< 7) {
5344 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5348 info_level
= SVAL(params
,0);
5350 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level
));
5352 if (INFO_LEVEL_IS_UNIX(info_level
)) {
5353 if (!lp_unix_extensions()) {
5354 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
5357 if (info_level
== SMB_QUERY_FILE_UNIX_BASIC
||
5358 info_level
== SMB_QUERY_FILE_UNIX_INFO2
||
5359 info_level
== SMB_QUERY_FILE_UNIX_LINK
) {
5360 ucf_flags
|= UCF_UNIX_NAME_LOOKUP
;
5364 srvstr_get_path(req
, params
, req
->flags2
, &fname
, ¶ms
[6],
5366 STR_TERMINATE
, &status
);
5367 if (!NT_STATUS_IS_OK(status
)) {
5368 reply_nterror(req
, status
);
5372 status
= filename_convert(req
,
5374 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
5379 if (!NT_STATUS_IS_OK(status
)) {
5380 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
5381 reply_botherror(req
,
5382 NT_STATUS_PATH_NOT_COVERED
,
5383 ERRSRV
, ERRbadpath
);
5386 reply_nterror(req
, status
);
5390 /* If this is a stream, check if there is a delete_pending. */
5391 if ((conn
->fs_capabilities
& FILE_NAMED_STREAMS
)
5392 && is_ntfs_stream_smb_fname(smb_fname
)) {
5393 struct smb_filename
*smb_fname_base
= NULL
;
5395 /* Create an smb_filename with stream_name == NULL. */
5397 create_synthetic_smb_fname(talloc_tos(),
5398 smb_fname
->base_name
,
5401 if (!NT_STATUS_IS_OK(status
)) {
5402 reply_nterror(req
, status
);
5406 if (INFO_LEVEL_IS_UNIX(info_level
)) {
5407 /* Always do lstat for UNIX calls. */
5408 if (SMB_VFS_LSTAT(conn
, smb_fname_base
) != 0) {
5409 DEBUG(3,("call_trans2qfilepathinfo: "
5410 "SMB_VFS_LSTAT of %s failed "
5412 smb_fname_str_dbg(smb_fname_base
),
5414 TALLOC_FREE(smb_fname_base
);
5416 map_nt_error_from_unix(errno
));
5420 if (SMB_VFS_STAT(conn
, smb_fname_base
) != 0) {
5421 DEBUG(3,("call_trans2qfilepathinfo: "
5422 "fileinfo of %s failed "
5424 smb_fname_str_dbg(smb_fname_base
),
5426 TALLOC_FREE(smb_fname_base
);
5428 map_nt_error_from_unix(errno
));
5433 status
= file_name_hash(conn
,
5434 smb_fname_str_dbg(smb_fname_base
),
5436 if (!NT_STATUS_IS_OK(status
)) {
5437 TALLOC_FREE(smb_fname_base
);
5438 reply_nterror(req
, status
);
5442 fileid
= vfs_file_id_from_sbuf(conn
,
5443 &smb_fname_base
->st
);
5444 TALLOC_FREE(smb_fname_base
);
5445 get_file_infos(fileid
, name_hash
, &delete_pending
, NULL
);
5446 if (delete_pending
) {
5447 reply_nterror(req
, NT_STATUS_DELETE_PENDING
);
5452 if (INFO_LEVEL_IS_UNIX(info_level
)) {
5453 /* Always do lstat for UNIX calls. */
5454 if (SMB_VFS_LSTAT(conn
, smb_fname
)) {
5455 DEBUG(3,("call_trans2qfilepathinfo: "
5456 "SMB_VFS_LSTAT of %s failed (%s)\n",
5457 smb_fname_str_dbg(smb_fname
),
5460 map_nt_error_from_unix(errno
));
5465 if (SMB_VFS_STAT(conn
, smb_fname
) != 0) {
5466 DEBUG(3,("call_trans2qfilepathinfo: "
5467 "SMB_VFS_STAT of %s failed (%s)\n",
5468 smb_fname_str_dbg(smb_fname
),
5471 map_nt_error_from_unix(errno
));
5476 status
= file_name_hash(conn
,
5477 smb_fname_str_dbg(smb_fname
),
5479 if (!NT_STATUS_IS_OK(status
)) {
5480 reply_nterror(req
, status
);
5484 fileid
= vfs_file_id_from_sbuf(conn
, &smb_fname
->st
);
5485 get_file_infos(fileid
, name_hash
, &delete_pending
, &write_time_ts
);
5486 if (delete_pending
) {
5487 reply_nterror(req
, NT_STATUS_DELETE_PENDING
);
5492 DEBUG(3,("call_trans2qfilepathinfo %s (%s) level=%d call=%d "
5493 "total_data=%d\n", smb_fname_str_dbg(smb_fname
),
5495 info_level
,tran_call
,total_data
));
5497 /* Pull out any data sent here before we realloc. */
5498 switch (info_level
) {
5499 case SMB_INFO_QUERY_EAS_FROM_LIST
:
5501 /* Pull any EA list from the data portion. */
5504 if (total_data
< 4) {
5506 req
, NT_STATUS_INVALID_PARAMETER
);
5509 ea_size
= IVAL(pdata
,0);
5511 if (total_data
> 0 && ea_size
!= total_data
) {
5512 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5513 total_data=%u (should be %u)\n", (unsigned int)total_data
, (unsigned int)IVAL(pdata
,0) ));
5515 req
, NT_STATUS_INVALID_PARAMETER
);
5519 if (!lp_ea_support(SNUM(conn
))) {
5520 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
5524 /* Pull out the list of names. */
5525 ea_list
= read_ea_name_list(req
, pdata
+ 4, ea_size
- 4);
5528 req
, NT_STATUS_INVALID_PARAMETER
);
5534 case SMB_QUERY_POSIX_LOCK
:
5536 if (fsp
== NULL
|| fsp
->fh
->fd
== -1) {
5537 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
5541 if (total_data
!= POSIX_LOCK_DATA_SIZE
) {
5543 req
, NT_STATUS_INVALID_PARAMETER
);
5547 /* Copy the lock range data. */
5548 lock_data
= (char *)talloc_memdup(
5549 req
, pdata
, total_data
);
5551 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5554 lock_data_count
= total_data
;
5560 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
5561 if (*pparams
== NULL
) {
5562 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5569 * draft-leach-cifs-v1-spec-02.txt
5570 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
5573 * The requested information is placed in the Data portion of the
5574 * transaction response. For the information levels greater than 0x100,
5575 * the transaction response has 1 parameter word which should be
5576 * ignored by the client.
5578 * However Windows only follows this rule for the IS_NAME_VALID call.
5580 switch (info_level
) {
5581 case SMB_INFO_IS_NAME_VALID
:
5586 if ((info_level
& 0xFF00) == 0xFF00) {
5588 * We use levels that start with 0xFF00
5589 * internally to represent SMB2 specific levels
5591 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
5595 status
= smbd_do_qfilepathinfo(conn
, req
, info_level
,
5597 delete_pending
, write_time_ts
,
5599 lock_data_count
, lock_data
,
5600 req
->flags2
, max_data_bytes
,
5601 ppdata
, &data_size
);
5602 if (!NT_STATUS_IS_OK(status
)) {
5603 reply_nterror(req
, status
);
5607 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, param_size
, *ppdata
, data_size
,
5613 /****************************************************************************
5614 Set a hard link (called by UNIX extensions and by NT rename with HARD link
5616 ****************************************************************************/
5618 NTSTATUS
hardlink_internals(TALLOC_CTX
*ctx
,
5619 connection_struct
*conn
,
5620 struct smb_request
*req
,
5621 bool overwrite_if_exists
,
5622 const struct smb_filename
*smb_fname_old
,
5623 struct smb_filename
*smb_fname_new
)
5625 NTSTATUS status
= NT_STATUS_OK
;
5627 /* source must already exist. */
5628 if (!VALID_STAT(smb_fname_old
->st
)) {
5629 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5632 if (VALID_STAT(smb_fname_new
->st
)) {
5633 if (overwrite_if_exists
) {
5634 if (S_ISDIR(smb_fname_new
->st
.st_ex_mode
)) {
5635 return NT_STATUS_FILE_IS_A_DIRECTORY
;
5637 status
= unlink_internals(conn
,
5639 FILE_ATTRIBUTE_NORMAL
,
5642 if (!NT_STATUS_IS_OK(status
)) {
5646 /* Disallow if newname already exists. */
5647 return NT_STATUS_OBJECT_NAME_COLLISION
;
5651 /* No links from a directory. */
5652 if (S_ISDIR(smb_fname_old
->st
.st_ex_mode
)) {
5653 return NT_STATUS_FILE_IS_A_DIRECTORY
;
5656 /* Setting a hardlink to/from a stream isn't currently supported. */
5657 if (is_ntfs_stream_smb_fname(smb_fname_old
) ||
5658 is_ntfs_stream_smb_fname(smb_fname_new
)) {
5659 return NT_STATUS_INVALID_PARAMETER
;
5662 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
5663 smb_fname_old
->base_name
, smb_fname_new
->base_name
));
5665 if (SMB_VFS_LINK(conn
, smb_fname_old
->base_name
,
5666 smb_fname_new
->base_name
) != 0) {
5667 status
= map_nt_error_from_unix(errno
);
5668 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
5669 nt_errstr(status
), smb_fname_old
->base_name
,
5670 smb_fname_new
->base_name
));
5675 /****************************************************************************
5676 Deal with setting the time from any of the setfilepathinfo functions.
5677 NOTE !!!! The check for FILE_WRITE_ATTRIBUTES access must be done *before*
5678 calling this function.
5679 ****************************************************************************/
5681 NTSTATUS
smb_set_file_time(connection_struct
*conn
,
5683 const struct smb_filename
*smb_fname
,
5684 struct smb_file_time
*ft
,
5685 bool setting_write_time
)
5687 struct smb_filename smb_fname_base
;
5689 FILE_NOTIFY_CHANGE_LAST_ACCESS
5690 |FILE_NOTIFY_CHANGE_LAST_WRITE
5691 |FILE_NOTIFY_CHANGE_CREATION
;
5693 if (!VALID_STAT(smb_fname
->st
)) {
5694 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5697 /* get some defaults (no modifications) if any info is zero or -1. */
5698 if (null_timespec(ft
->create_time
)) {
5699 action
&= ~FILE_NOTIFY_CHANGE_CREATION
;
5702 if (null_timespec(ft
->atime
)) {
5703 action
&= ~FILE_NOTIFY_CHANGE_LAST_ACCESS
;
5706 if (null_timespec(ft
->mtime
)) {
5707 action
&= ~FILE_NOTIFY_CHANGE_LAST_WRITE
;
5710 if (!setting_write_time
) {
5711 /* ft->mtime comes from change time, not write time. */
5712 action
&= ~FILE_NOTIFY_CHANGE_LAST_WRITE
;
5715 /* Ensure the resolution is the correct for
5716 * what we can store on this filesystem. */
5718 round_timespec(conn
->ts_res
, &ft
->create_time
);
5719 round_timespec(conn
->ts_res
, &ft
->ctime
);
5720 round_timespec(conn
->ts_res
, &ft
->atime
);
5721 round_timespec(conn
->ts_res
, &ft
->mtime
);
5723 DEBUG(5,("smb_set_filetime: actime: %s\n ",
5724 time_to_asc(convert_timespec_to_time_t(ft
->atime
))));
5725 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
5726 time_to_asc(convert_timespec_to_time_t(ft
->mtime
))));
5727 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
5728 time_to_asc(convert_timespec_to_time_t(ft
->ctime
))));
5729 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
5730 time_to_asc(convert_timespec_to_time_t(ft
->create_time
))));
5732 if (setting_write_time
) {
5734 * This was a Windows setfileinfo on an open file.
5735 * NT does this a lot. We also need to
5736 * set the time here, as it can be read by
5737 * FindFirst/FindNext and with the patch for bug #2045
5738 * in smbd/fileio.c it ensures that this timestamp is
5739 * kept sticky even after a write. We save the request
5740 * away and will set it on file close and after a write. JRA.
5743 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
5744 time_to_asc(convert_timespec_to_time_t(ft
->mtime
))));
5747 if (fsp
->base_fsp
) {
5748 set_sticky_write_time_fsp(fsp
->base_fsp
,
5751 set_sticky_write_time_fsp(fsp
, ft
->mtime
);
5754 set_sticky_write_time_path(
5755 vfs_file_id_from_sbuf(conn
, &smb_fname
->st
),
5760 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5762 /* Always call ntimes on the base, even if a stream was passed in. */
5763 smb_fname_base
= *smb_fname
;
5764 smb_fname_base
.stream_name
= NULL
;
5766 if(file_ntimes(conn
, &smb_fname_base
, ft
)!=0) {
5767 return map_nt_error_from_unix(errno
);
5770 notify_fname(conn
, NOTIFY_ACTION_MODIFIED
, action
,
5771 smb_fname
->base_name
);
5772 return NT_STATUS_OK
;
5775 /****************************************************************************
5776 Deal with setting the dosmode from any of the setfilepathinfo functions.
5777 NB. The check for FILE_WRITE_ATTRIBUTES access on this path must have been
5778 done before calling this function.
5779 ****************************************************************************/
5781 static NTSTATUS
smb_set_file_dosmode(connection_struct
*conn
,
5782 const struct smb_filename
*smb_fname
,
5785 struct smb_filename
*smb_fname_base
= NULL
;
5788 if (!VALID_STAT(smb_fname
->st
)) {
5789 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5792 /* Always operate on the base_name, even if a stream was passed in. */
5793 status
= create_synthetic_smb_fname(talloc_tos(), smb_fname
->base_name
,
5794 NULL
, &smb_fname
->st
,
5796 if (!NT_STATUS_IS_OK(status
)) {
5801 if (S_ISDIR(smb_fname_base
->st
.st_ex_mode
)) {
5802 dosmode
|= FILE_ATTRIBUTE_DIRECTORY
;
5804 dosmode
&= ~FILE_ATTRIBUTE_DIRECTORY
;
5808 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode
));
5810 /* check the mode isn't different, before changing it */
5811 if ((dosmode
!= 0) && (dosmode
!= dos_mode(conn
, smb_fname_base
))) {
5812 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
5813 "0x%x\n", smb_fname_str_dbg(smb_fname_base
),
5814 (unsigned int)dosmode
));
5816 if(file_set_dosmode(conn
, smb_fname_base
, dosmode
, NULL
,
5818 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
5820 smb_fname_str_dbg(smb_fname_base
),
5822 status
= map_nt_error_from_unix(errno
);
5826 status
= NT_STATUS_OK
;
5828 TALLOC_FREE(smb_fname_base
);
5832 /****************************************************************************
5833 Deal with setting the size from any of the setfilepathinfo functions.
5834 ****************************************************************************/
5836 static NTSTATUS
smb_set_file_size(connection_struct
*conn
,
5837 struct smb_request
*req
,
5839 const struct smb_filename
*smb_fname
,
5840 const SMB_STRUCT_STAT
*psbuf
,
5842 bool fail_after_createfile
)
5844 NTSTATUS status
= NT_STATUS_OK
;
5845 struct smb_filename
*smb_fname_tmp
= NULL
;
5846 files_struct
*new_fsp
= NULL
;
5848 if (!VALID_STAT(*psbuf
)) {
5849 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5852 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size
));
5854 if (size
== get_file_size_stat(psbuf
)) {
5855 return NT_STATUS_OK
;
5858 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5859 smb_fname_str_dbg(smb_fname
), (double)size
));
5861 if (fsp
&& fsp
->fh
->fd
!= -1) {
5862 /* Handle based call. */
5863 if (!(fsp
->access_mask
& FILE_WRITE_DATA
)) {
5864 return NT_STATUS_ACCESS_DENIED
;
5867 if (vfs_set_filelen(fsp
, size
) == -1) {
5868 return map_nt_error_from_unix(errno
);
5870 trigger_write_time_update_immediate(fsp
);
5871 return NT_STATUS_OK
;
5874 status
= copy_smb_filename(talloc_tos(), smb_fname
, &smb_fname_tmp
);
5875 if (!NT_STATUS_IS_OK(status
)) {
5879 smb_fname_tmp
->st
= *psbuf
;
5881 status
= SMB_VFS_CREATE_FILE(
5884 0, /* root_dir_fid */
5885 smb_fname_tmp
, /* fname */
5886 FILE_WRITE_DATA
, /* access_mask */
5887 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
5889 FILE_OPEN
, /* create_disposition*/
5890 0, /* create_options */
5891 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
5892 FORCE_OPLOCK_BREAK_TO_NONE
, /* oplock_request */
5893 0, /* allocation_size */
5894 0, /* private_flags */
5897 &new_fsp
, /* result */
5900 TALLOC_FREE(smb_fname_tmp
);
5902 if (!NT_STATUS_IS_OK(status
)) {
5903 /* NB. We check for open_was_deferred in the caller. */
5907 /* See RAW-SFILEINFO-END-OF-FILE */
5908 if (fail_after_createfile
) {
5909 close_file(req
, new_fsp
,NORMAL_CLOSE
);
5910 return NT_STATUS_INVALID_LEVEL
;
5913 if (vfs_set_filelen(new_fsp
, size
) == -1) {
5914 status
= map_nt_error_from_unix(errno
);
5915 close_file(req
, new_fsp
,NORMAL_CLOSE
);
5919 trigger_write_time_update_immediate(new_fsp
);
5920 close_file(req
, new_fsp
,NORMAL_CLOSE
);
5921 return NT_STATUS_OK
;
5924 /****************************************************************************
5925 Deal with SMB_INFO_SET_EA.
5926 ****************************************************************************/
5928 static NTSTATUS
smb_info_set_ea(connection_struct
*conn
,
5932 const struct smb_filename
*smb_fname
)
5934 struct ea_list
*ea_list
= NULL
;
5935 TALLOC_CTX
*ctx
= NULL
;
5936 NTSTATUS status
= NT_STATUS_OK
;
5938 if (total_data
< 10) {
5940 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5941 length. They seem to have no effect. Bug #3212. JRA */
5943 if ((total_data
== 4) && (IVAL(pdata
,0) == 4)) {
5944 /* We're done. We only get EA info in this call. */
5945 return NT_STATUS_OK
;
5948 return NT_STATUS_INVALID_PARAMETER
;
5951 if (IVAL(pdata
,0) > total_data
) {
5952 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5953 IVAL(pdata
,0), (unsigned int)total_data
));
5954 return NT_STATUS_INVALID_PARAMETER
;
5958 ea_list
= read_ea_list(ctx
, pdata
+ 4, total_data
- 4);
5960 return NT_STATUS_INVALID_PARAMETER
;
5963 status
= set_ea(conn
, fsp
, smb_fname
, ea_list
);
5968 /****************************************************************************
5969 Deal with SMB_FILE_FULL_EA_INFORMATION set.
5970 ****************************************************************************/
5972 static NTSTATUS
smb_set_file_full_ea_info(connection_struct
*conn
,
5977 struct ea_list
*ea_list
= NULL
;
5981 return NT_STATUS_INVALID_HANDLE
;
5984 if (!lp_ea_support(SNUM(conn
))) {
5985 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
5986 "EA's not supported.\n",
5987 (unsigned int)total_data
));
5988 return NT_STATUS_EAS_NOT_SUPPORTED
;
5991 if (total_data
< 10) {
5992 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
5994 (unsigned int)total_data
));
5995 return NT_STATUS_INVALID_PARAMETER
;
5998 ea_list
= read_nttrans_ea_list(talloc_tos(),
6003 return NT_STATUS_INVALID_PARAMETER
;
6006 status
= set_ea(conn
, fsp
, fsp
->fsp_name
, ea_list
);
6008 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
6009 smb_fname_str_dbg(fsp
->fsp_name
),
6010 nt_errstr(status
) ));
6016 /****************************************************************************
6017 Deal with SMB_SET_FILE_DISPOSITION_INFO.
6018 ****************************************************************************/
6020 static NTSTATUS
smb_set_file_disposition_info(connection_struct
*conn
,
6024 struct smb_filename
*smb_fname
)
6026 NTSTATUS status
= NT_STATUS_OK
;
6027 bool delete_on_close
;
6030 if (total_data
< 1) {
6031 return NT_STATUS_INVALID_PARAMETER
;
6035 return NT_STATUS_INVALID_HANDLE
;
6038 delete_on_close
= (CVAL(pdata
,0) ? True
: False
);
6039 dosmode
= dos_mode(conn
, smb_fname
);
6041 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
6042 "delete_on_close = %u\n",
6043 smb_fname_str_dbg(smb_fname
),
6044 (unsigned int)dosmode
,
6045 (unsigned int)delete_on_close
));
6047 if (delete_on_close
) {
6048 status
= can_set_delete_on_close(fsp
, dosmode
);
6049 if (!NT_STATUS_IS_OK(status
)) {
6054 /* The set is across all open files on this dev/inode pair. */
6055 if (!set_delete_on_close(fsp
, delete_on_close
,
6056 conn
->session_info
->security_token
,
6057 conn
->session_info
->unix_token
)) {
6058 return NT_STATUS_ACCESS_DENIED
;
6060 return NT_STATUS_OK
;
6063 /****************************************************************************
6064 Deal with SMB_FILE_POSITION_INFORMATION.
6065 ****************************************************************************/
6067 static NTSTATUS
smb_file_position_information(connection_struct
*conn
,
6072 uint64_t position_information
;
6074 if (total_data
< 8) {
6075 return NT_STATUS_INVALID_PARAMETER
;
6079 /* Ignore on pathname based set. */
6080 return NT_STATUS_OK
;
6083 position_information
= (uint64_t)IVAL(pdata
,0);
6084 position_information
|= (((uint64_t)IVAL(pdata
,4)) << 32);
6086 DEBUG(10,("smb_file_position_information: Set file position "
6087 "information for file %s to %.0f\n", fsp_str_dbg(fsp
),
6088 (double)position_information
));
6089 fsp
->fh
->position_information
= position_information
;
6090 return NT_STATUS_OK
;
6093 /****************************************************************************
6094 Deal with SMB_FILE_MODE_INFORMATION.
6095 ****************************************************************************/
6097 static NTSTATUS
smb_file_mode_information(connection_struct
*conn
,
6103 if (total_data
< 4) {
6104 return NT_STATUS_INVALID_PARAMETER
;
6106 mode
= IVAL(pdata
,0);
6107 if (mode
!= 0 && mode
!= 2 && mode
!= 4 && mode
!= 6) {
6108 return NT_STATUS_INVALID_PARAMETER
;
6110 return NT_STATUS_OK
;
6113 /****************************************************************************
6114 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
6115 ****************************************************************************/
6117 static NTSTATUS
smb_set_file_unix_link(connection_struct
*conn
,
6118 struct smb_request
*req
,
6121 const struct smb_filename
*smb_fname
)
6123 char *link_target
= NULL
;
6124 const char *newname
= smb_fname
->base_name
;
6125 TALLOC_CTX
*ctx
= talloc_tos();
6127 /* Set a symbolic link. */
6128 /* Don't allow this if follow links is false. */
6130 if (total_data
== 0) {
6131 return NT_STATUS_INVALID_PARAMETER
;
6134 if (!lp_symlinks(SNUM(conn
))) {
6135 return NT_STATUS_ACCESS_DENIED
;
6138 srvstr_pull_talloc(ctx
, pdata
, req
->flags2
, &link_target
, pdata
,
6139 total_data
, STR_TERMINATE
);
6142 return NT_STATUS_INVALID_PARAMETER
;
6145 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
6146 newname
, link_target
));
6148 if (SMB_VFS_SYMLINK(conn
,link_target
,newname
) != 0) {
6149 return map_nt_error_from_unix(errno
);
6152 return NT_STATUS_OK
;
6155 /****************************************************************************
6156 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
6157 ****************************************************************************/
6159 static NTSTATUS
smb_set_file_unix_hlink(connection_struct
*conn
,
6160 struct smb_request
*req
,
6161 const char *pdata
, int total_data
,
6162 struct smb_filename
*smb_fname_new
)
6164 char *oldname
= NULL
;
6165 struct smb_filename
*smb_fname_old
= NULL
;
6166 TALLOC_CTX
*ctx
= talloc_tos();
6167 NTSTATUS status
= NT_STATUS_OK
;
6169 /* Set a hard link. */
6170 if (total_data
== 0) {
6171 return NT_STATUS_INVALID_PARAMETER
;
6174 srvstr_get_path(ctx
, pdata
, req
->flags2
, &oldname
, pdata
,
6175 total_data
, STR_TERMINATE
, &status
);
6176 if (!NT_STATUS_IS_OK(status
)) {
6180 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
6181 smb_fname_str_dbg(smb_fname_new
), oldname
));
6183 status
= filename_convert(ctx
,
6185 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6190 if (!NT_STATUS_IS_OK(status
)) {
6194 return hardlink_internals(ctx
, conn
, req
, false,
6195 smb_fname_old
, smb_fname_new
);
6198 /****************************************************************************
6199 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
6200 ****************************************************************************/
6202 static NTSTATUS
smb2_file_rename_information(connection_struct
*conn
,
6203 struct smb_request
*req
,
6207 struct smb_filename
*smb_fname_src
)
6211 char *newname
= NULL
;
6212 struct smb_filename
*smb_fname_dst
= NULL
;
6213 NTSTATUS status
= NT_STATUS_OK
;
6214 TALLOC_CTX
*ctx
= talloc_tos();
6217 return NT_STATUS_INVALID_HANDLE
;
6220 if (total_data
< 20) {
6221 return NT_STATUS_INVALID_PARAMETER
;
6224 overwrite
= (CVAL(pdata
,0) ? True
: False
);
6225 len
= IVAL(pdata
,16);
6227 if (len
> (total_data
- 20) || (len
== 0)) {
6228 return NT_STATUS_INVALID_PARAMETER
;
6231 srvstr_get_path(ctx
, pdata
, req
->flags2
, &newname
,
6232 &pdata
[20], len
, STR_TERMINATE
,
6234 if (!NT_STATUS_IS_OK(status
)) {
6238 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
6241 status
= filename_convert(ctx
,
6243 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6248 if (!NT_STATUS_IS_OK(status
)) {
6252 if (fsp
->base_fsp
) {
6253 /* newname must be a stream name. */
6254 if (newname
[0] != ':') {
6255 return NT_STATUS_NOT_SUPPORTED
;
6258 /* Create an smb_fname to call rename_internals_fsp() with. */
6259 status
= create_synthetic_smb_fname(talloc_tos(),
6260 fsp
->base_fsp
->fsp_name
->base_name
, newname
, NULL
,
6262 if (!NT_STATUS_IS_OK(status
)) {
6267 * Set the original last component, since
6268 * rename_internals_fsp() requires it.
6270 smb_fname_dst
->original_lcomp
= talloc_strdup(smb_fname_dst
,
6272 if (smb_fname_dst
->original_lcomp
== NULL
) {
6273 status
= NT_STATUS_NO_MEMORY
;
6279 DEBUG(10,("smb2_file_rename_information: "
6280 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
6281 fsp_fnum_dbg(fsp
), fsp_str_dbg(fsp
),
6282 smb_fname_str_dbg(smb_fname_dst
)));
6283 status
= rename_internals_fsp(conn
, fsp
, smb_fname_dst
,
6284 (FILE_ATTRIBUTE_HIDDEN
|FILE_ATTRIBUTE_SYSTEM
),
6288 TALLOC_FREE(smb_fname_dst
);
6292 static NTSTATUS
smb_file_link_information(connection_struct
*conn
,
6293 struct smb_request
*req
,
6297 struct smb_filename
*smb_fname_src
)
6301 char *newname
= NULL
;
6302 struct smb_filename
*smb_fname_dst
= NULL
;
6303 NTSTATUS status
= NT_STATUS_OK
;
6304 TALLOC_CTX
*ctx
= talloc_tos();
6307 return NT_STATUS_INVALID_HANDLE
;
6310 if (total_data
< 20) {
6311 return NT_STATUS_INVALID_PARAMETER
;
6314 overwrite
= (CVAL(pdata
,0) ? true : false);
6315 len
= IVAL(pdata
,16);
6317 if (len
> (total_data
- 20) || (len
== 0)) {
6318 return NT_STATUS_INVALID_PARAMETER
;
6321 srvstr_get_path(ctx
, pdata
, req
->flags2
, &newname
,
6322 &pdata
[20], len
, STR_TERMINATE
,
6324 if (!NT_STATUS_IS_OK(status
)) {
6328 DEBUG(10,("smb_file_link_information: got name |%s|\n",
6331 status
= filename_convert(ctx
,
6333 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6338 if (!NT_STATUS_IS_OK(status
)) {
6342 if (fsp
->base_fsp
) {
6343 /* No stream names. */
6344 return NT_STATUS_NOT_SUPPORTED
;
6347 DEBUG(10,("smb_file_link_information: "
6348 "SMB_FILE_LINK_INFORMATION (%s) %s -> %s\n",
6349 fsp_fnum_dbg(fsp
), fsp_str_dbg(fsp
),
6350 smb_fname_str_dbg(smb_fname_dst
)));
6351 status
= hardlink_internals(ctx
,
6358 TALLOC_FREE(smb_fname_dst
);
6362 /****************************************************************************
6363 Deal with SMB_FILE_RENAME_INFORMATION.
6364 ****************************************************************************/
6366 static NTSTATUS
smb_file_rename_information(connection_struct
*conn
,
6367 struct smb_request
*req
,
6371 struct smb_filename
*smb_fname_src
)
6376 char *newname
= NULL
;
6377 struct smb_filename
*smb_fname_dst
= NULL
;
6378 bool dest_has_wcard
= False
;
6379 NTSTATUS status
= NT_STATUS_OK
;
6381 TALLOC_CTX
*ctx
= talloc_tos();
6383 if (total_data
< 13) {
6384 return NT_STATUS_INVALID_PARAMETER
;
6387 overwrite
= (CVAL(pdata
,0) ? True
: False
);
6388 root_fid
= IVAL(pdata
,4);
6389 len
= IVAL(pdata
,8);
6391 if (len
> (total_data
- 12) || (len
== 0) || (root_fid
!= 0)) {
6392 return NT_STATUS_INVALID_PARAMETER
;
6395 srvstr_get_path_wcard(ctx
, pdata
, req
->flags2
, &newname
, &pdata
[12],
6398 if (!NT_STATUS_IS_OK(status
)) {
6402 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
6405 status
= resolve_dfspath_wcard(ctx
, conn
,
6406 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6409 !conn
->sconn
->using_smb2
,
6412 if (!NT_STATUS_IS_OK(status
)) {
6416 /* Check the new name has no '/' characters. */
6417 if (strchr_m(newname
, '/')) {
6418 return NT_STATUS_NOT_SUPPORTED
;
6421 if (fsp
&& fsp
->base_fsp
) {
6422 /* newname must be a stream name. */
6423 if (newname
[0] != ':') {
6424 return NT_STATUS_NOT_SUPPORTED
;
6427 /* Create an smb_fname to call rename_internals_fsp() with. */
6428 status
= create_synthetic_smb_fname(talloc_tos(),
6429 fsp
->base_fsp
->fsp_name
->base_name
, newname
, NULL
,
6431 if (!NT_STATUS_IS_OK(status
)) {
6436 * Set the original last component, since
6437 * rename_internals_fsp() requires it.
6439 smb_fname_dst
->original_lcomp
= talloc_strdup(smb_fname_dst
,
6441 if (smb_fname_dst
->original_lcomp
== NULL
) {
6442 status
= NT_STATUS_NO_MEMORY
;
6448 * Build up an smb_fname_dst based on the filename passed in.
6449 * We basically just strip off the last component, and put on
6450 * the newname instead.
6452 char *base_name
= NULL
;
6454 /* newname must *not* be a stream name. */
6455 if (newname
[0] == ':') {
6456 return NT_STATUS_NOT_SUPPORTED
;
6460 * Strip off the last component (filename) of the path passed
6463 base_name
= talloc_strdup(ctx
, smb_fname_src
->base_name
);
6465 return NT_STATUS_NO_MEMORY
;
6467 p
= strrchr_m(base_name
, '/');
6471 base_name
= talloc_strdup(ctx
, "");
6473 return NT_STATUS_NO_MEMORY
;
6476 /* Append the new name. */
6477 base_name
= talloc_asprintf_append(base_name
,
6481 return NT_STATUS_NO_MEMORY
;
6484 status
= unix_convert(ctx
, conn
, base_name
, &smb_fname_dst
,
6487 UCF_ALWAYS_ALLOW_WCARD_LCOMP
:
6490 /* If an error we expect this to be
6491 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
6493 if (!NT_STATUS_IS_OK(status
)) {
6494 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND
,
6498 /* Create an smb_fname to call rename_internals_fsp() */
6499 status
= create_synthetic_smb_fname(ctx
,
6503 if (!NT_STATUS_IS_OK(status
)) {
6510 DEBUG(10,("smb_file_rename_information: "
6511 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
6512 fsp_fnum_dbg(fsp
), fsp_str_dbg(fsp
),
6513 smb_fname_str_dbg(smb_fname_dst
)));
6514 status
= rename_internals_fsp(conn
, fsp
, smb_fname_dst
, 0,
6517 DEBUG(10,("smb_file_rename_information: "
6518 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
6519 smb_fname_str_dbg(smb_fname_src
),
6520 smb_fname_str_dbg(smb_fname_dst
)));
6521 status
= rename_internals(ctx
, conn
, req
, smb_fname_src
,
6522 smb_fname_dst
, 0, overwrite
, false,
6524 FILE_WRITE_ATTRIBUTES
);
6527 TALLOC_FREE(smb_fname_dst
);
6531 /****************************************************************************
6532 Deal with SMB_SET_POSIX_ACL.
6533 ****************************************************************************/
6535 #if defined(HAVE_POSIX_ACLS)
6536 static NTSTATUS
smb_set_posix_acl(connection_struct
*conn
,
6540 const struct smb_filename
*smb_fname
)
6542 uint16 posix_acl_version
;
6543 uint16 num_file_acls
;
6544 uint16 num_def_acls
;
6545 bool valid_file_acls
= True
;
6546 bool valid_def_acls
= True
;
6548 if (total_data
< SMB_POSIX_ACL_HEADER_SIZE
) {
6549 return NT_STATUS_INVALID_PARAMETER
;
6551 posix_acl_version
= SVAL(pdata
,0);
6552 num_file_acls
= SVAL(pdata
,2);
6553 num_def_acls
= SVAL(pdata
,4);
6555 if (num_file_acls
== SMB_POSIX_IGNORE_ACE_ENTRIES
) {
6556 valid_file_acls
= False
;
6560 if (num_def_acls
== SMB_POSIX_IGNORE_ACE_ENTRIES
) {
6561 valid_def_acls
= False
;
6565 if (posix_acl_version
!= SMB_POSIX_ACL_VERSION
) {
6566 return NT_STATUS_INVALID_PARAMETER
;
6569 if (total_data
< SMB_POSIX_ACL_HEADER_SIZE
+
6570 (num_file_acls
+num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
) {
6571 return NT_STATUS_INVALID_PARAMETER
;
6574 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
6575 smb_fname
? smb_fname_str_dbg(smb_fname
) : fsp_str_dbg(fsp
),
6576 (unsigned int)num_file_acls
,
6577 (unsigned int)num_def_acls
));
6579 if (valid_file_acls
&& !set_unix_posix_acl(conn
, fsp
,
6580 smb_fname
->base_name
, num_file_acls
,
6581 pdata
+ SMB_POSIX_ACL_HEADER_SIZE
)) {
6582 return map_nt_error_from_unix(errno
);
6585 if (valid_def_acls
&& !set_unix_posix_default_acl(conn
,
6586 smb_fname
->base_name
, &smb_fname
->st
, num_def_acls
,
6587 pdata
+ SMB_POSIX_ACL_HEADER_SIZE
+
6588 (num_file_acls
*SMB_POSIX_ACL_ENTRY_SIZE
))) {
6589 return map_nt_error_from_unix(errno
);
6591 return NT_STATUS_OK
;
6595 /****************************************************************************
6596 Deal with SMB_SET_POSIX_LOCK.
6597 ****************************************************************************/
6599 static NTSTATUS
smb_set_posix_lock(connection_struct
*conn
,
6600 struct smb_request
*req
,
6608 bool blocking_lock
= False
;
6609 enum brl_type lock_type
;
6611 NTSTATUS status
= NT_STATUS_OK
;
6613 if (fsp
== NULL
|| fsp
->fh
->fd
== -1) {
6614 return NT_STATUS_INVALID_HANDLE
;
6617 if (total_data
!= POSIX_LOCK_DATA_SIZE
) {
6618 return NT_STATUS_INVALID_PARAMETER
;
6621 switch (SVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
)) {
6622 case POSIX_LOCK_TYPE_READ
:
6623 lock_type
= READ_LOCK
;
6625 case POSIX_LOCK_TYPE_WRITE
:
6626 /* Return the right POSIX-mappable error code for files opened read-only. */
6627 if (!fsp
->can_write
) {
6628 return NT_STATUS_INVALID_HANDLE
;
6630 lock_type
= WRITE_LOCK
;
6632 case POSIX_LOCK_TYPE_UNLOCK
:
6633 lock_type
= UNLOCK_LOCK
;
6636 return NT_STATUS_INVALID_PARAMETER
;
6639 if (SVAL(pdata
,POSIX_LOCK_FLAGS_OFFSET
) == POSIX_LOCK_FLAG_NOWAIT
) {
6640 blocking_lock
= False
;
6641 } else if (SVAL(pdata
,POSIX_LOCK_FLAGS_OFFSET
) == POSIX_LOCK_FLAG_WAIT
) {
6642 blocking_lock
= True
;
6644 return NT_STATUS_INVALID_PARAMETER
;
6647 if (!lp_blocking_locks(SNUM(conn
))) {
6648 blocking_lock
= False
;
6651 smblctx
= (uint64_t)IVAL(pdata
, POSIX_LOCK_PID_OFFSET
);
6652 #if defined(HAVE_LONGLONG)
6653 offset
= (((uint64_t) IVAL(pdata
,(POSIX_LOCK_START_OFFSET
+4))) << 32) |
6654 ((uint64_t) IVAL(pdata
,POSIX_LOCK_START_OFFSET
));
6655 count
= (((uint64_t) IVAL(pdata
,(POSIX_LOCK_LEN_OFFSET
+4))) << 32) |
6656 ((uint64_t) IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
));
6657 #else /* HAVE_LONGLONG */
6658 offset
= (uint64_t)IVAL(pdata
,POSIX_LOCK_START_OFFSET
);
6659 count
= (uint64_t)IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
);
6660 #endif /* HAVE_LONGLONG */
6662 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
6663 "smblctx = %llu, count = %.0f, offset = %.0f\n",
6665 (unsigned int)lock_type
,
6666 (unsigned long long)smblctx
,
6670 if (lock_type
== UNLOCK_LOCK
) {
6671 status
= do_unlock(req
->sconn
->msg_ctx
,
6678 uint64_t block_smblctx
;
6680 struct byte_range_lock
*br_lck
= do_lock(req
->sconn
->msg_ctx
,
6692 if (br_lck
&& blocking_lock
&& ERROR_WAS_LOCK_DENIED(status
)) {
6694 * A blocking lock was requested. Package up
6695 * this smb into a queued request and push it
6696 * onto the blocking lock queue.
6698 if(push_blocking_lock_request(br_lck
,
6701 -1, /* infinite timeout. */
6709 TALLOC_FREE(br_lck
);
6713 TALLOC_FREE(br_lck
);
6719 /****************************************************************************
6720 Deal with SMB_SET_FILE_BASIC_INFO.
6721 ****************************************************************************/
6723 static NTSTATUS
smb_set_file_basic_info(connection_struct
*conn
,
6727 const struct smb_filename
*smb_fname
)
6729 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
6730 struct smb_file_time ft
;
6732 NTSTATUS status
= NT_STATUS_OK
;
6736 if (total_data
< 36) {
6737 return NT_STATUS_INVALID_PARAMETER
;
6740 status
= check_access(conn
, fsp
, smb_fname
, FILE_WRITE_ATTRIBUTES
);
6741 if (!NT_STATUS_IS_OK(status
)) {
6745 /* Set the attributes */
6746 dosmode
= IVAL(pdata
,32);
6747 status
= smb_set_file_dosmode(conn
, smb_fname
, dosmode
);
6748 if (!NT_STATUS_IS_OK(status
)) {
6753 ft
.create_time
= interpret_long_date(pdata
);
6756 ft
.atime
= interpret_long_date(pdata
+8);
6759 ft
.mtime
= interpret_long_date(pdata
+16);
6762 ft
.ctime
= interpret_long_date(pdata
+24);
6764 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
6765 smb_fname_str_dbg(smb_fname
)));
6767 return smb_set_file_time(conn
, fsp
, smb_fname
, &ft
,
6771 /****************************************************************************
6772 Deal with SMB_INFO_STANDARD.
6773 ****************************************************************************/
6775 static NTSTATUS
smb_set_info_standard(connection_struct
*conn
,
6779 const struct smb_filename
*smb_fname
)
6782 struct smb_file_time ft
;
6786 if (total_data
< 12) {
6787 return NT_STATUS_INVALID_PARAMETER
;
6791 ft
.create_time
= convert_time_t_to_timespec(srv_make_unix_date2(pdata
));
6793 ft
.atime
= convert_time_t_to_timespec(srv_make_unix_date2(pdata
+4));
6795 ft
.mtime
= convert_time_t_to_timespec(srv_make_unix_date2(pdata
+8));
6797 DEBUG(10,("smb_set_info_standard: file %s\n",
6798 smb_fname_str_dbg(smb_fname
)));
6800 status
= check_access(conn
, fsp
, smb_fname
, FILE_WRITE_ATTRIBUTES
);
6801 if (!NT_STATUS_IS_OK(status
)) {
6805 return smb_set_file_time(conn
,
6812 /****************************************************************************
6813 Deal with SMB_SET_FILE_ALLOCATION_INFO.
6814 ****************************************************************************/
6816 static NTSTATUS
smb_set_file_allocation_info(connection_struct
*conn
,
6817 struct smb_request
*req
,
6821 struct smb_filename
*smb_fname
)
6823 uint64_t allocation_size
= 0;
6824 NTSTATUS status
= NT_STATUS_OK
;
6825 files_struct
*new_fsp
= NULL
;
6827 if (!VALID_STAT(smb_fname
->st
)) {
6828 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
6831 if (total_data
< 8) {
6832 return NT_STATUS_INVALID_PARAMETER
;
6835 allocation_size
= (uint64_t)IVAL(pdata
,0);
6836 allocation_size
|= (((uint64_t)IVAL(pdata
,4)) << 32);
6837 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
6838 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname
),
6839 (double)allocation_size
));
6841 if (allocation_size
) {
6842 allocation_size
= smb_roundup(conn
, allocation_size
);
6845 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
6846 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname
),
6847 (double)allocation_size
));
6849 if (fsp
&& fsp
->fh
->fd
!= -1) {
6850 /* Open file handle. */
6851 if (!(fsp
->access_mask
& FILE_WRITE_DATA
)) {
6852 return NT_STATUS_ACCESS_DENIED
;
6855 /* Only change if needed. */
6856 if (allocation_size
!= get_file_size_stat(&smb_fname
->st
)) {
6857 if (vfs_allocate_file_space(fsp
, allocation_size
) == -1) {
6858 return map_nt_error_from_unix(errno
);
6861 /* But always update the time. */
6863 * This is equivalent to a write. Ensure it's seen immediately
6864 * if there are no pending writes.
6866 trigger_write_time_update_immediate(fsp
);
6867 return NT_STATUS_OK
;
6870 /* Pathname or stat or directory file. */
6871 status
= SMB_VFS_CREATE_FILE(
6874 0, /* root_dir_fid */
6875 smb_fname
, /* fname */
6876 FILE_WRITE_DATA
, /* access_mask */
6877 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
6879 FILE_OPEN
, /* create_disposition*/
6880 0, /* create_options */
6881 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
6882 FORCE_OPLOCK_BREAK_TO_NONE
, /* oplock_request */
6883 0, /* allocation_size */
6884 0, /* private_flags */
6887 &new_fsp
, /* result */
6890 if (!NT_STATUS_IS_OK(status
)) {
6891 /* NB. We check for open_was_deferred in the caller. */
6895 /* Only change if needed. */
6896 if (allocation_size
!= get_file_size_stat(&smb_fname
->st
)) {
6897 if (vfs_allocate_file_space(new_fsp
, allocation_size
) == -1) {
6898 status
= map_nt_error_from_unix(errno
);
6899 close_file(req
, new_fsp
, NORMAL_CLOSE
);
6904 /* Changing the allocation size should set the last mod time. */
6906 * This is equivalent to a write. Ensure it's seen immediately
6907 * if there are no pending writes.
6909 trigger_write_time_update_immediate(new_fsp
);
6911 close_file(req
, new_fsp
, NORMAL_CLOSE
);
6912 return NT_STATUS_OK
;
6915 /****************************************************************************
6916 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
6917 ****************************************************************************/
6919 static NTSTATUS
smb_set_file_end_of_file_info(connection_struct
*conn
,
6920 struct smb_request
*req
,
6924 const struct smb_filename
*smb_fname
,
6925 bool fail_after_createfile
)
6929 if (total_data
< 8) {
6930 return NT_STATUS_INVALID_PARAMETER
;
6933 size
= IVAL(pdata
,0);
6934 size
|= (((off_t
)IVAL(pdata
,4)) << 32);
6935 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
6936 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname
),
6939 return smb_set_file_size(conn
, req
,
6944 fail_after_createfile
);
6947 /****************************************************************************
6948 Allow a UNIX info mknod.
6949 ****************************************************************************/
6951 static NTSTATUS
smb_unix_mknod(connection_struct
*conn
,
6954 const struct smb_filename
*smb_fname
)
6956 uint32 file_type
= IVAL(pdata
,56);
6957 #if defined(HAVE_MAKEDEV)
6958 uint32 dev_major
= IVAL(pdata
,60);
6959 uint32 dev_minor
= IVAL(pdata
,68);
6961 SMB_DEV_T dev
= (SMB_DEV_T
)0;
6962 uint32 raw_unixmode
= IVAL(pdata
,84);
6966 if (total_data
< 100) {
6967 return NT_STATUS_INVALID_PARAMETER
;
6970 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
6971 PERM_NEW_FILE
, &unixmode
);
6972 if (!NT_STATUS_IS_OK(status
)) {
6976 #if defined(HAVE_MAKEDEV)
6977 dev
= makedev(dev_major
, dev_minor
);
6980 switch (file_type
) {
6981 #if defined(S_IFIFO)
6982 case UNIX_TYPE_FIFO
:
6983 unixmode
|= S_IFIFO
;
6986 #if defined(S_IFSOCK)
6987 case UNIX_TYPE_SOCKET
:
6988 unixmode
|= S_IFSOCK
;
6991 #if defined(S_IFCHR)
6992 case UNIX_TYPE_CHARDEV
:
6993 unixmode
|= S_IFCHR
;
6996 #if defined(S_IFBLK)
6997 case UNIX_TYPE_BLKDEV
:
6998 unixmode
|= S_IFBLK
;
7002 return NT_STATUS_INVALID_PARAMETER
;
7005 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
7006 "%.0f mode 0%o for file %s\n", (double)dev
,
7007 (unsigned int)unixmode
, smb_fname_str_dbg(smb_fname
)));
7009 /* Ok - do the mknod. */
7010 if (SMB_VFS_MKNOD(conn
, smb_fname
->base_name
, unixmode
, dev
) != 0) {
7011 return map_nt_error_from_unix(errno
);
7014 /* If any of the other "set" calls fail we
7015 * don't want to end up with a half-constructed mknod.
7018 if (lp_inherit_perms(SNUM(conn
))) {
7020 if (!parent_dirname(talloc_tos(), smb_fname
->base_name
,
7022 return NT_STATUS_NO_MEMORY
;
7024 inherit_access_posix_acl(conn
, parent
, smb_fname
->base_name
,
7026 TALLOC_FREE(parent
);
7029 return NT_STATUS_OK
;
7032 /****************************************************************************
7033 Deal with SMB_SET_FILE_UNIX_BASIC.
7034 ****************************************************************************/
7036 static NTSTATUS
smb_set_file_unix_basic(connection_struct
*conn
,
7037 struct smb_request
*req
,
7041 const struct smb_filename
*smb_fname
)
7043 struct smb_file_time ft
;
7044 uint32 raw_unixmode
;
7047 uid_t set_owner
= (uid_t
)SMB_UID_NO_CHANGE
;
7048 gid_t set_grp
= (uid_t
)SMB_GID_NO_CHANGE
;
7049 NTSTATUS status
= NT_STATUS_OK
;
7050 bool delete_on_fail
= False
;
7051 enum perm_type ptype
;
7052 files_struct
*all_fsps
= NULL
;
7053 bool modify_mtime
= true;
7055 struct smb_filename
*smb_fname_tmp
= NULL
;
7056 SMB_STRUCT_STAT sbuf
;
7060 if (total_data
< 100) {
7061 return NT_STATUS_INVALID_PARAMETER
;
7064 if(IVAL(pdata
, 0) != SMB_SIZE_NO_CHANGE_LO
&&
7065 IVAL(pdata
, 4) != SMB_SIZE_NO_CHANGE_HI
) {
7066 size
=IVAL(pdata
,0); /* first 8 Bytes are size */
7067 size
|= (((off_t
)IVAL(pdata
,4)) << 32);
7070 ft
.atime
= interpret_long_date(pdata
+24); /* access_time */
7071 ft
.mtime
= interpret_long_date(pdata
+32); /* modification_time */
7072 set_owner
= (uid_t
)IVAL(pdata
,40);
7073 set_grp
= (gid_t
)IVAL(pdata
,48);
7074 raw_unixmode
= IVAL(pdata
,84);
7076 if (VALID_STAT(smb_fname
->st
)) {
7077 if (S_ISDIR(smb_fname
->st
.st_ex_mode
)) {
7078 ptype
= PERM_EXISTING_DIR
;
7080 ptype
= PERM_EXISTING_FILE
;
7083 ptype
= PERM_NEW_FILE
;
7086 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
7088 if (!NT_STATUS_IS_OK(status
)) {
7092 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
7093 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
7094 smb_fname_str_dbg(smb_fname
), (double)size
,
7095 (unsigned int)set_owner
, (unsigned int)set_grp
,
7096 (int)raw_unixmode
));
7098 sbuf
= smb_fname
->st
;
7100 if (!VALID_STAT(sbuf
)) {
7102 * The only valid use of this is to create character and block
7103 * devices, and named pipes. This is deprecated (IMHO) and
7104 * a new info level should be used for mknod. JRA.
7107 status
= smb_unix_mknod(conn
,
7111 if (!NT_STATUS_IS_OK(status
)) {
7115 status
= copy_smb_filename(talloc_tos(), smb_fname
,
7117 if (!NT_STATUS_IS_OK(status
)) {
7121 if (SMB_VFS_STAT(conn
, smb_fname_tmp
) != 0) {
7122 status
= map_nt_error_from_unix(errno
);
7123 TALLOC_FREE(smb_fname_tmp
);
7124 SMB_VFS_UNLINK(conn
, smb_fname
);
7128 sbuf
= smb_fname_tmp
->st
;
7129 smb_fname
= smb_fname_tmp
;
7131 /* Ensure we don't try and change anything else. */
7132 raw_unixmode
= SMB_MODE_NO_CHANGE
;
7133 size
= get_file_size_stat(&sbuf
);
7134 ft
.atime
= sbuf
.st_ex_atime
;
7135 ft
.mtime
= sbuf
.st_ex_mtime
;
7137 * We continue here as we might want to change the
7140 delete_on_fail
= True
;
7144 /* Horrible backwards compatibility hack as an old server bug
7145 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
7149 size
= get_file_size_stat(&sbuf
);
7154 * Deal with the UNIX specific mode set.
7157 if (raw_unixmode
!= SMB_MODE_NO_CHANGE
) {
7160 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7161 "setting mode 0%o for file %s\n",
7162 (unsigned int)unixmode
,
7163 smb_fname_str_dbg(smb_fname
)));
7164 if (fsp
&& fsp
->fh
->fd
!= -1) {
7165 ret
= SMB_VFS_FCHMOD(fsp
, unixmode
);
7167 ret
= SMB_VFS_CHMOD(conn
, smb_fname
->base_name
, unixmode
);
7170 return map_nt_error_from_unix(errno
);
7175 * Deal with the UNIX specific uid set.
7178 if ((set_owner
!= (uid_t
)SMB_UID_NO_CHANGE
) &&
7179 (sbuf
.st_ex_uid
!= set_owner
)) {
7182 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7183 "changing owner %u for path %s\n",
7184 (unsigned int)set_owner
,
7185 smb_fname_str_dbg(smb_fname
)));
7187 if (fsp
&& fsp
->fh
->fd
!= -1) {
7188 ret
= SMB_VFS_FCHOWN(fsp
, set_owner
, (gid_t
)-1);
7191 * UNIX extensions calls must always operate
7194 ret
= SMB_VFS_LCHOWN(conn
, smb_fname
->base_name
,
7195 set_owner
, (gid_t
)-1);
7199 status
= map_nt_error_from_unix(errno
);
7200 if (delete_on_fail
) {
7201 SMB_VFS_UNLINK(conn
, smb_fname
);
7208 * Deal with the UNIX specific gid set.
7211 if ((set_grp
!= (uid_t
)SMB_GID_NO_CHANGE
) &&
7212 (sbuf
.st_ex_gid
!= set_grp
)) {
7215 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7216 "changing group %u for file %s\n",
7217 (unsigned int)set_owner
,
7218 smb_fname_str_dbg(smb_fname
)));
7219 if (fsp
&& fsp
->fh
->fd
!= -1) {
7220 ret
= SMB_VFS_FCHOWN(fsp
, set_owner
, (gid_t
)-1);
7223 * UNIX extensions calls must always operate
7226 ret
= SMB_VFS_LCHOWN(conn
, smb_fname
->base_name
, (uid_t
)-1,
7230 status
= map_nt_error_from_unix(errno
);
7231 if (delete_on_fail
) {
7232 SMB_VFS_UNLINK(conn
, smb_fname
);
7238 /* Deal with any size changes. */
7240 status
= smb_set_file_size(conn
, req
,
7246 if (!NT_STATUS_IS_OK(status
)) {
7250 /* Deal with any time changes. */
7251 if (null_timespec(ft
.mtime
) && null_timespec(ft
.atime
)) {
7252 /* No change, don't cancel anything. */
7256 id
= vfs_file_id_from_sbuf(conn
, &sbuf
);
7257 for(all_fsps
= file_find_di_first(conn
->sconn
, id
); all_fsps
;
7258 all_fsps
= file_find_di_next(all_fsps
)) {
7260 * We're setting the time explicitly for UNIX.
7261 * Cancel any pending changes over all handles.
7263 all_fsps
->update_write_time_on_close
= false;
7264 TALLOC_FREE(all_fsps
->update_write_time_event
);
7268 * Override the "setting_write_time"
7269 * parameter here as it almost does what
7270 * we need. Just remember if we modified
7271 * mtime and send the notify ourselves.
7273 if (null_timespec(ft
.mtime
)) {
7274 modify_mtime
= false;
7277 status
= smb_set_file_time(conn
,
7283 notify_fname(conn
, NOTIFY_ACTION_MODIFIED
,
7284 FILE_NOTIFY_CHANGE_LAST_WRITE
, smb_fname
->base_name
);
7289 /****************************************************************************
7290 Deal with SMB_SET_FILE_UNIX_INFO2.
7291 ****************************************************************************/
7293 static NTSTATUS
smb_set_file_unix_info2(connection_struct
*conn
,
7294 struct smb_request
*req
,
7298 const struct smb_filename
*smb_fname
)
7304 if (total_data
< 116) {
7305 return NT_STATUS_INVALID_PARAMETER
;
7308 /* Start by setting all the fields that are common between UNIX_BASIC
7311 status
= smb_set_file_unix_basic(conn
, req
, pdata
, total_data
,
7313 if (!NT_STATUS_IS_OK(status
)) {
7317 smb_fflags
= IVAL(pdata
, 108);
7318 smb_fmask
= IVAL(pdata
, 112);
7320 /* NB: We should only attempt to alter the file flags if the client
7321 * sends a non-zero mask.
7323 if (smb_fmask
!= 0) {
7324 int stat_fflags
= 0;
7326 if (!map_info2_flags_to_sbuf(&smb_fname
->st
, smb_fflags
,
7327 smb_fmask
, &stat_fflags
)) {
7328 /* Client asked to alter a flag we don't understand. */
7329 return NT_STATUS_INVALID_PARAMETER
;
7332 if (fsp
&& fsp
->fh
->fd
!= -1) {
7333 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
7334 return NT_STATUS_NOT_SUPPORTED
;
7336 if (SMB_VFS_CHFLAGS(conn
, smb_fname
->base_name
,
7337 stat_fflags
) != 0) {
7338 return map_nt_error_from_unix(errno
);
7343 /* XXX: need to add support for changing the create_time here. You
7344 * can do this for paths on Darwin with setattrlist(2). The right way
7345 * to hook this up is probably by extending the VFS utimes interface.
7348 return NT_STATUS_OK
;
7351 /****************************************************************************
7352 Create a directory with POSIX semantics.
7353 ****************************************************************************/
7355 static NTSTATUS
smb_posix_mkdir(connection_struct
*conn
,
7356 struct smb_request
*req
,
7359 struct smb_filename
*smb_fname
,
7360 int *pdata_return_size
)
7362 NTSTATUS status
= NT_STATUS_OK
;
7363 uint32 raw_unixmode
= 0;
7364 uint32 mod_unixmode
= 0;
7365 mode_t unixmode
= (mode_t
)0;
7366 files_struct
*fsp
= NULL
;
7367 uint16 info_level_return
= 0;
7369 char *pdata
= *ppdata
;
7371 if (total_data
< 18) {
7372 return NT_STATUS_INVALID_PARAMETER
;
7375 raw_unixmode
= IVAL(pdata
,8);
7376 /* Next 4 bytes are not yet defined. */
7378 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
7379 PERM_NEW_DIR
, &unixmode
);
7380 if (!NT_STATUS_IS_OK(status
)) {
7384 mod_unixmode
= (uint32
)unixmode
| FILE_FLAG_POSIX_SEMANTICS
;
7386 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
7387 smb_fname_str_dbg(smb_fname
), (unsigned int)unixmode
));
7389 status
= SMB_VFS_CREATE_FILE(
7392 0, /* root_dir_fid */
7393 smb_fname
, /* fname */
7394 FILE_READ_ATTRIBUTES
, /* access_mask */
7395 FILE_SHARE_NONE
, /* share_access */
7396 FILE_CREATE
, /* create_disposition*/
7397 FILE_DIRECTORY_FILE
, /* create_options */
7398 mod_unixmode
, /* file_attributes */
7399 0, /* oplock_request */
7400 0, /* allocation_size */
7401 0, /* private_flags */
7407 if (NT_STATUS_IS_OK(status
)) {
7408 close_file(req
, fsp
, NORMAL_CLOSE
);
7411 info_level_return
= SVAL(pdata
,16);
7413 if (info_level_return
== SMB_QUERY_FILE_UNIX_BASIC
) {
7414 *pdata_return_size
= 12 + SMB_FILE_UNIX_BASIC_SIZE
;
7415 } else if (info_level_return
== SMB_QUERY_FILE_UNIX_INFO2
) {
7416 *pdata_return_size
= 12 + SMB_FILE_UNIX_INFO2_SIZE
;
7418 *pdata_return_size
= 12;
7421 /* Realloc the data size */
7422 *ppdata
= (char *)SMB_REALLOC(*ppdata
,*pdata_return_size
);
7423 if (*ppdata
== NULL
) {
7424 *pdata_return_size
= 0;
7425 return NT_STATUS_NO_MEMORY
;
7429 SSVAL(pdata
,0,NO_OPLOCK_RETURN
);
7430 SSVAL(pdata
,2,0); /* No fnum. */
7431 SIVAL(pdata
,4,info
); /* Was directory created. */
7433 switch (info_level_return
) {
7434 case SMB_QUERY_FILE_UNIX_BASIC
:
7435 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_BASIC
);
7436 SSVAL(pdata
,10,0); /* Padding. */
7437 store_file_unix_basic(conn
, pdata
+ 12, fsp
,
7440 case SMB_QUERY_FILE_UNIX_INFO2
:
7441 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_INFO2
);
7442 SSVAL(pdata
,10,0); /* Padding. */
7443 store_file_unix_basic_info2(conn
, pdata
+ 12, fsp
,
7447 SSVAL(pdata
,8,SMB_NO_INFO_LEVEL_RETURNED
);
7448 SSVAL(pdata
,10,0); /* Padding. */
7455 /****************************************************************************
7456 Open/Create a file with POSIX semantics.
7457 ****************************************************************************/
7459 #define SMB_O_RDONLY_MAPPING (FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA)
7460 #define SMB_O_WRONLY_MAPPING (FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA)
7462 static NTSTATUS
smb_posix_open(connection_struct
*conn
,
7463 struct smb_request
*req
,
7466 struct smb_filename
*smb_fname
,
7467 int *pdata_return_size
)
7469 bool extended_oplock_granted
= False
;
7470 char *pdata
= *ppdata
;
7472 uint32 wire_open_mode
= 0;
7473 uint32 raw_unixmode
= 0;
7474 uint32 mod_unixmode
= 0;
7475 uint32 create_disp
= 0;
7476 uint32 access_mask
= 0;
7477 uint32 create_options
= FILE_NON_DIRECTORY_FILE
;
7478 NTSTATUS status
= NT_STATUS_OK
;
7479 mode_t unixmode
= (mode_t
)0;
7480 files_struct
*fsp
= NULL
;
7481 int oplock_request
= 0;
7483 uint16 info_level_return
= 0;
7485 if (total_data
< 18) {
7486 return NT_STATUS_INVALID_PARAMETER
;
7489 flags
= IVAL(pdata
,0);
7490 oplock_request
= (flags
& REQUEST_OPLOCK
) ? EXCLUSIVE_OPLOCK
: 0;
7491 if (oplock_request
) {
7492 oplock_request
|= (flags
& REQUEST_BATCH_OPLOCK
) ? BATCH_OPLOCK
: 0;
7495 wire_open_mode
= IVAL(pdata
,4);
7497 if (wire_open_mode
== (SMB_O_CREAT
|SMB_O_DIRECTORY
)) {
7498 return smb_posix_mkdir(conn
, req
,
7505 switch (wire_open_mode
& SMB_ACCMODE
) {
7507 access_mask
= SMB_O_RDONLY_MAPPING
;
7510 access_mask
= SMB_O_WRONLY_MAPPING
;
7513 access_mask
= (SMB_O_RDONLY_MAPPING
|
7514 SMB_O_WRONLY_MAPPING
);
7517 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
7518 (unsigned int)wire_open_mode
));
7519 return NT_STATUS_INVALID_PARAMETER
;
7522 wire_open_mode
&= ~SMB_ACCMODE
;
7524 /* First take care of O_CREAT|O_EXCL interactions. */
7525 switch (wire_open_mode
& (SMB_O_CREAT
| SMB_O_EXCL
)) {
7526 case (SMB_O_CREAT
| SMB_O_EXCL
):
7527 /* File exists fail. File not exist create. */
7528 create_disp
= FILE_CREATE
;
7531 /* File exists open. File not exist create. */
7532 create_disp
= FILE_OPEN_IF
;
7535 /* O_EXCL on its own without O_CREAT is undefined.
7536 We deliberately ignore it as some versions of
7537 Linux CIFSFS can send a bare O_EXCL on the
7538 wire which other filesystems in the kernel
7539 ignore. See bug 9519 for details. */
7544 /* File exists open. File not exist fail. */
7545 create_disp
= FILE_OPEN
;
7548 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
7549 (unsigned int)wire_open_mode
));
7550 return NT_STATUS_INVALID_PARAMETER
;
7553 /* Next factor in the effects of O_TRUNC. */
7554 wire_open_mode
&= ~(SMB_O_CREAT
| SMB_O_EXCL
);
7556 if (wire_open_mode
& SMB_O_TRUNC
) {
7557 switch (create_disp
) {
7559 /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
7560 /* Leave create_disp alone as
7561 (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
7563 /* File exists fail. File not exist create. */
7566 /* SMB_O_CREAT | SMB_O_TRUNC */
7567 /* File exists overwrite. File not exist create. */
7568 create_disp
= FILE_OVERWRITE_IF
;
7572 /* File exists overwrite. File not exist fail. */
7573 create_disp
= FILE_OVERWRITE
;
7576 /* Cannot get here. */
7577 smb_panic("smb_posix_open: logic error");
7578 return NT_STATUS_INVALID_PARAMETER
;
7582 raw_unixmode
= IVAL(pdata
,8);
7583 /* Next 4 bytes are not yet defined. */
7585 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
7586 (VALID_STAT(smb_fname
->st
) ?
7587 PERM_EXISTING_FILE
: PERM_NEW_FILE
),
7590 if (!NT_STATUS_IS_OK(status
)) {
7594 mod_unixmode
= (uint32
)unixmode
| FILE_FLAG_POSIX_SEMANTICS
;
7596 if (wire_open_mode
& SMB_O_SYNC
) {
7597 create_options
|= FILE_WRITE_THROUGH
;
7599 if (wire_open_mode
& SMB_O_APPEND
) {
7600 access_mask
|= FILE_APPEND_DATA
;
7602 if (wire_open_mode
& SMB_O_DIRECT
) {
7603 mod_unixmode
|= FILE_FLAG_NO_BUFFERING
;
7606 if ((wire_open_mode
& SMB_O_DIRECTORY
) ||
7607 VALID_STAT_OF_DIR(smb_fname
->st
)) {
7608 if (access_mask
!= SMB_O_RDONLY_MAPPING
) {
7609 return NT_STATUS_FILE_IS_A_DIRECTORY
;
7611 create_options
&= ~FILE_NON_DIRECTORY_FILE
;
7612 create_options
|= FILE_DIRECTORY_FILE
;
7615 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
7616 smb_fname_str_dbg(smb_fname
),
7617 (unsigned int)wire_open_mode
,
7618 (unsigned int)unixmode
));
7620 status
= SMB_VFS_CREATE_FILE(
7623 0, /* root_dir_fid */
7624 smb_fname
, /* fname */
7625 access_mask
, /* access_mask */
7626 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
7628 create_disp
, /* create_disposition*/
7629 create_options
, /* create_options */
7630 mod_unixmode
, /* file_attributes */
7631 oplock_request
, /* oplock_request */
7632 0, /* allocation_size */
7633 0, /* private_flags */
7639 if (!NT_STATUS_IS_OK(status
)) {
7643 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
7644 extended_oplock_granted
= True
;
7647 if(oplock_request
&& EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
7648 extended_oplock_granted
= True
;
7651 info_level_return
= SVAL(pdata
,16);
7653 /* Allocate the correct return size. */
7655 if (info_level_return
== SMB_QUERY_FILE_UNIX_BASIC
) {
7656 *pdata_return_size
= 12 + SMB_FILE_UNIX_BASIC_SIZE
;
7657 } else if (info_level_return
== SMB_QUERY_FILE_UNIX_INFO2
) {
7658 *pdata_return_size
= 12 + SMB_FILE_UNIX_INFO2_SIZE
;
7660 *pdata_return_size
= 12;
7663 /* Realloc the data size */
7664 *ppdata
= (char *)SMB_REALLOC(*ppdata
,*pdata_return_size
);
7665 if (*ppdata
== NULL
) {
7666 close_file(req
, fsp
, ERROR_CLOSE
);
7667 *pdata_return_size
= 0;
7668 return NT_STATUS_NO_MEMORY
;
7672 if (extended_oplock_granted
) {
7673 if (flags
& REQUEST_BATCH_OPLOCK
) {
7674 SSVAL(pdata
,0, BATCH_OPLOCK_RETURN
);
7676 SSVAL(pdata
,0, EXCLUSIVE_OPLOCK_RETURN
);
7678 } else if (fsp
->oplock_type
== LEVEL_II_OPLOCK
) {
7679 SSVAL(pdata
,0, LEVEL_II_OPLOCK_RETURN
);
7681 SSVAL(pdata
,0,NO_OPLOCK_RETURN
);
7684 SSVAL(pdata
,2,fsp
->fnum
);
7685 SIVAL(pdata
,4,info
); /* Was file created etc. */
7687 switch (info_level_return
) {
7688 case SMB_QUERY_FILE_UNIX_BASIC
:
7689 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_BASIC
);
7690 SSVAL(pdata
,10,0); /* padding. */
7691 store_file_unix_basic(conn
, pdata
+ 12, fsp
,
7694 case SMB_QUERY_FILE_UNIX_INFO2
:
7695 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_INFO2
);
7696 SSVAL(pdata
,10,0); /* padding. */
7697 store_file_unix_basic_info2(conn
, pdata
+ 12, fsp
,
7701 SSVAL(pdata
,8,SMB_NO_INFO_LEVEL_RETURNED
);
7702 SSVAL(pdata
,10,0); /* padding. */
7705 return NT_STATUS_OK
;
7708 /****************************************************************************
7709 Delete a file with POSIX semantics.
7710 ****************************************************************************/
7712 static NTSTATUS
smb_posix_unlink(connection_struct
*conn
,
7713 struct smb_request
*req
,
7716 struct smb_filename
*smb_fname
)
7718 NTSTATUS status
= NT_STATUS_OK
;
7719 files_struct
*fsp
= NULL
;
7723 int create_options
= 0;
7725 struct share_mode_lock
*lck
= NULL
;
7727 if (total_data
< 2) {
7728 return NT_STATUS_INVALID_PARAMETER
;
7731 flags
= SVAL(pdata
,0);
7733 if (!VALID_STAT(smb_fname
->st
)) {
7734 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
7737 if ((flags
== SMB_POSIX_UNLINK_DIRECTORY_TARGET
) &&
7738 !VALID_STAT_OF_DIR(smb_fname
->st
)) {
7739 return NT_STATUS_NOT_A_DIRECTORY
;
7742 DEBUG(10,("smb_posix_unlink: %s %s\n",
7743 (flags
== SMB_POSIX_UNLINK_DIRECTORY_TARGET
) ? "directory" : "file",
7744 smb_fname_str_dbg(smb_fname
)));
7746 if (VALID_STAT_OF_DIR(smb_fname
->st
)) {
7747 create_options
|= FILE_DIRECTORY_FILE
;
7750 status
= SMB_VFS_CREATE_FILE(
7753 0, /* root_dir_fid */
7754 smb_fname
, /* fname */
7755 DELETE_ACCESS
, /* access_mask */
7756 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
7758 FILE_OPEN
, /* create_disposition*/
7759 create_options
, /* create_options */
7760 FILE_FLAG_POSIX_SEMANTICS
|0777, /* file_attributes */
7761 0, /* oplock_request */
7762 0, /* allocation_size */
7763 0, /* private_flags */
7769 if (!NT_STATUS_IS_OK(status
)) {
7774 * Don't lie to client. If we can't really delete due to
7775 * non-POSIX opens return SHARING_VIOLATION.
7778 lck
= get_existing_share_mode_lock(talloc_tos(), fsp
->file_id
);
7780 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
7781 "lock for file %s\n", fsp_str_dbg(fsp
)));
7782 close_file(req
, fsp
, NORMAL_CLOSE
);
7783 return NT_STATUS_INVALID_PARAMETER
;
7787 * See if others still have the file open. If this is the case, then
7788 * don't delete. If all opens are POSIX delete we can set the delete
7789 * on close disposition.
7791 for (i
=0; i
<lck
->data
->num_share_modes
; i
++) {
7792 struct share_mode_entry
*e
= &lck
->data
->share_modes
[i
];
7793 if (is_valid_share_mode_entry(e
)) {
7794 if (e
->flags
& SHARE_MODE_FLAG_POSIX_OPEN
) {
7797 if (share_mode_stale_pid(lck
->data
, i
)) {
7800 /* Fail with sharing violation. */
7802 close_file(req
, fsp
, NORMAL_CLOSE
);
7803 return NT_STATUS_SHARING_VIOLATION
;
7808 * Set the delete on close.
7810 status
= smb_set_file_disposition_info(conn
,
7818 if (!NT_STATUS_IS_OK(status
)) {
7819 close_file(req
, fsp
, NORMAL_CLOSE
);
7822 return close_file(req
, fsp
, NORMAL_CLOSE
);
7825 NTSTATUS
smbd_do_setfilepathinfo(connection_struct
*conn
,
7826 struct smb_request
*req
,
7827 TALLOC_CTX
*mem_ctx
,
7828 uint16_t info_level
,
7830 struct smb_filename
*smb_fname
,
7831 char **ppdata
, int total_data
,
7834 char *pdata
= *ppdata
;
7835 NTSTATUS status
= NT_STATUS_OK
;
7836 int data_return_size
= 0;
7840 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
7841 return NT_STATUS_INVALID_LEVEL
;
7844 if (!CAN_WRITE(conn
)) {
7845 /* Allow POSIX opens. The open path will deny
7846 * any non-readonly opens. */
7847 if (info_level
!= SMB_POSIX_PATH_OPEN
) {
7848 return NT_STATUS_DOS(ERRSRV
, ERRaccess
);
7852 DEBUG(3,("smbd_do_setfilepathinfo: %s (%s) info_level=%d "
7853 "totdata=%d\n", smb_fname_str_dbg(smb_fname
),
7855 info_level
, total_data
));
7857 switch (info_level
) {
7859 case SMB_INFO_STANDARD
:
7861 status
= smb_set_info_standard(conn
,
7869 case SMB_INFO_SET_EA
:
7871 status
= smb_info_set_ea(conn
,
7879 case SMB_SET_FILE_BASIC_INFO
:
7880 case SMB_FILE_BASIC_INFORMATION
:
7882 status
= smb_set_file_basic_info(conn
,
7890 case SMB_FILE_ALLOCATION_INFORMATION
:
7891 case SMB_SET_FILE_ALLOCATION_INFO
:
7893 status
= smb_set_file_allocation_info(conn
, req
,
7901 case SMB_FILE_END_OF_FILE_INFORMATION
:
7902 case SMB_SET_FILE_END_OF_FILE_INFO
:
7905 * XP/Win7 both fail after the createfile with
7906 * SMB_SET_FILE_END_OF_FILE_INFO but not
7907 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
7908 * The level is known here, so pass it down
7912 (info_level
== SMB_SET_FILE_END_OF_FILE_INFO
);
7914 status
= smb_set_file_end_of_file_info(conn
, req
,
7923 case SMB_FILE_DISPOSITION_INFORMATION
:
7924 case SMB_SET_FILE_DISPOSITION_INFO
: /* Set delete on close for open file. */
7927 /* JRA - We used to just ignore this on a path ?
7928 * Shouldn't this be invalid level on a pathname
7931 if (tran_call
!= TRANSACT2_SETFILEINFO
) {
7932 return ERROR_NT(NT_STATUS_INVALID_LEVEL
);
7935 status
= smb_set_file_disposition_info(conn
,
7943 case SMB_FILE_POSITION_INFORMATION
:
7945 status
= smb_file_position_information(conn
,
7952 case SMB_FILE_FULL_EA_INFORMATION
:
7954 status
= smb_set_file_full_ea_info(conn
,
7961 /* From tridge Samba4 :
7962 * MODE_INFORMATION in setfileinfo (I have no
7963 * idea what "mode information" on a file is - it takes a value of 0,
7964 * 2, 4 or 6. What could it be?).
7967 case SMB_FILE_MODE_INFORMATION
:
7969 status
= smb_file_mode_information(conn
,
7976 * CIFS UNIX extensions.
7979 case SMB_SET_FILE_UNIX_BASIC
:
7981 status
= smb_set_file_unix_basic(conn
, req
,
7989 case SMB_SET_FILE_UNIX_INFO2
:
7991 status
= smb_set_file_unix_info2(conn
, req
,
7999 case SMB_SET_FILE_UNIX_LINK
:
8002 /* We must have a pathname for this. */
8003 return NT_STATUS_INVALID_LEVEL
;
8005 status
= smb_set_file_unix_link(conn
, req
, pdata
,
8006 total_data
, smb_fname
);
8010 case SMB_SET_FILE_UNIX_HLINK
:
8013 /* We must have a pathname for this. */
8014 return NT_STATUS_INVALID_LEVEL
;
8016 status
= smb_set_file_unix_hlink(conn
, req
,
8022 case SMB_FILE_RENAME_INFORMATION
:
8024 status
= smb_file_rename_information(conn
, req
,
8030 case SMB2_FILE_RENAME_INFORMATION_INTERNAL
:
8032 /* SMB2 rename information. */
8033 status
= smb2_file_rename_information(conn
, req
,
8039 case SMB_FILE_LINK_INFORMATION
:
8041 status
= smb_file_link_information(conn
, req
,
8047 #if defined(HAVE_POSIX_ACLS)
8048 case SMB_SET_POSIX_ACL
:
8050 status
= smb_set_posix_acl(conn
,
8059 case SMB_SET_POSIX_LOCK
:
8062 return NT_STATUS_INVALID_LEVEL
;
8064 status
= smb_set_posix_lock(conn
, req
,
8065 pdata
, total_data
, fsp
);
8069 case SMB_POSIX_PATH_OPEN
:
8072 /* We must have a pathname for this. */
8073 return NT_STATUS_INVALID_LEVEL
;
8076 status
= smb_posix_open(conn
, req
,
8084 case SMB_POSIX_PATH_UNLINK
:
8087 /* We must have a pathname for this. */
8088 return NT_STATUS_INVALID_LEVEL
;
8091 status
= smb_posix_unlink(conn
, req
,
8099 return NT_STATUS_INVALID_LEVEL
;
8102 if (!NT_STATUS_IS_OK(status
)) {
8106 *ret_data_size
= data_return_size
;
8107 return NT_STATUS_OK
;
8110 /****************************************************************************
8111 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
8112 ****************************************************************************/
8114 static void call_trans2setfilepathinfo(connection_struct
*conn
,
8115 struct smb_request
*req
,
8116 unsigned int tran_call
,
8117 char **pparams
, int total_params
,
8118 char **ppdata
, int total_data
,
8119 unsigned int max_data_bytes
)
8121 char *params
= *pparams
;
8122 char *pdata
= *ppdata
;
8124 struct smb_filename
*smb_fname
= NULL
;
8125 files_struct
*fsp
= NULL
;
8126 NTSTATUS status
= NT_STATUS_OK
;
8127 int data_return_size
= 0;
8130 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8134 if (tran_call
== TRANSACT2_SETFILEINFO
) {
8135 if (total_params
< 4) {
8136 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8140 fsp
= file_fsp(req
, SVAL(params
,0));
8141 /* Basic check for non-null fsp. */
8142 if (!check_fsp_open(conn
, req
, fsp
)) {
8145 info_level
= SVAL(params
,2);
8147 status
= copy_smb_filename(talloc_tos(), fsp
->fsp_name
,
8149 if (!NT_STATUS_IS_OK(status
)) {
8150 reply_nterror(req
, status
);
8154 if(fsp
->fh
->fd
== -1) {
8156 * This is actually a SETFILEINFO on a directory
8157 * handle (returned from an NT SMB). NT5.0 seems
8158 * to do this call. JRA.
8160 if (INFO_LEVEL_IS_UNIX(info_level
)) {
8161 /* Always do lstat for UNIX calls. */
8162 if (SMB_VFS_LSTAT(conn
, smb_fname
)) {
8163 DEBUG(3,("call_trans2setfilepathinfo: "
8164 "SMB_VFS_LSTAT of %s failed "
8166 smb_fname_str_dbg(smb_fname
),
8168 reply_nterror(req
, map_nt_error_from_unix(errno
));
8172 if (SMB_VFS_STAT(conn
, smb_fname
) != 0) {
8173 DEBUG(3,("call_trans2setfilepathinfo: "
8174 "fileinfo of %s failed (%s)\n",
8175 smb_fname_str_dbg(smb_fname
),
8177 reply_nterror(req
, map_nt_error_from_unix(errno
));
8181 } else if (fsp
->print_file
) {
8183 * Doing a DELETE_ON_CLOSE should cancel a print job.
8185 if ((info_level
== SMB_SET_FILE_DISPOSITION_INFO
) && CVAL(pdata
,0)) {
8186 fsp
->fh
->private_options
|= NTCREATEX_OPTIONS_PRIVATE_DELETE_ON_CLOSE
;
8188 DEBUG(3,("call_trans2setfilepathinfo: "
8189 "Cancelling print job (%s)\n",
8193 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 2,
8199 NT_STATUS_OBJECT_PATH_NOT_FOUND
);
8204 * Original code - this is an open file.
8206 if (SMB_VFS_FSTAT(fsp
, &smb_fname
->st
) != 0) {
8207 DEBUG(3,("call_trans2setfilepathinfo: fstat "
8208 "of %s failed (%s)\n", fsp_fnum_dbg(fsp
),
8210 reply_nterror(req
, map_nt_error_from_unix(errno
));
8216 uint32_t ucf_flags
= 0;
8219 if (total_params
< 7) {
8220 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8224 info_level
= SVAL(params
,0);
8225 srvstr_get_path(req
, params
, req
->flags2
, &fname
, ¶ms
[6],
8226 total_params
- 6, STR_TERMINATE
,
8228 if (!NT_STATUS_IS_OK(status
)) {
8229 reply_nterror(req
, status
);
8233 if (info_level
== SMB_SET_FILE_UNIX_BASIC
||
8234 info_level
== SMB_SET_FILE_UNIX_INFO2
||
8235 info_level
== SMB_FILE_RENAME_INFORMATION
||
8236 info_level
== SMB_POSIX_PATH_UNLINK
) {
8237 ucf_flags
|= UCF_UNIX_NAME_LOOKUP
;
8240 status
= filename_convert(req
, conn
,
8241 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
8246 if (!NT_STATUS_IS_OK(status
)) {
8247 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
8248 reply_botherror(req
,
8249 NT_STATUS_PATH_NOT_COVERED
,
8250 ERRSRV
, ERRbadpath
);
8253 reply_nterror(req
, status
);
8257 if (INFO_LEVEL_IS_UNIX(info_level
)) {
8259 * For CIFS UNIX extensions the target name may not exist.
8262 /* Always do lstat for UNIX calls. */
8263 SMB_VFS_LSTAT(conn
, smb_fname
);
8265 } else if (!VALID_STAT(smb_fname
->st
) &&
8266 SMB_VFS_STAT(conn
, smb_fname
)) {
8267 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
8269 smb_fname_str_dbg(smb_fname
),
8271 reply_nterror(req
, map_nt_error_from_unix(errno
));
8276 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (%s) info_level=%d "
8277 "totdata=%d\n", tran_call
, smb_fname_str_dbg(smb_fname
),
8279 info_level
,total_data
));
8281 /* Realloc the parameter size */
8282 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
8283 if (*pparams
== NULL
) {
8284 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8291 status
= smbd_do_setfilepathinfo(conn
, req
, req
,
8297 if (!NT_STATUS_IS_OK(status
)) {
8298 if (open_was_deferred(req
->sconn
, req
->mid
)) {
8299 /* We have re-scheduled this call. */
8302 if (blocking_lock_was_deferred_smb1(req
->sconn
, req
->mid
)) {
8303 /* We have re-scheduled this call. */
8306 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
8307 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
8308 ERRSRV
, ERRbadpath
);
8311 if (info_level
== SMB_POSIX_PATH_OPEN
) {
8312 reply_openerror(req
, status
);
8317 * Invalid EA name needs to return 2 param bytes,
8318 * not a zero-length error packet.
8320 if (NT_STATUS_EQUAL(status
, STATUS_INVALID_EA_NAME
)) {
8321 send_trans2_replies(conn
, req
, status
, params
, 2, NULL
, 0,
8324 reply_nterror(req
, status
);
8329 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 2, *ppdata
, data_return_size
,
8335 /****************************************************************************
8336 Reply to a TRANS2_MKDIR (make directory with extended attributes).
8337 ****************************************************************************/
8339 static void call_trans2mkdir(connection_struct
*conn
, struct smb_request
*req
,
8340 char **pparams
, int total_params
,
8341 char **ppdata
, int total_data
,
8342 unsigned int max_data_bytes
)
8344 struct smb_filename
*smb_dname
= NULL
;
8345 char *params
= *pparams
;
8346 char *pdata
= *ppdata
;
8347 char *directory
= NULL
;
8348 NTSTATUS status
= NT_STATUS_OK
;
8349 struct ea_list
*ea_list
= NULL
;
8350 TALLOC_CTX
*ctx
= talloc_tos();
8352 if (!CAN_WRITE(conn
)) {
8353 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
8357 if (total_params
< 5) {
8358 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8362 srvstr_get_path(ctx
, params
, req
->flags2
, &directory
, ¶ms
[4],
8363 total_params
- 4, STR_TERMINATE
,
8365 if (!NT_STATUS_IS_OK(status
)) {
8366 reply_nterror(req
, status
);
8370 DEBUG(3,("call_trans2mkdir : name = %s\n", directory
));
8372 status
= filename_convert(ctx
,
8374 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
8380 if (!NT_STATUS_IS_OK(status
)) {
8381 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
8382 reply_botherror(req
,
8383 NT_STATUS_PATH_NOT_COVERED
,
8384 ERRSRV
, ERRbadpath
);
8387 reply_nterror(req
, status
);
8392 * OS/2 workplace shell seems to send SET_EA requests of "null"
8393 * length (4 bytes containing IVAL 4).
8394 * They seem to have no effect. Bug #3212. JRA.
8397 if (total_data
&& (total_data
!= 4)) {
8398 /* Any data in this call is an EA list. */
8399 if (total_data
< 10) {
8400 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8404 if (IVAL(pdata
,0) > total_data
) {
8405 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
8406 IVAL(pdata
,0), (unsigned int)total_data
));
8407 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8411 ea_list
= read_ea_list(talloc_tos(), pdata
+ 4,
8414 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8418 if (!lp_ea_support(SNUM(conn
))) {
8419 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
8423 /* If total_data == 4 Windows doesn't care what values
8424 * are placed in that field, it just ignores them.
8425 * The System i QNTC IBM SMB client puts bad values here,
8426 * so ignore them. */
8428 status
= create_directory(conn
, req
, smb_dname
);
8430 if (!NT_STATUS_IS_OK(status
)) {
8431 reply_nterror(req
, status
);
8435 /* Try and set any given EA. */
8437 status
= set_ea(conn
, NULL
, smb_dname
, ea_list
);
8438 if (!NT_STATUS_IS_OK(status
)) {
8439 reply_nterror(req
, status
);
8444 /* Realloc the parameter and data sizes */
8445 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
8446 if(*pparams
== NULL
) {
8447 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8454 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 2, *ppdata
, 0, max_data_bytes
);
8457 TALLOC_FREE(smb_dname
);
8461 /****************************************************************************
8462 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
8463 We don't actually do this - we just send a null response.
8464 ****************************************************************************/
8466 static void call_trans2findnotifyfirst(connection_struct
*conn
,
8467 struct smb_request
*req
,
8468 char **pparams
, int total_params
,
8469 char **ppdata
, int total_data
,
8470 unsigned int max_data_bytes
)
8472 char *params
= *pparams
;
8475 if (total_params
< 6) {
8476 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8480 info_level
= SVAL(params
,4);
8481 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level
));
8483 switch (info_level
) {
8488 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
8492 /* Realloc the parameter and data sizes */
8493 *pparams
= (char *)SMB_REALLOC(*pparams
,6);
8494 if (*pparams
== NULL
) {
8495 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8500 SSVAL(params
,0,fnf_handle
);
8501 SSVAL(params
,2,0); /* No changes */
8502 SSVAL(params
,4,0); /* No EA errors */
8509 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 6, *ppdata
, 0, max_data_bytes
);
8514 /****************************************************************************
8515 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
8516 changes). Currently this does nothing.
8517 ****************************************************************************/
8519 static void call_trans2findnotifynext(connection_struct
*conn
,
8520 struct smb_request
*req
,
8521 char **pparams
, int total_params
,
8522 char **ppdata
, int total_data
,
8523 unsigned int max_data_bytes
)
8525 char *params
= *pparams
;
8527 DEBUG(3,("call_trans2findnotifynext\n"));
8529 /* Realloc the parameter and data sizes */
8530 *pparams
= (char *)SMB_REALLOC(*pparams
,4);
8531 if (*pparams
== NULL
) {
8532 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8537 SSVAL(params
,0,0); /* No changes */
8538 SSVAL(params
,2,0); /* No EA errors */
8540 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 4, *ppdata
, 0, max_data_bytes
);
8545 /****************************************************************************
8546 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
8547 ****************************************************************************/
8549 static void call_trans2getdfsreferral(connection_struct
*conn
,
8550 struct smb_request
*req
,
8551 char **pparams
, int total_params
,
8552 char **ppdata
, int total_data
,
8553 unsigned int max_data_bytes
)
8555 char *params
= *pparams
;
8556 char *pathname
= NULL
;
8558 int max_referral_level
;
8559 NTSTATUS status
= NT_STATUS_OK
;
8560 TALLOC_CTX
*ctx
= talloc_tos();
8562 DEBUG(10,("call_trans2getdfsreferral\n"));
8564 if (total_params
< 3) {
8565 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8569 max_referral_level
= SVAL(params
,0);
8571 if(!lp_host_msdfs()) {
8572 reply_nterror(req
, NT_STATUS_NOT_IMPLEMENTED
);
8576 srvstr_pull_talloc(ctx
, params
, req
->flags2
, &pathname
, ¶ms
[2],
8577 total_params
- 2, STR_TERMINATE
);
8579 reply_nterror(req
, NT_STATUS_NOT_FOUND
);
8582 if((reply_size
= setup_dfs_referral(conn
, pathname
, max_referral_level
,
8583 ppdata
,&status
)) < 0) {
8584 reply_nterror(req
, status
);
8588 SSVAL((discard_const_p(uint8_t, req
->inbuf
)), smb_flg2
,
8589 SVAL(req
->inbuf
,smb_flg2
) | FLAGS2_DFS_PATHNAMES
);
8590 send_trans2_replies(conn
, req
, NT_STATUS_OK
, 0,0,*ppdata
,reply_size
, max_data_bytes
);
8595 #define LMCAT_SPL 0x53
8596 #define LMFUNC_GETJOBID 0x60
8598 /****************************************************************************
8599 Reply to a TRANS2_IOCTL - used for OS/2 printing.
8600 ****************************************************************************/
8602 static void call_trans2ioctl(connection_struct
*conn
,
8603 struct smb_request
*req
,
8604 char **pparams
, int total_params
,
8605 char **ppdata
, int total_data
,
8606 unsigned int max_data_bytes
)
8608 char *pdata
= *ppdata
;
8609 files_struct
*fsp
= file_fsp(req
, SVAL(req
->vwv
+15, 0));
8611 /* check for an invalid fid before proceeding */
8614 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
8618 if ((SVAL(req
->vwv
+16, 0) == LMCAT_SPL
)
8619 && (SVAL(req
->vwv
+17, 0) == LMFUNC_GETJOBID
)) {
8620 *ppdata
= (char *)SMB_REALLOC(*ppdata
, 32);
8621 if (*ppdata
== NULL
) {
8622 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8627 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
8628 CAN ACCEPT THIS IN UNICODE. JRA. */
8631 SSVAL(pdata
, 0, print_spool_rap_jobid(fsp
->print_file
));
8633 srvstr_push(pdata
, req
->flags2
, pdata
+ 2,
8634 lp_netbios_name(), 15,
8635 STR_ASCII
|STR_TERMINATE
); /* Our NetBIOS name */
8636 srvstr_push(pdata
, req
->flags2
, pdata
+18,
8637 lp_servicename(talloc_tos(), SNUM(conn
)), 13,
8638 STR_ASCII
|STR_TERMINATE
); /* Service name */
8639 send_trans2_replies(conn
, req
, NT_STATUS_OK
, *pparams
, 0, *ppdata
, 32,
8644 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
8645 reply_nterror(req
, NT_STATUS_NOT_IMPLEMENTED
);
8648 /****************************************************************************
8649 Reply to a SMBfindclose (stop trans2 directory search).
8650 ****************************************************************************/
8652 void reply_findclose(struct smb_request
*req
)
8655 struct smbd_server_connection
*sconn
= req
->sconn
;
8657 START_PROFILE(SMBfindclose
);
8660 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8661 END_PROFILE(SMBfindclose
);
8665 dptr_num
= SVALS(req
->vwv
+0, 0);
8667 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num
));
8669 dptr_close(sconn
, &dptr_num
);
8671 reply_outbuf(req
, 0, 0);
8673 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num
));
8675 END_PROFILE(SMBfindclose
);
8679 /****************************************************************************
8680 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
8681 ****************************************************************************/
8683 void reply_findnclose(struct smb_request
*req
)
8687 START_PROFILE(SMBfindnclose
);
8690 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8691 END_PROFILE(SMBfindnclose
);
8695 dptr_num
= SVAL(req
->vwv
+0, 0);
8697 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num
));
8699 /* We never give out valid handles for a
8700 findnotifyfirst - so any dptr_num is ok here.
8703 reply_outbuf(req
, 0, 0);
8705 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num
));
8707 END_PROFILE(SMBfindnclose
);
8711 static void handle_trans2(connection_struct
*conn
, struct smb_request
*req
,
8712 struct trans_state
*state
)
8714 if (get_Protocol() >= PROTOCOL_NT1
) {
8715 req
->flags2
|= 0x40; /* IS_LONG_NAME */
8716 SSVAL((discard_const_p(uint8_t, req
->inbuf
)),smb_flg2
,req
->flags2
);
8719 if (ENCRYPTION_REQUIRED(conn
) && !req
->encrypted
) {
8720 if (state
->call
!= TRANSACT2_QFSINFO
&&
8721 state
->call
!= TRANSACT2_SETFSINFO
) {
8722 DEBUG(0,("handle_trans2: encryption required "
8724 (unsigned int)state
->call
));
8725 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
8730 SMB_PERFCOUNT_SET_SUBOP(&req
->pcd
, state
->call
);
8732 /* Now we must call the relevant TRANS2 function */
8733 switch(state
->call
) {
8734 case TRANSACT2_OPEN
:
8736 START_PROFILE(Trans2_open
);
8737 call_trans2open(conn
, req
,
8738 &state
->param
, state
->total_param
,
8739 &state
->data
, state
->total_data
,
8740 state
->max_data_return
);
8741 END_PROFILE(Trans2_open
);
8745 case TRANSACT2_FINDFIRST
:
8747 START_PROFILE(Trans2_findfirst
);
8748 call_trans2findfirst(conn
, req
,
8749 &state
->param
, state
->total_param
,
8750 &state
->data
, state
->total_data
,
8751 state
->max_data_return
);
8752 END_PROFILE(Trans2_findfirst
);
8756 case TRANSACT2_FINDNEXT
:
8758 START_PROFILE(Trans2_findnext
);
8759 call_trans2findnext(conn
, req
,
8760 &state
->param
, state
->total_param
,
8761 &state
->data
, state
->total_data
,
8762 state
->max_data_return
);
8763 END_PROFILE(Trans2_findnext
);
8767 case TRANSACT2_QFSINFO
:
8769 START_PROFILE(Trans2_qfsinfo
);
8770 call_trans2qfsinfo(conn
, req
,
8771 &state
->param
, state
->total_param
,
8772 &state
->data
, state
->total_data
,
8773 state
->max_data_return
);
8774 END_PROFILE(Trans2_qfsinfo
);
8778 case TRANSACT2_SETFSINFO
:
8780 START_PROFILE(Trans2_setfsinfo
);
8781 call_trans2setfsinfo(conn
, req
,
8782 &state
->param
, state
->total_param
,
8783 &state
->data
, state
->total_data
,
8784 state
->max_data_return
);
8785 END_PROFILE(Trans2_setfsinfo
);
8789 case TRANSACT2_QPATHINFO
:
8790 case TRANSACT2_QFILEINFO
:
8792 START_PROFILE(Trans2_qpathinfo
);
8793 call_trans2qfilepathinfo(conn
, req
, state
->call
,
8794 &state
->param
, state
->total_param
,
8795 &state
->data
, state
->total_data
,
8796 state
->max_data_return
);
8797 END_PROFILE(Trans2_qpathinfo
);
8801 case TRANSACT2_SETPATHINFO
:
8802 case TRANSACT2_SETFILEINFO
:
8804 START_PROFILE(Trans2_setpathinfo
);
8805 call_trans2setfilepathinfo(conn
, req
, state
->call
,
8806 &state
->param
, state
->total_param
,
8807 &state
->data
, state
->total_data
,
8808 state
->max_data_return
);
8809 END_PROFILE(Trans2_setpathinfo
);
8813 case TRANSACT2_FINDNOTIFYFIRST
:
8815 START_PROFILE(Trans2_findnotifyfirst
);
8816 call_trans2findnotifyfirst(conn
, req
,
8817 &state
->param
, state
->total_param
,
8818 &state
->data
, state
->total_data
,
8819 state
->max_data_return
);
8820 END_PROFILE(Trans2_findnotifyfirst
);
8824 case TRANSACT2_FINDNOTIFYNEXT
:
8826 START_PROFILE(Trans2_findnotifynext
);
8827 call_trans2findnotifynext(conn
, req
,
8828 &state
->param
, state
->total_param
,
8829 &state
->data
, state
->total_data
,
8830 state
->max_data_return
);
8831 END_PROFILE(Trans2_findnotifynext
);
8835 case TRANSACT2_MKDIR
:
8837 START_PROFILE(Trans2_mkdir
);
8838 call_trans2mkdir(conn
, req
,
8839 &state
->param
, state
->total_param
,
8840 &state
->data
, state
->total_data
,
8841 state
->max_data_return
);
8842 END_PROFILE(Trans2_mkdir
);
8846 case TRANSACT2_GET_DFS_REFERRAL
:
8848 START_PROFILE(Trans2_get_dfs_referral
);
8849 call_trans2getdfsreferral(conn
, req
,
8850 &state
->param
, state
->total_param
,
8851 &state
->data
, state
->total_data
,
8852 state
->max_data_return
);
8853 END_PROFILE(Trans2_get_dfs_referral
);
8857 case TRANSACT2_IOCTL
:
8859 START_PROFILE(Trans2_ioctl
);
8860 call_trans2ioctl(conn
, req
,
8861 &state
->param
, state
->total_param
,
8862 &state
->data
, state
->total_data
,
8863 state
->max_data_return
);
8864 END_PROFILE(Trans2_ioctl
);
8869 /* Error in request */
8870 DEBUG(2,("Unknown request %d in trans2 call\n", state
->call
));
8871 reply_nterror(req
, NT_STATUS_NOT_IMPLEMENTED
);
8875 /****************************************************************************
8876 Reply to a SMBtrans2.
8877 ****************************************************************************/
8879 void reply_trans2(struct smb_request
*req
)
8881 connection_struct
*conn
= req
->conn
;
8886 unsigned int tran_call
;
8887 struct trans_state
*state
;
8890 START_PROFILE(SMBtrans2
);
8892 if (req
->wct
< 14) {
8893 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8894 END_PROFILE(SMBtrans2
);
8898 dsoff
= SVAL(req
->vwv
+12, 0);
8899 dscnt
= SVAL(req
->vwv
+11, 0);
8900 psoff
= SVAL(req
->vwv
+10, 0);
8901 pscnt
= SVAL(req
->vwv
+9, 0);
8902 tran_call
= SVAL(req
->vwv
+14, 0);
8904 result
= allow_new_trans(conn
->pending_trans
, req
->mid
);
8905 if (!NT_STATUS_IS_OK(result
)) {
8906 DEBUG(2, ("Got invalid trans2 request: %s\n",
8907 nt_errstr(result
)));
8908 reply_nterror(req
, result
);
8909 END_PROFILE(SMBtrans2
);
8914 switch (tran_call
) {
8915 /* List the allowed trans2 calls on IPC$ */
8916 case TRANSACT2_OPEN
:
8917 case TRANSACT2_GET_DFS_REFERRAL
:
8918 case TRANSACT2_QFILEINFO
:
8919 case TRANSACT2_QFSINFO
:
8920 case TRANSACT2_SETFSINFO
:
8923 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
8924 END_PROFILE(SMBtrans2
);
8929 if ((state
= talloc(conn
, struct trans_state
)) == NULL
) {
8930 DEBUG(0, ("talloc failed\n"));
8931 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8932 END_PROFILE(SMBtrans2
);
8936 state
->cmd
= SMBtrans2
;
8938 state
->mid
= req
->mid
;
8939 state
->vuid
= req
->vuid
;
8940 state
->setup_count
= SVAL(req
->vwv
+13, 0);
8941 state
->setup
= NULL
;
8942 state
->total_param
= SVAL(req
->vwv
+0, 0);
8943 state
->param
= NULL
;
8944 state
->total_data
= SVAL(req
->vwv
+1, 0);
8946 state
->max_param_return
= SVAL(req
->vwv
+2, 0);
8947 state
->max_data_return
= SVAL(req
->vwv
+3, 0);
8948 state
->max_setup_return
= SVAL(req
->vwv
+4, 0);
8949 state
->close_on_completion
= BITSETW(req
->vwv
+5, 0);
8950 state
->one_way
= BITSETW(req
->vwv
+5, 1);
8952 state
->call
= tran_call
;
8954 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
8955 is so as a sanity check */
8956 if (state
->setup_count
!= 1) {
8958 * Need to have rc=0 for ioctl to get job id for OS/2.
8959 * Network printing will fail if function is not successful.
8960 * Similar function in reply.c will be used if protocol
8961 * is LANMAN1.0 instead of LM1.2X002.
8962 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
8963 * outbuf doesn't have to be set(only job id is used).
8965 if ( (state
->setup_count
== 4)
8966 && (tran_call
== TRANSACT2_IOCTL
)
8967 && (SVAL(req
->vwv
+16, 0) == LMCAT_SPL
)
8968 && (SVAL(req
->vwv
+17, 0) == LMFUNC_GETJOBID
)) {
8969 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
8971 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state
->setup_count
));
8972 DEBUG(2,("Transaction is %d\n",tran_call
));
8974 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8975 END_PROFILE(SMBtrans2
);
8980 if ((dscnt
> state
->total_data
) || (pscnt
> state
->total_param
))
8983 if (state
->total_data
) {
8985 if (trans_oob(state
->total_data
, 0, dscnt
)
8986 || trans_oob(smb_len(req
->inbuf
), dsoff
, dscnt
)) {
8990 /* Can't use talloc here, the core routines do realloc on the
8991 * params and data. */
8992 state
->data
= (char *)SMB_MALLOC(state
->total_data
);
8993 if (state
->data
== NULL
) {
8994 DEBUG(0,("reply_trans2: data malloc fail for %u "
8995 "bytes !\n", (unsigned int)state
->total_data
));
8997 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8998 END_PROFILE(SMBtrans2
);
9002 memcpy(state
->data
,smb_base(req
->inbuf
)+dsoff
,dscnt
);
9005 if (state
->total_param
) {
9007 if (trans_oob(state
->total_param
, 0, pscnt
)
9008 || trans_oob(smb_len(req
->inbuf
), psoff
, pscnt
)) {
9012 /* Can't use talloc here, the core routines do realloc on the
9013 * params and data. */
9014 state
->param
= (char *)SMB_MALLOC(state
->total_param
);
9015 if (state
->param
== NULL
) {
9016 DEBUG(0,("reply_trans: param malloc fail for %u "
9017 "bytes !\n", (unsigned int)state
->total_param
));
9018 SAFE_FREE(state
->data
);
9020 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
9021 END_PROFILE(SMBtrans2
);
9025 memcpy(state
->param
,smb_base(req
->inbuf
)+psoff
,pscnt
);
9028 state
->received_data
= dscnt
;
9029 state
->received_param
= pscnt
;
9031 if ((state
->received_param
== state
->total_param
) &&
9032 (state
->received_data
== state
->total_data
)) {
9034 handle_trans2(conn
, req
, state
);
9036 SAFE_FREE(state
->data
);
9037 SAFE_FREE(state
->param
);
9039 END_PROFILE(SMBtrans2
);
9043 DLIST_ADD(conn
->pending_trans
, state
);
9045 /* We need to send an interim response then receive the rest
9046 of the parameter/data bytes */
9047 reply_outbuf(req
, 0, 0);
9048 show_msg((char *)req
->outbuf
);
9049 END_PROFILE(SMBtrans2
);
9054 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
9055 SAFE_FREE(state
->data
);
9056 SAFE_FREE(state
->param
);
9058 END_PROFILE(SMBtrans2
);
9059 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
9063 /****************************************************************************
9064 Reply to a SMBtranss2
9065 ****************************************************************************/
9067 void reply_transs2(struct smb_request
*req
)
9069 connection_struct
*conn
= req
->conn
;
9070 unsigned int pcnt
,poff
,dcnt
,doff
,pdisp
,ddisp
;
9071 struct trans_state
*state
;
9073 START_PROFILE(SMBtranss2
);
9075 show_msg((const char *)req
->inbuf
);
9077 /* Windows clients expect all replies to
9078 a transact secondary (SMBtranss2 0x33)
9079 to have a command code of transact
9080 (SMBtrans2 0x32). See bug #8989
9081 and also [MS-CIFS] section 2.2.4.47.2
9084 req
->cmd
= SMBtrans2
;
9087 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
9088 END_PROFILE(SMBtranss2
);
9092 for (state
= conn
->pending_trans
; state
!= NULL
;
9093 state
= state
->next
) {
9094 if (state
->mid
== req
->mid
) {
9099 if ((state
== NULL
) || (state
->cmd
!= SMBtrans2
)) {
9100 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
9101 END_PROFILE(SMBtranss2
);
9105 /* Revise state->total_param and state->total_data in case they have
9106 changed downwards */
9108 if (SVAL(req
->vwv
+0, 0) < state
->total_param
)
9109 state
->total_param
= SVAL(req
->vwv
+0, 0);
9110 if (SVAL(req
->vwv
+1, 0) < state
->total_data
)
9111 state
->total_data
= SVAL(req
->vwv
+1, 0);
9113 pcnt
= SVAL(req
->vwv
+2, 0);
9114 poff
= SVAL(req
->vwv
+3, 0);
9115 pdisp
= SVAL(req
->vwv
+4, 0);
9117 dcnt
= SVAL(req
->vwv
+5, 0);
9118 doff
= SVAL(req
->vwv
+6, 0);
9119 ddisp
= SVAL(req
->vwv
+7, 0);
9121 state
->received_param
+= pcnt
;
9122 state
->received_data
+= dcnt
;
9124 if ((state
->received_data
> state
->total_data
) ||
9125 (state
->received_param
> state
->total_param
))
9129 if (trans_oob(state
->total_param
, pdisp
, pcnt
)
9130 || trans_oob(smb_len(req
->inbuf
), poff
, pcnt
)) {
9133 memcpy(state
->param
+pdisp
,smb_base(req
->inbuf
)+poff
,pcnt
);
9137 if (trans_oob(state
->total_data
, ddisp
, dcnt
)
9138 || trans_oob(smb_len(req
->inbuf
), doff
, dcnt
)) {
9141 memcpy(state
->data
+ddisp
, smb_base(req
->inbuf
)+doff
,dcnt
);
9144 if ((state
->received_param
< state
->total_param
) ||
9145 (state
->received_data
< state
->total_data
)) {
9146 END_PROFILE(SMBtranss2
);
9150 handle_trans2(conn
, req
, state
);
9152 DLIST_REMOVE(conn
->pending_trans
, state
);
9153 SAFE_FREE(state
->data
);
9154 SAFE_FREE(state
->param
);
9157 END_PROFILE(SMBtranss2
);
9162 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
9163 DLIST_REMOVE(conn
->pending_trans
, state
);
9164 SAFE_FREE(state
->data
);
9165 SAFE_FREE(state
->param
);
9167 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
9168 END_PROFILE(SMBtranss2
);