2 Unix SMB/CIFS implementation.
3 SMB transaction2 handling
4 Copyright (C) Jeremy Allison 1994-2007
5 Copyright (C) Stefan (metze) Metzmacher 2003
6 Copyright (C) Volker Lendecke 2005-2007
7 Copyright (C) Steve French 2005
8 Copyright (C) James Peach 2006-2007
10 Extensively modified by Andrew Tridgell, 1995
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 3 of the License, or
15 (at your option) any later version.
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with this program. If not, see <http://www.gnu.org/licenses/>.
28 #include "system/filesys.h"
30 #include "smbd/smbd.h"
31 #include "smbd/globals.h"
32 #include "../libcli/auth/libcli_auth.h"
33 #include "../librpc/gen_ndr/xattr.h"
34 #include "../librpc/gen_ndr/ndr_security.h"
35 #include "../librpc/gen_ndr/open_files.h"
36 #include "libcli/security/security.h"
39 #include "smbprofile.h"
40 #include "rpc_server/srv_pipe_hnd.h"
42 #include "lib/util_ea.h"
43 #include "lib/readdir_attr.h"
45 #define DIR_ENTRY_SAFETY_MARGIN 4096
47 static char *store_file_unix_basic(connection_struct
*conn
,
50 const SMB_STRUCT_STAT
*psbuf
);
52 static char *store_file_unix_basic_info2(connection_struct
*conn
,
55 const SMB_STRUCT_STAT
*psbuf
);
57 /********************************************************************
58 The canonical "check access" based on object handle or path function.
59 ********************************************************************/
61 NTSTATUS
check_access(connection_struct
*conn
,
63 const struct smb_filename
*smb_fname
,
67 if (!(fsp
->access_mask
& access_mask
)) {
68 return NT_STATUS_ACCESS_DENIED
;
71 NTSTATUS status
= smbd_check_access_rights(conn
,
75 if (!NT_STATUS_IS_OK(status
)) {
82 /********************************************************************
83 Roundup a value to the nearest allocation roundup size boundary.
84 Only do this for Windows clients.
85 ********************************************************************/
87 uint64_t smb_roundup(connection_struct
*conn
, uint64_t val
)
89 uint64_t rval
= lp_allocation_roundup_size(SNUM(conn
));
91 /* Only roundup for Windows clients. */
92 enum remote_arch_types ra_type
= get_remote_arch();
93 if (rval
&& (ra_type
!= RA_SAMBA
) && (ra_type
!= RA_CIFSFS
)) {
94 val
= SMB_ROUNDUP(val
,rval
);
99 /********************************************************************
100 Create a 64 bit FileIndex. If the file is on the same device as
101 the root of the share, just return the 64-bit inode. If it isn't,
102 mangle as we used to do.
103 ********************************************************************/
105 uint64_t get_FileIndex(connection_struct
*conn
, const SMB_STRUCT_STAT
*psbuf
)
108 if (conn
->base_share_dev
== psbuf
->st_ex_dev
) {
109 return (uint64_t)psbuf
->st_ex_ino
;
111 file_index
= ((psbuf
->st_ex_ino
) & UINT32_MAX
); /* FileIndexLow */
112 file_index
|= ((uint64_t)((psbuf
->st_ex_dev
) & UINT32_MAX
)) << 32; /* FileIndexHigh */
116 /****************************************************************************
117 Utility functions for dealing with extended attributes.
118 ****************************************************************************/
120 /****************************************************************************
121 Refuse to allow clients to overwrite our private xattrs.
122 ****************************************************************************/
124 bool samba_private_attr_name(const char *unix_ea_name
)
126 static const char * const prohibited_ea_names
[] = {
127 SAMBA_POSIX_INHERITANCE_EA_NAME
,
128 SAMBA_XATTR_DOS_ATTRIB
,
136 for (i
= 0; prohibited_ea_names
[i
]; i
++) {
137 if (strequal( prohibited_ea_names
[i
], unix_ea_name
))
140 if (strncasecmp_m(unix_ea_name
, SAMBA_XATTR_DOSSTREAM_PREFIX
,
141 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX
)) == 0) {
147 /****************************************************************************
148 Get one EA value. Fill in a struct ea_struct.
149 ****************************************************************************/
151 NTSTATUS
get_ea_value(TALLOC_CTX
*mem_ctx
, connection_struct
*conn
,
152 files_struct
*fsp
, const char *fname
,
153 const char *ea_name
, struct ea_struct
*pea
)
155 /* Get the value of this xattr. Max size is 64k. */
156 size_t attr_size
= 256;
162 val
= talloc_realloc(mem_ctx
, val
, char, attr_size
);
164 return NT_STATUS_NO_MEMORY
;
167 if (fsp
&& fsp
->fh
->fd
!= -1) {
168 sizeret
= SMB_VFS_FGETXATTR(fsp
, ea_name
, val
, attr_size
);
170 sizeret
= SMB_VFS_GETXATTR(conn
, fname
, ea_name
, val
, attr_size
);
173 if (sizeret
== -1 && errno
== ERANGE
&& attr_size
!= 65536) {
179 return map_nt_error_from_unix(errno
);
182 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name
, (unsigned int)sizeret
));
183 dump_data(10, (uint8
*)val
, sizeret
);
186 if (strnequal(ea_name
, "user.", 5)) {
187 pea
->name
= talloc_strdup(mem_ctx
, &ea_name
[5]);
189 pea
->name
= talloc_strdup(mem_ctx
, ea_name
);
191 if (pea
->name
== NULL
) {
193 return NT_STATUS_NO_MEMORY
;
195 pea
->value
.data
= (unsigned char *)val
;
196 pea
->value
.length
= (size_t)sizeret
;
200 NTSTATUS
get_ea_names_from_file(TALLOC_CTX
*mem_ctx
, connection_struct
*conn
,
201 files_struct
*fsp
, const char *fname
,
202 char ***pnames
, size_t *pnum_names
)
204 /* Get a list of all xattrs. Max namesize is 64k. */
205 size_t ea_namelist_size
= 1024;
206 char *ea_namelist
= NULL
;
211 ssize_t sizeret
= -1;
213 if (!lp_ea_support(SNUM(conn
))) {
222 * TALLOC the result early to get the talloc hierarchy right.
225 names
= talloc_array(mem_ctx
, char *, 1);
227 DEBUG(0, ("talloc failed\n"));
228 return NT_STATUS_NO_MEMORY
;
231 while (ea_namelist_size
<= 65536) {
233 ea_namelist
= talloc_realloc(
234 names
, ea_namelist
, char, ea_namelist_size
);
235 if (ea_namelist
== NULL
) {
236 DEBUG(0, ("talloc failed\n"));
238 return NT_STATUS_NO_MEMORY
;
241 if (fsp
&& fsp
->fh
->fd
!= -1) {
242 sizeret
= SMB_VFS_FLISTXATTR(fsp
, ea_namelist
,
245 sizeret
= SMB_VFS_LISTXATTR(conn
, fname
, ea_namelist
,
249 if ((sizeret
== -1) && (errno
== ERANGE
)) {
250 ea_namelist_size
*= 2;
259 return map_nt_error_from_unix(errno
);
262 DEBUG(10, ("%s: ea_namelist size = %u\n",
263 __func__
, (unsigned int)sizeret
));
275 * Ensure the result is 0-terminated
278 if (ea_namelist
[sizeret
-1] != '\0') {
280 return NT_STATUS_INTERNAL_ERROR
;
288 for (p
= ea_namelist
; p
- ea_namelist
< sizeret
; p
+= strlen(p
)+1) {
292 tmp
= talloc_realloc(mem_ctx
, names
, char *, num_names
);
294 DEBUG(0, ("talloc failed\n"));
296 return NT_STATUS_NO_MEMORY
;
302 for (p
= ea_namelist
; p
- ea_namelist
< sizeret
; p
+= strlen(p
)+1) {
303 names
[num_names
++] = p
;
311 *pnum_names
= num_names
;
315 /****************************************************************************
316 Return a linked list of the total EA's. Plus the total size
317 ****************************************************************************/
319 static NTSTATUS
get_ea_list_from_file_path(TALLOC_CTX
*mem_ctx
, connection_struct
*conn
, files_struct
*fsp
,
320 const char *fname
, size_t *pea_total_len
, struct ea_list
**ea_list
)
322 /* Get a list of all xattrs. Max namesize is 64k. */
325 struct ea_list
*ea_list_head
= NULL
;
331 status
= get_ea_names_from_file(talloc_tos(), conn
, fsp
, fname
,
334 if (!NT_STATUS_IS_OK(status
)) {
338 if (num_names
== 0) {
343 for (i
=0; i
<num_names
; i
++) {
344 struct ea_list
*listp
;
347 if (strnequal(names
[i
], "system.", 7)
348 || samba_private_attr_name(names
[i
]))
352 * Filter out any underlying POSIX EA names
353 * that a Windows client can't handle.
355 if (!lp_posix_pathnames() &&
356 is_invalid_windows_ea_name(names
[i
])) {
360 listp
= talloc(mem_ctx
, struct ea_list
);
362 return NT_STATUS_NO_MEMORY
;
365 status
= get_ea_value(listp
, conn
, fsp
,
369 if (!NT_STATUS_IS_OK(status
)) {
374 if (listp
->ea
.value
.length
== 0) {
376 * We can never return a zero length EA.
377 * Windows reports the EA's as corrupted.
383 push_ascii_fstring(dos_ea_name
, listp
->ea
.name
);
386 4 + strlen(dos_ea_name
) + 1 + listp
->ea
.value
.length
;
388 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
389 "= %u\n", (unsigned int)*pea_total_len
, dos_ea_name
,
390 (unsigned int)listp
->ea
.value
.length
));
392 DLIST_ADD_END(ea_list_head
, listp
, struct ea_list
*);
396 /* Add on 4 for total length. */
397 if (*pea_total_len
) {
401 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
402 (unsigned int)*pea_total_len
));
404 *ea_list
= ea_list_head
;
408 static NTSTATUS
get_ea_list_from_file(TALLOC_CTX
*mem_ctx
, connection_struct
*conn
, files_struct
*fsp
,
409 const struct smb_filename
*smb_fname
, size_t *pea_total_len
, struct ea_list
**ea_list
)
414 if (!lp_ea_support(SNUM(conn
))) {
418 if (is_ntfs_stream_smb_fname(smb_fname
)) {
419 return NT_STATUS_INVALID_PARAMETER
;
422 return get_ea_list_from_file_path(mem_ctx
, conn
, fsp
, smb_fname
->base_name
, pea_total_len
, ea_list
);
425 /****************************************************************************
426 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
428 ****************************************************************************/
430 static unsigned int fill_ea_buffer(TALLOC_CTX
*mem_ctx
, char *pdata
, unsigned int total_data_size
,
431 connection_struct
*conn
, struct ea_list
*ea_list
)
433 unsigned int ret_data_size
= 4;
436 SMB_ASSERT(total_data_size
>= 4);
438 if (!lp_ea_support(SNUM(conn
))) {
443 for (p
= pdata
+ 4; ea_list
; ea_list
= ea_list
->next
) {
446 push_ascii_fstring(dos_ea_name
, ea_list
->ea
.name
);
447 dos_namelen
= strlen(dos_ea_name
);
448 if (dos_namelen
> 255 || dos_namelen
== 0) {
451 if (ea_list
->ea
.value
.length
> 65535) {
454 if (4 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
> total_data_size
) {
458 /* We know we have room. */
459 SCVAL(p
,0,ea_list
->ea
.flags
);
460 SCVAL(p
,1,dos_namelen
);
461 SSVAL(p
,2,ea_list
->ea
.value
.length
);
462 strlcpy(p
+4, dos_ea_name
, dos_namelen
+1);
463 memcpy( p
+ 4 + dos_namelen
+ 1, ea_list
->ea
.value
.data
, ea_list
->ea
.value
.length
);
465 total_data_size
-= 4 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
;
466 p
+= 4 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
;
469 ret_data_size
= PTR_DIFF(p
, pdata
);
470 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size
));
471 SIVAL(pdata
,0,ret_data_size
);
472 return ret_data_size
;
475 static NTSTATUS
fill_ea_chained_buffer(TALLOC_CTX
*mem_ctx
,
477 unsigned int total_data_size
,
478 unsigned int *ret_data_size
,
479 connection_struct
*conn
,
480 struct ea_list
*ea_list
)
482 uint8_t *p
= (uint8_t *)pdata
;
483 uint8_t *last_start
= NULL
;
484 bool do_store_data
= (pdata
!= NULL
);
488 if (!lp_ea_support(SNUM(conn
))) {
489 return NT_STATUS_NO_EAS_ON_FILE
;
492 for (; ea_list
; ea_list
= ea_list
->next
) {
498 if (last_start
!= NULL
&& do_store_data
) {
499 SIVAL(last_start
, 0, PTR_DIFF(p
, last_start
));
503 push_ascii_fstring(dos_ea_name
, ea_list
->ea
.name
);
504 dos_namelen
= strlen(dos_ea_name
);
505 if (dos_namelen
> 255 || dos_namelen
== 0) {
506 return NT_STATUS_INTERNAL_ERROR
;
508 if (ea_list
->ea
.value
.length
> 65535) {
509 return NT_STATUS_INTERNAL_ERROR
;
512 this_size
= 0x08 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
;
515 pad
= (4 - (this_size
% 4)) % 4;
520 if (this_size
> total_data_size
) {
521 return NT_STATUS_INFO_LENGTH_MISMATCH
;
524 /* We know we have room. */
525 SIVAL(p
, 0x00, 0); /* next offset */
526 SCVAL(p
, 0x04, ea_list
->ea
.flags
);
527 SCVAL(p
, 0x05, dos_namelen
);
528 SSVAL(p
, 0x06, ea_list
->ea
.value
.length
);
529 strlcpy((char *)(p
+0x08), dos_ea_name
, dos_namelen
+1);
530 memcpy(p
+ 0x08 + dos_namelen
+ 1, ea_list
->ea
.value
.data
, ea_list
->ea
.value
.length
);
532 memset(p
+ 0x08 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
,
536 total_data_size
-= this_size
;
542 *ret_data_size
= PTR_DIFF(p
, pdata
);
543 DEBUG(10,("fill_ea_chained_buffer: data_size = %u\n", *ret_data_size
));
547 static unsigned int estimate_ea_size(connection_struct
*conn
, files_struct
*fsp
, const struct smb_filename
*smb_fname
)
549 size_t total_ea_len
= 0;
551 struct ea_list
*ea_list
= NULL
;
553 if (!lp_ea_support(SNUM(conn
))) {
556 mem_ctx
= talloc_stackframe();
558 /* If this is a stream fsp, then we need to instead find the
559 * estimated ea len from the main file, not the stream
560 * (streams cannot have EAs), but the estimate isn't just 0 in
562 if (is_ntfs_stream_smb_fname(smb_fname
)) {
565 (void)get_ea_list_from_file_path(mem_ctx
, conn
, fsp
, smb_fname
->base_name
, &total_ea_len
, &ea_list
);
566 if(conn
->sconn
->using_smb2
) {
568 unsigned int ret_data_size
;
570 * We're going to be using fill_ea_chained_buffer() to
571 * marshall EA's - this size is significantly larger
572 * than the SMB1 buffer. Re-calculate the size without
575 status
= fill_ea_chained_buffer(mem_ctx
,
581 if (!NT_STATUS_IS_OK(status
)) {
584 total_ea_len
= ret_data_size
;
586 TALLOC_FREE(mem_ctx
);
590 /****************************************************************************
591 Ensure the EA name is case insensitive by matching any existing EA name.
592 ****************************************************************************/
594 static void canonicalize_ea_name(connection_struct
*conn
, files_struct
*fsp
, const char *fname
, fstring unix_ea_name
)
597 TALLOC_CTX
*mem_ctx
= talloc_tos();
598 struct ea_list
*ea_list
;
599 NTSTATUS status
= get_ea_list_from_file_path(mem_ctx
, conn
, fsp
, fname
, &total_ea_len
, &ea_list
);
600 if (!NT_STATUS_IS_OK(status
)) {
604 for (; ea_list
; ea_list
= ea_list
->next
) {
605 if (strequal(&unix_ea_name
[5], ea_list
->ea
.name
)) {
606 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
607 &unix_ea_name
[5], ea_list
->ea
.name
));
608 strlcpy(&unix_ea_name
[5], ea_list
->ea
.name
, sizeof(fstring
)-5);
614 /****************************************************************************
615 Set or delete an extended attribute.
616 ****************************************************************************/
618 NTSTATUS
set_ea(connection_struct
*conn
, files_struct
*fsp
,
619 const struct smb_filename
*smb_fname
, struct ea_list
*ea_list
)
624 if (!lp_ea_support(SNUM(conn
))) {
625 return NT_STATUS_EAS_NOT_SUPPORTED
;
628 status
= check_access(conn
, fsp
, smb_fname
, FILE_WRITE_EA
);
629 if (!NT_STATUS_IS_OK(status
)) {
633 /* Setting EAs on streams isn't supported. */
634 if (is_ntfs_stream_smb_fname(smb_fname
)) {
635 return NT_STATUS_INVALID_PARAMETER
;
639 * Filter out invalid Windows EA names - before
640 * we set *any* of them.
643 if (ea_list_has_invalid_name(ea_list
)) {
644 return STATUS_INVALID_EA_NAME
;
647 fname
= smb_fname
->base_name
;
649 for (;ea_list
; ea_list
= ea_list
->next
) {
651 fstring unix_ea_name
;
653 fstrcpy(unix_ea_name
, "user."); /* All EA's must start with user. */
654 fstrcat(unix_ea_name
, ea_list
->ea
.name
);
656 canonicalize_ea_name(conn
, fsp
, fname
, unix_ea_name
);
658 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name
, (unsigned int)ea_list
->ea
.value
.length
));
660 if (samba_private_attr_name(unix_ea_name
)) {
661 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name
));
662 return NT_STATUS_ACCESS_DENIED
;
665 if (ea_list
->ea
.value
.length
== 0) {
666 /* Remove the attribute. */
667 if (fsp
&& (fsp
->fh
->fd
!= -1)) {
668 DEBUG(10,("set_ea: deleting ea name %s on "
669 "file %s by file descriptor.\n",
670 unix_ea_name
, fsp_str_dbg(fsp
)));
671 ret
= SMB_VFS_FREMOVEXATTR(fsp
, unix_ea_name
);
673 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
674 unix_ea_name
, fname
));
675 ret
= SMB_VFS_REMOVEXATTR(conn
, fname
, unix_ea_name
);
678 /* Removing a non existent attribute always succeeds. */
679 if (ret
== -1 && errno
== ENOATTR
) {
680 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
686 if (fsp
&& (fsp
->fh
->fd
!= -1)) {
687 DEBUG(10,("set_ea: setting ea name %s on file "
688 "%s by file descriptor.\n",
689 unix_ea_name
, fsp_str_dbg(fsp
)));
690 ret
= SMB_VFS_FSETXATTR(fsp
, unix_ea_name
,
691 ea_list
->ea
.value
.data
, ea_list
->ea
.value
.length
, 0);
693 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
694 unix_ea_name
, fname
));
695 ret
= SMB_VFS_SETXATTR(conn
, fname
, unix_ea_name
,
696 ea_list
->ea
.value
.data
, ea_list
->ea
.value
.length
, 0);
702 if (errno
== ENOTSUP
) {
703 return NT_STATUS_EAS_NOT_SUPPORTED
;
706 return map_nt_error_from_unix(errno
);
712 /****************************************************************************
713 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
714 ****************************************************************************/
716 static struct ea_list
*read_ea_name_list(TALLOC_CTX
*ctx
, const char *pdata
, size_t data_size
)
718 struct ea_list
*ea_list_head
= NULL
;
719 size_t converted_size
, offset
= 0;
721 while (offset
+ 2 < data_size
) {
722 struct ea_list
*eal
= talloc_zero(ctx
, struct ea_list
);
723 unsigned int namelen
= CVAL(pdata
,offset
);
725 offset
++; /* Go past the namelen byte. */
727 /* integer wrap paranioa. */
728 if ((offset
+ namelen
< offset
) || (offset
+ namelen
< namelen
) ||
729 (offset
> data_size
) || (namelen
> data_size
) ||
730 (offset
+ namelen
>= data_size
)) {
733 /* Ensure the name is null terminated. */
734 if (pdata
[offset
+ namelen
] != '\0') {
737 if (!pull_ascii_talloc(ctx
, &eal
->ea
.name
, &pdata
[offset
],
739 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
740 "failed: %s", strerror(errno
)));
746 offset
+= (namelen
+ 1); /* Go past the name + terminating zero. */
747 DLIST_ADD_END(ea_list_head
, eal
, struct ea_list
*);
748 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal
->ea
.name
));
754 /****************************************************************************
755 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
756 ****************************************************************************/
758 static struct ea_list
*read_ea_list(TALLOC_CTX
*ctx
, const char *pdata
, size_t data_size
)
760 struct ea_list
*ea_list_head
= NULL
;
762 size_t bytes_used
= 0;
764 while (offset
< data_size
) {
765 struct ea_list
*eal
= read_ea_list_entry(ctx
, pdata
+ offset
, data_size
- offset
, &bytes_used
);
771 DLIST_ADD_END(ea_list_head
, eal
, struct ea_list
*);
772 offset
+= bytes_used
;
778 /****************************************************************************
779 Count the total EA size needed.
780 ****************************************************************************/
782 static size_t ea_list_size(struct ea_list
*ealist
)
785 struct ea_list
*listp
;
788 for (listp
= ealist
; listp
; listp
= listp
->next
) {
789 push_ascii_fstring(dos_ea_name
, listp
->ea
.name
);
790 ret
+= 4 + strlen(dos_ea_name
) + 1 + listp
->ea
.value
.length
;
792 /* Add on 4 for total length. */
800 /****************************************************************************
801 Return a union of EA's from a file list and a list of names.
802 The TALLOC context for the two lists *MUST* be identical as we steal
803 memory from one list to add to another. JRA.
804 ****************************************************************************/
806 static struct ea_list
*ea_list_union(struct ea_list
*name_list
, struct ea_list
*file_list
, size_t *total_ea_len
)
808 struct ea_list
*nlistp
, *flistp
;
810 for (nlistp
= name_list
; nlistp
; nlistp
= nlistp
->next
) {
811 for (flistp
= file_list
; flistp
; flistp
= flistp
->next
) {
812 if (strequal(nlistp
->ea
.name
, flistp
->ea
.name
)) {
818 /* Copy the data from this entry. */
819 nlistp
->ea
.flags
= flistp
->ea
.flags
;
820 nlistp
->ea
.value
= flistp
->ea
.value
;
823 nlistp
->ea
.flags
= 0;
824 ZERO_STRUCT(nlistp
->ea
.value
);
828 *total_ea_len
= ea_list_size(name_list
);
832 /****************************************************************************
833 Send the required number of replies back.
834 We assume all fields other than the data fields are
835 set correctly for the type of call.
836 HACK ! Always assumes smb_setup field is zero.
837 ****************************************************************************/
839 void send_trans2_replies(connection_struct
*conn
,
840 struct smb_request
*req
,
848 /* As we are using a protocol > LANMAN1 then the max_send
849 variable must have been set in the sessetupX call.
850 This takes precedence over the max_xmit field in the
851 global struct. These different max_xmit variables should
852 be merged as this is now too confusing */
854 int data_to_send
= datasize
;
855 int params_to_send
= paramsize
;
857 const char *pp
= params
;
858 const char *pd
= pdata
;
859 int params_sent_thistime
, data_sent_thistime
, total_sent_thistime
;
860 int alignment_offset
= 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
861 int data_alignment_offset
= 0;
862 bool overflow
= False
;
863 struct smbXsrv_connection
*xconn
= req
->xconn
;
864 int max_send
= xconn
->smb1
.sessions
.max_send
;
866 /* Modify the data_to_send and datasize and set the error if
867 we're trying to send more than max_data_bytes. We still send
868 the part of the packet(s) that fit. Strange, but needed
871 if (max_data_bytes
> 0 && datasize
> max_data_bytes
) {
872 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
873 max_data_bytes
, datasize
));
874 datasize
= data_to_send
= max_data_bytes
;
878 /* If there genuinely are no parameters or data to send just send the empty packet */
880 if(params_to_send
== 0 && data_to_send
== 0) {
881 reply_outbuf(req
, 10, 0);
882 if (NT_STATUS_V(status
)) {
885 ntstatus_to_dos(status
, &eclass
, &ecode
);
886 error_packet_set((char *)req
->outbuf
,
887 eclass
, ecode
, status
,
890 show_msg((char *)req
->outbuf
);
891 if (!srv_send_smb(xconn
,
894 IS_CONN_ENCRYPTED(conn
),
896 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
898 TALLOC_FREE(req
->outbuf
);
902 /* When sending params and data ensure that both are nicely aligned */
903 /* Only do this alignment when there is also data to send - else
904 can cause NT redirector problems. */
906 if (((params_to_send
% 4) != 0) && (data_to_send
!= 0))
907 data_alignment_offset
= 4 - (params_to_send
% 4);
909 /* Space is bufsize minus Netbios over TCP header minus SMB header */
910 /* The alignment_offset is to align the param bytes on an even byte
911 boundary. NT 4.0 Beta needs this to work correctly. */
913 useable_space
= max_send
- (smb_size
916 + data_alignment_offset
);
918 if (useable_space
< 0) {
919 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
920 "= %d!!!", useable_space
));
921 exit_server_cleanly("send_trans2_replies: Not enough space");
924 while (params_to_send
|| data_to_send
) {
925 /* Calculate whether we will totally or partially fill this packet */
927 total_sent_thistime
= params_to_send
+ data_to_send
;
929 /* We can never send more than useable_space */
931 * Note that 'useable_space' does not include the alignment offsets,
932 * but we must include the alignment offsets in the calculation of
933 * the length of the data we send over the wire, as the alignment offsets
934 * are sent here. Fix from Marc_Jacobsen@hp.com.
937 total_sent_thistime
= MIN(total_sent_thistime
, useable_space
);
939 reply_outbuf(req
, 10, total_sent_thistime
+ alignment_offset
940 + data_alignment_offset
);
942 /* Set total params and data to be sent */
943 SSVAL(req
->outbuf
,smb_tprcnt
,paramsize
);
944 SSVAL(req
->outbuf
,smb_tdrcnt
,datasize
);
946 /* Calculate how many parameters and data we can fit into
947 * this packet. Parameters get precedence
950 params_sent_thistime
= MIN(params_to_send
,useable_space
);
951 data_sent_thistime
= useable_space
- params_sent_thistime
;
952 data_sent_thistime
= MIN(data_sent_thistime
,data_to_send
);
954 SSVAL(req
->outbuf
,smb_prcnt
, params_sent_thistime
);
956 /* smb_proff is the offset from the start of the SMB header to the
957 parameter bytes, however the first 4 bytes of outbuf are
958 the Netbios over TCP header. Thus use smb_base() to subtract
959 them from the calculation */
961 SSVAL(req
->outbuf
,smb_proff
,
962 ((smb_buf(req
->outbuf
)+alignment_offset
)
963 - smb_base(req
->outbuf
)));
965 if(params_sent_thistime
== 0)
966 SSVAL(req
->outbuf
,smb_prdisp
,0);
968 /* Absolute displacement of param bytes sent in this packet */
969 SSVAL(req
->outbuf
,smb_prdisp
,pp
- params
);
971 SSVAL(req
->outbuf
,smb_drcnt
, data_sent_thistime
);
972 if(data_sent_thistime
== 0) {
973 SSVAL(req
->outbuf
,smb_droff
,0);
974 SSVAL(req
->outbuf
,smb_drdisp
, 0);
976 /* The offset of the data bytes is the offset of the
977 parameter bytes plus the number of parameters being sent this time */
978 SSVAL(req
->outbuf
, smb_droff
,
979 ((smb_buf(req
->outbuf
)+alignment_offset
)
980 - smb_base(req
->outbuf
))
981 + params_sent_thistime
+ data_alignment_offset
);
982 SSVAL(req
->outbuf
,smb_drdisp
, pd
- pdata
);
985 /* Initialize the padding for alignment */
987 if (alignment_offset
!= 0) {
988 memset(smb_buf(req
->outbuf
), 0, alignment_offset
);
991 /* Copy the param bytes into the packet */
993 if(params_sent_thistime
) {
994 memcpy((smb_buf(req
->outbuf
)+alignment_offset
), pp
,
995 params_sent_thistime
);
998 /* Copy in the data bytes */
999 if(data_sent_thistime
) {
1000 if (data_alignment_offset
!= 0) {
1001 memset((smb_buf(req
->outbuf
)+alignment_offset
+
1002 params_sent_thistime
), 0,
1003 data_alignment_offset
);
1005 memcpy(smb_buf(req
->outbuf
)+alignment_offset
1006 +params_sent_thistime
+data_alignment_offset
,
1007 pd
,data_sent_thistime
);
1010 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
1011 params_sent_thistime
, data_sent_thistime
, useable_space
));
1012 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
1013 params_to_send
, data_to_send
, paramsize
, datasize
));
1016 error_packet_set((char *)req
->outbuf
,
1017 ERRDOS
,ERRbufferoverflow
,
1018 STATUS_BUFFER_OVERFLOW
,
1020 } else if (NT_STATUS_V(status
)) {
1023 ntstatus_to_dos(status
, &eclass
, &ecode
);
1024 error_packet_set((char *)req
->outbuf
,
1025 eclass
, ecode
, status
,
1029 /* Send the packet */
1030 show_msg((char *)req
->outbuf
);
1031 if (!srv_send_smb(xconn
,
1032 (char *)req
->outbuf
,
1033 true, req
->seqnum
+1,
1034 IS_CONN_ENCRYPTED(conn
),
1036 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
1038 TALLOC_FREE(req
->outbuf
);
1040 pp
+= params_sent_thistime
;
1041 pd
+= data_sent_thistime
;
1043 params_to_send
-= params_sent_thistime
;
1044 data_to_send
-= data_sent_thistime
;
1047 if(params_to_send
< 0 || data_to_send
< 0) {
1048 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
1049 params_to_send
, data_to_send
));
1057 /****************************************************************************
1058 Reply to a TRANSACT2_OPEN.
1059 ****************************************************************************/
1061 static void call_trans2open(connection_struct
*conn
,
1062 struct smb_request
*req
,
1063 char **pparams
, int total_params
,
1064 char **ppdata
, int total_data
,
1065 unsigned int max_data_bytes
)
1067 struct smb_filename
*smb_fname
= NULL
;
1068 char *params
= *pparams
;
1069 char *pdata
= *ppdata
;
1072 bool oplock_request
;
1074 bool return_additional_info
;
1083 int fattr
=0,mtime
=0;
1084 SMB_INO_T inode
= 0;
1087 struct ea_list
*ea_list
= NULL
;
1092 uint32 create_disposition
;
1093 uint32 create_options
= 0;
1094 uint32_t private_flags
= 0;
1095 TALLOC_CTX
*ctx
= talloc_tos();
1098 * Ensure we have enough parameters to perform the operation.
1101 if (total_params
< 29) {
1102 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1106 flags
= SVAL(params
, 0);
1107 deny_mode
= SVAL(params
, 2);
1108 open_attr
= SVAL(params
,6);
1109 oplock_request
= (flags
& REQUEST_OPLOCK
) ? EXCLUSIVE_OPLOCK
: 0;
1110 if (oplock_request
) {
1111 oplock_request
|= (flags
& REQUEST_BATCH_OPLOCK
) ? BATCH_OPLOCK
: 0;
1115 return_additional_info
= BITSETW(params
,0);
1116 open_sattr
= SVAL(params
, 4);
1117 open_time
= make_unix_date3(params
+8);
1119 open_ofun
= SVAL(params
,12);
1120 open_size
= IVAL(params
,14);
1121 pname
= ¶ms
[28];
1124 reply_nterror(req
, NT_STATUS_NETWORK_ACCESS_DENIED
);
1128 srvstr_get_path(ctx
, params
, req
->flags2
, &fname
, pname
,
1129 total_params
- 28, STR_TERMINATE
,
1131 if (!NT_STATUS_IS_OK(status
)) {
1132 reply_nterror(req
, status
);
1136 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
1137 fname
, (unsigned int)deny_mode
, (unsigned int)open_attr
,
1138 (unsigned int)open_ofun
, open_size
));
1140 status
= filename_convert(ctx
,
1142 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
1147 if (!NT_STATUS_IS_OK(status
)) {
1148 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
1149 reply_botherror(req
,
1150 NT_STATUS_PATH_NOT_COVERED
,
1151 ERRSRV
, ERRbadpath
);
1154 reply_nterror(req
, status
);
1158 if (open_ofun
== 0) {
1159 reply_nterror(req
, NT_STATUS_OBJECT_NAME_COLLISION
);
1163 if (!map_open_params_to_ntcreate(smb_fname
->base_name
, deny_mode
,
1165 &access_mask
, &share_mode
,
1166 &create_disposition
,
1169 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
1173 /* Any data in this call is an EA list. */
1174 if (total_data
&& (total_data
!= 4)) {
1175 if (total_data
< 10) {
1176 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1180 if (IVAL(pdata
,0) > total_data
) {
1181 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
1182 IVAL(pdata
,0), (unsigned int)total_data
));
1183 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1187 ea_list
= read_ea_list(talloc_tos(), pdata
+ 4,
1190 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1194 if (!lp_ea_support(SNUM(conn
))) {
1195 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
1199 if (ea_list_has_invalid_name(ea_list
)) {
1201 *pparams
= (char *)SMB_REALLOC(*pparams
, param_len
);
1202 if(*pparams
== NULL
) {
1203 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1207 memset(params
, '\0', param_len
);
1208 send_trans2_replies(conn
, req
, STATUS_INVALID_EA_NAME
,
1209 params
, param_len
, NULL
, 0, max_data_bytes
);
1214 status
= SMB_VFS_CREATE_FILE(
1217 0, /* root_dir_fid */
1218 smb_fname
, /* fname */
1219 access_mask
, /* access_mask */
1220 share_mode
, /* share_access */
1221 create_disposition
, /* create_disposition*/
1222 create_options
, /* create_options */
1223 open_attr
, /* file_attributes */
1224 oplock_request
, /* oplock_request */
1226 open_size
, /* allocation_size */
1229 ea_list
, /* ea_list */
1231 &smb_action
, /* psbuf */
1232 NULL
, NULL
); /* create context */
1234 if (!NT_STATUS_IS_OK(status
)) {
1235 if (open_was_deferred(req
->xconn
, req
->mid
)) {
1236 /* We have re-scheduled this call. */
1239 reply_openerror(req
, status
);
1243 size
= get_file_size_stat(&smb_fname
->st
);
1244 fattr
= dos_mode(conn
, smb_fname
);
1245 mtime
= convert_timespec_to_time_t(smb_fname
->st
.st_ex_mtime
);
1246 inode
= smb_fname
->st
.st_ex_ino
;
1247 if (fattr
& FILE_ATTRIBUTE_DIRECTORY
) {
1248 close_file(req
, fsp
, ERROR_CLOSE
);
1249 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
1253 /* Realloc the size of parameters and data we will return */
1254 *pparams
= (char *)SMB_REALLOC(*pparams
, 30);
1255 if(*pparams
== NULL
) {
1256 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1261 SSVAL(params
,0,fsp
->fnum
);
1262 SSVAL(params
,2,fattr
);
1263 srv_put_dos_date2(params
,4, mtime
);
1264 SIVAL(params
,8, (uint32
)size
);
1265 SSVAL(params
,12,deny_mode
);
1266 SSVAL(params
,14,0); /* open_type - file or directory. */
1267 SSVAL(params
,16,0); /* open_state - only valid for IPC device. */
1269 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
1270 smb_action
|= EXTENDED_OPLOCK_GRANTED
;
1273 SSVAL(params
,18,smb_action
);
1276 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1278 SIVAL(params
,20,inode
);
1279 SSVAL(params
,24,0); /* Padding. */
1281 uint32 ea_size
= estimate_ea_size(conn
, fsp
,
1283 SIVAL(params
, 26, ea_size
);
1285 SIVAL(params
, 26, 0);
1288 /* Send the required number of replies */
1289 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 30, *ppdata
, 0, max_data_bytes
);
1291 TALLOC_FREE(smb_fname
);
1294 /*********************************************************
1295 Routine to check if a given string matches exactly.
1296 as a special case a mask of "." does NOT match. That
1297 is required for correct wildcard semantics
1298 Case can be significant or not.
1299 **********************************************************/
1301 static bool exact_match(bool has_wild
,
1302 bool case_sensitive
,
1306 if (mask
[0] == '.' && mask
[1] == 0) {
1314 if (case_sensitive
) {
1315 return strcmp(str
,mask
)==0;
1317 return strcasecmp_m(str
,mask
) == 0;
1321 /****************************************************************************
1322 Return the filetype for UNIX extensions.
1323 ****************************************************************************/
1325 static uint32
unix_filetype(mode_t mode
)
1328 return UNIX_TYPE_FILE
;
1329 else if(S_ISDIR(mode
))
1330 return UNIX_TYPE_DIR
;
1332 else if(S_ISLNK(mode
))
1333 return UNIX_TYPE_SYMLINK
;
1336 else if(S_ISCHR(mode
))
1337 return UNIX_TYPE_CHARDEV
;
1340 else if(S_ISBLK(mode
))
1341 return UNIX_TYPE_BLKDEV
;
1344 else if(S_ISFIFO(mode
))
1345 return UNIX_TYPE_FIFO
;
1348 else if(S_ISSOCK(mode
))
1349 return UNIX_TYPE_SOCKET
;
1352 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode
));
1353 return UNIX_TYPE_UNKNOWN
;
1356 /****************************************************************************
1357 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1358 ****************************************************************************/
1360 enum perm_type
{ PERM_NEW_FILE
, PERM_NEW_DIR
, PERM_EXISTING_FILE
, PERM_EXISTING_DIR
};
1362 static NTSTATUS
unix_perms_from_wire( connection_struct
*conn
,
1363 const SMB_STRUCT_STAT
*psbuf
,
1365 enum perm_type ptype
,
1370 if (perms
== SMB_MODE_NO_CHANGE
) {
1371 if (!VALID_STAT(*psbuf
)) {
1372 return NT_STATUS_INVALID_PARAMETER
;
1374 *ret_perms
= psbuf
->st_ex_mode
;
1375 return NT_STATUS_OK
;
1379 ret
|= ((perms
& UNIX_X_OTH
) ? S_IXOTH
: 0);
1380 ret
|= ((perms
& UNIX_W_OTH
) ? S_IWOTH
: 0);
1381 ret
|= ((perms
& UNIX_R_OTH
) ? S_IROTH
: 0);
1382 ret
|= ((perms
& UNIX_X_GRP
) ? S_IXGRP
: 0);
1383 ret
|= ((perms
& UNIX_W_GRP
) ? S_IWGRP
: 0);
1384 ret
|= ((perms
& UNIX_R_GRP
) ? S_IRGRP
: 0);
1385 ret
|= ((perms
& UNIX_X_USR
) ? S_IXUSR
: 0);
1386 ret
|= ((perms
& UNIX_W_USR
) ? S_IWUSR
: 0);
1387 ret
|= ((perms
& UNIX_R_USR
) ? S_IRUSR
: 0);
1389 ret
|= ((perms
& UNIX_STICKY
) ? S_ISVTX
: 0);
1392 ret
|= ((perms
& UNIX_SET_GID
) ? S_ISGID
: 0);
1395 ret
|= ((perms
& UNIX_SET_UID
) ? S_ISUID
: 0);
1398 if (ptype
== PERM_NEW_FILE
) {
1400 * "create mask"/"force create mode" are
1401 * only applied to new files, not existing ones.
1403 ret
&= lp_create_mask(SNUM(conn
));
1404 /* Add in force bits */
1405 ret
|= lp_force_create_mode(SNUM(conn
));
1406 } else if (ptype
== PERM_NEW_DIR
) {
1408 * "directory mask"/"force directory mode" are
1409 * only applied to new directories, not existing ones.
1411 ret
&= lp_directory_mask(SNUM(conn
));
1412 /* Add in force bits */
1413 ret
|= lp_force_directory_mode(SNUM(conn
));
1417 return NT_STATUS_OK
;
1420 /****************************************************************************
1421 Needed to show the msdfs symlinks as directories. Modifies psbuf
1422 to be a directory if it's a msdfs link.
1423 ****************************************************************************/
1425 static bool check_msdfs_link(connection_struct
*conn
,
1426 const char *pathname
,
1427 SMB_STRUCT_STAT
*psbuf
)
1429 int saved_errno
= errno
;
1430 if(lp_host_msdfs() &&
1431 lp_msdfs_root(SNUM(conn
)) &&
1432 is_msdfs_link(conn
, pathname
, psbuf
)) {
1434 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1437 psbuf
->st_ex_mode
= (psbuf
->st_ex_mode
& 0xFFF) | S_IFDIR
;
1438 errno
= saved_errno
;
1441 errno
= saved_errno
;
1446 /****************************************************************************
1447 Get a level dependent lanman2 dir entry.
1448 ****************************************************************************/
1450 struct smbd_dirptr_lanman2_state
{
1451 connection_struct
*conn
;
1452 uint32_t info_level
;
1453 bool check_mangled_names
;
1455 bool got_exact_match
;
1458 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX
*ctx
,
1464 struct smbd_dirptr_lanman2_state
*state
=
1465 (struct smbd_dirptr_lanman2_state
*)private_data
;
1467 char mangled_name
[13]; /* mangled 8.3 name. */
1471 /* Mangle fname if it's an illegal name. */
1472 if (mangle_must_mangle(dname
, state
->conn
->params
)) {
1474 * Slow path - ensure we can push the original name as UCS2. If
1475 * not, then just don't return this name.
1479 size_t len
= (strlen(dname
) + 2) * 4; /* Allow enough space. */
1480 uint8_t *tmp
= talloc_array(talloc_tos(),
1484 status
= srvstr_push(NULL
,
1485 FLAGS2_UNICODE_STRINGS
,
1494 if (!NT_STATUS_IS_OK(status
)) {
1498 ok
= name_to_8_3(dname
, mangled_name
,
1499 true, state
->conn
->params
);
1503 fname
= mangled_name
;
1508 got_match
= exact_match(state
->has_wild
,
1509 state
->conn
->case_sensitive
,
1511 state
->got_exact_match
= got_match
;
1513 got_match
= mask_match(fname
, mask
,
1514 state
->conn
->case_sensitive
);
1517 if(!got_match
&& state
->check_mangled_names
&&
1518 !mangle_is_8_3(fname
, false, state
->conn
->params
)) {
1520 * It turns out that NT matches wildcards against
1521 * both long *and* short names. This may explain some
1522 * of the wildcard wierdness from old DOS clients
1523 * that some people have been seeing.... JRA.
1525 /* Force the mangling into 8.3. */
1526 ok
= name_to_8_3(fname
, mangled_name
,
1527 false, state
->conn
->params
);
1532 got_match
= exact_match(state
->has_wild
,
1533 state
->conn
->case_sensitive
,
1534 mangled_name
, mask
);
1535 state
->got_exact_match
= got_match
;
1537 got_match
= mask_match(mangled_name
, mask
,
1538 state
->conn
->case_sensitive
);
1546 *_fname
= talloc_strdup(ctx
, fname
);
1547 if (*_fname
== NULL
) {
1554 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX
*ctx
,
1556 struct smb_filename
*smb_fname
,
1559 struct smbd_dirptr_lanman2_state
*state
=
1560 (struct smbd_dirptr_lanman2_state
*)private_data
;
1561 bool ms_dfs_link
= false;
1564 if (INFO_LEVEL_IS_UNIX(state
->info_level
)) {
1565 if (SMB_VFS_LSTAT(state
->conn
, smb_fname
) != 0) {
1566 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1567 "Couldn't lstat [%s] (%s)\n",
1568 smb_fname_str_dbg(smb_fname
),
1572 } else if (!VALID_STAT(smb_fname
->st
) &&
1573 SMB_VFS_STAT(state
->conn
, smb_fname
) != 0) {
1574 /* Needed to show the msdfs symlinks as
1577 ms_dfs_link
= check_msdfs_link(state
->conn
,
1578 smb_fname
->base_name
,
1581 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1582 "Couldn't stat [%s] (%s)\n",
1583 smb_fname_str_dbg(smb_fname
),
1590 mode
= dos_mode_msdfs(state
->conn
, smb_fname
);
1592 mode
= dos_mode(state
->conn
, smb_fname
);
1599 static NTSTATUS
smbd_marshall_dir_entry(TALLOC_CTX
*ctx
,
1600 connection_struct
*conn
,
1602 uint32_t info_level
,
1603 struct ea_list
*name_list
,
1604 bool check_mangled_names
,
1605 bool requires_resume_key
,
1608 const struct smb_filename
*smb_fname
,
1609 int space_remaining
,
1615 uint64_t *last_entry_off
)
1617 char *p
, *q
, *pdata
= *ppdata
;
1619 uint64_t file_size
= 0;
1620 uint64_t allocation_size
= 0;
1621 uint64_t file_index
= 0;
1623 struct timespec mdate_ts
, adate_ts
, cdate_ts
, create_date_ts
;
1624 time_t mdate
= (time_t)0, adate
= (time_t)0, create_date
= (time_t)0;
1626 char *last_entry_ptr
;
1631 struct readdir_attr_data
*readdir_attr_data
= NULL
;
1633 ZERO_STRUCT(mdate_ts
);
1634 ZERO_STRUCT(adate_ts
);
1635 ZERO_STRUCT(create_date_ts
);
1636 ZERO_STRUCT(cdate_ts
);
1638 if (!(mode
& FILE_ATTRIBUTE_DIRECTORY
)) {
1639 file_size
= get_file_size_stat(&smb_fname
->st
);
1641 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
, NULL
, &smb_fname
->st
);
1643 status
= SMB_VFS_READDIR_ATTR(conn
, smb_fname
, ctx
, &readdir_attr_data
);
1644 if (!NT_STATUS_IS_OK(status
)) {
1645 if (!NT_STATUS_EQUAL(NT_STATUS_NOT_SUPPORTED
, status
)) {
1650 file_index
= get_FileIndex(conn
, &smb_fname
->st
);
1652 mdate_ts
= smb_fname
->st
.st_ex_mtime
;
1653 adate_ts
= smb_fname
->st
.st_ex_atime
;
1654 create_date_ts
= get_create_timespec(conn
, NULL
, smb_fname
);
1655 cdate_ts
= get_change_timespec(conn
, NULL
, smb_fname
);
1657 if (lp_dos_filetime_resolution(SNUM(conn
))) {
1658 dos_filetime_timespec(&create_date_ts
);
1659 dos_filetime_timespec(&mdate_ts
);
1660 dos_filetime_timespec(&adate_ts
);
1661 dos_filetime_timespec(&cdate_ts
);
1664 create_date
= convert_timespec_to_time_t(create_date_ts
);
1665 mdate
= convert_timespec_to_time_t(mdate_ts
);
1666 adate
= convert_timespec_to_time_t(adate_ts
);
1668 /* align the record */
1669 SMB_ASSERT(align
>= 1);
1671 off
= (int)PTR_DIFF(pdata
, base_data
);
1672 pad
= (off
+ (align
-1)) & ~(align
-1);
1675 if (pad
&& pad
> space_remaining
) {
1676 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1677 "for padding (wanted %u, had %d)\n",
1680 return STATUS_MORE_ENTRIES
; /* Not finished - just out of space */
1684 /* initialize padding to 0 */
1686 memset(pdata
, 0, pad
);
1688 space_remaining
-= pad
;
1690 DEBUG(10,("smbd_marshall_dir_entry: space_remaining = %d\n",
1700 switch (info_level
) {
1701 case SMB_FIND_INFO_STANDARD
:
1702 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1703 if(requires_resume_key
) {
1707 srv_put_dos_date2(p
,0,create_date
);
1708 srv_put_dos_date2(p
,4,adate
);
1709 srv_put_dos_date2(p
,8,mdate
);
1710 SIVAL(p
,12,(uint32
)file_size
);
1711 SIVAL(p
,16,(uint32
)allocation_size
);
1715 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1716 p
+= ucs2_align(base_data
, p
, 0);
1718 status
= srvstr_push(base_data
, flags2
, p
,
1719 fname
, PTR_DIFF(end_data
, p
),
1720 STR_TERMINATE
, &len
);
1721 if (!NT_STATUS_IS_OK(status
)) {
1724 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1726 SCVAL(nameptr
, -1, len
- 2);
1728 SCVAL(nameptr
, -1, 0);
1732 SCVAL(nameptr
, -1, len
- 1);
1734 SCVAL(nameptr
, -1, 0);
1740 case SMB_FIND_EA_SIZE
:
1741 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
1742 if (requires_resume_key
) {
1746 srv_put_dos_date2(p
,0,create_date
);
1747 srv_put_dos_date2(p
,4,adate
);
1748 srv_put_dos_date2(p
,8,mdate
);
1749 SIVAL(p
,12,(uint32
)file_size
);
1750 SIVAL(p
,16,(uint32
)allocation_size
);
1753 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
1755 SIVAL(p
,22,ea_size
); /* Extended attributes */
1759 status
= srvstr_push(base_data
, flags2
,
1760 p
, fname
, PTR_DIFF(end_data
, p
),
1761 STR_TERMINATE
| STR_NOALIGN
, &len
);
1762 if (!NT_STATUS_IS_OK(status
)) {
1765 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1778 SCVAL(nameptr
,0,len
);
1780 SCVAL(p
,0,0); p
+= 1; /* Extra zero byte ? - why.. */
1783 case SMB_FIND_EA_LIST
:
1785 struct ea_list
*file_list
= NULL
;
1788 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
1790 return NT_STATUS_INVALID_PARAMETER
;
1792 if (requires_resume_key
) {
1796 srv_put_dos_date2(p
,0,create_date
);
1797 srv_put_dos_date2(p
,4,adate
);
1798 srv_put_dos_date2(p
,8,mdate
);
1799 SIVAL(p
,12,(uint32
)file_size
);
1800 SIVAL(p
,16,(uint32
)allocation_size
);
1802 p
+= 22; /* p now points to the EA area. */
1804 status
= get_ea_list_from_file(ctx
, conn
, NULL
,
1806 &ea_len
, &file_list
);
1807 if (!NT_STATUS_IS_OK(status
)) {
1810 name_list
= ea_list_union(name_list
, file_list
, &ea_len
);
1812 /* We need to determine if this entry will fit in the space available. */
1813 /* Max string size is 255 bytes. */
1814 if (PTR_DIFF(p
+ 255 + ea_len
,pdata
) > space_remaining
) {
1815 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1816 "(wanted %u, had %d)\n",
1817 (unsigned int)PTR_DIFF(p
+ 255 + ea_len
,pdata
),
1819 return STATUS_MORE_ENTRIES
; /* Not finished - just out of space */
1822 /* Push the ea_data followed by the name. */
1823 p
+= fill_ea_buffer(ctx
, p
, space_remaining
, conn
, name_list
);
1825 status
= srvstr_push(base_data
, flags2
,
1826 p
+ 1, fname
, PTR_DIFF(end_data
, p
+1),
1827 STR_TERMINATE
| STR_NOALIGN
, &len
);
1828 if (!NT_STATUS_IS_OK(status
)) {
1831 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1844 SCVAL(nameptr
,0,len
);
1846 SCVAL(p
,0,0); p
+= 1; /* Extra zero byte ? - why.. */
1850 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
1851 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1852 was_8_3
= mangle_is_8_3(fname
, True
, conn
->params
);
1854 SIVAL(p
,0,reskey
); p
+= 4;
1855 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
1856 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
1857 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
1858 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
1859 SOFF_T(p
,0,file_size
); p
+= 8;
1860 SOFF_T(p
,0,allocation_size
); p
+= 8;
1861 SIVAL(p
,0,mode
); p
+= 4;
1862 q
= p
; p
+= 4; /* q is placeholder for name length. */
1863 if (mode
& FILE_ATTRIBUTE_REPARSE_POINT
) {
1864 SIVAL(p
, 0, IO_REPARSE_TAG_DFS
);
1866 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
1868 SIVAL(p
,0,ea_size
); /* Extended attributes */
1871 /* Clear the short name buffer. This is
1872 * IMPORTANT as not doing so will trigger
1873 * a Win2k client bug. JRA.
1875 if (!was_8_3
&& check_mangled_names
) {
1876 char mangled_name
[13]; /* mangled 8.3 name. */
1877 if (!name_to_8_3(fname
,mangled_name
,True
,
1879 /* Error - mangle failed ! */
1880 memset(mangled_name
,'\0',12);
1882 mangled_name
[12] = 0;
1883 status
= srvstr_push(base_data
, flags2
,
1884 p
+2, mangled_name
, 24,
1885 STR_UPPER
|STR_UNICODE
, &len
);
1886 if (!NT_STATUS_IS_OK(status
)) {
1890 memset(p
+ 2 + len
,'\0',24 - len
);
1897 status
= srvstr_push(base_data
, flags2
, p
,
1898 fname
, PTR_DIFF(end_data
, p
),
1899 STR_TERMINATE_ASCII
, &len
);
1900 if (!NT_STATUS_IS_OK(status
)) {
1906 len
= PTR_DIFF(p
, pdata
);
1907 pad
= (len
+ (align
-1)) & ~(align
-1);
1909 * offset to the next entry, the caller
1910 * will overwrite it for the last entry
1911 * that's why we always include the padding
1915 * set padding to zero
1918 memset(p
, 0, pad
- len
);
1925 case SMB_FIND_FILE_DIRECTORY_INFO
:
1926 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1928 SIVAL(p
,0,reskey
); p
+= 4;
1929 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
1930 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
1931 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
1932 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
1933 SOFF_T(p
,0,file_size
); p
+= 8;
1934 SOFF_T(p
,0,allocation_size
); p
+= 8;
1935 SIVAL(p
,0,mode
); p
+= 4;
1936 status
= srvstr_push(base_data
, flags2
,
1937 p
+ 4, fname
, PTR_DIFF(end_data
, p
+4),
1938 STR_TERMINATE_ASCII
, &len
);
1939 if (!NT_STATUS_IS_OK(status
)) {
1945 len
= PTR_DIFF(p
, pdata
);
1946 pad
= (len
+ (align
-1)) & ~(align
-1);
1948 * offset to the next entry, the caller
1949 * will overwrite it for the last entry
1950 * that's why we always include the padding
1954 * set padding to zero
1957 memset(p
, 0, pad
- len
);
1964 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
1965 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1967 SIVAL(p
,0,reskey
); p
+= 4;
1968 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
1969 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
1970 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
1971 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
1972 SOFF_T(p
,0,file_size
); p
+= 8;
1973 SOFF_T(p
,0,allocation_size
); p
+= 8;
1974 SIVAL(p
,0,mode
); p
+= 4;
1975 q
= p
; p
+= 4; /* q is placeholder for name length. */
1977 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
1979 SIVAL(p
,0,ea_size
); /* Extended attributes */
1982 status
= srvstr_push(base_data
, flags2
, p
,
1983 fname
, PTR_DIFF(end_data
, p
),
1984 STR_TERMINATE_ASCII
, &len
);
1985 if (!NT_STATUS_IS_OK(status
)) {
1991 len
= PTR_DIFF(p
, pdata
);
1992 pad
= (len
+ (align
-1)) & ~(align
-1);
1994 * offset to the next entry, the caller
1995 * will overwrite it for the last entry
1996 * that's why we always include the padding
2000 * set padding to zero
2003 memset(p
, 0, pad
- len
);
2010 case SMB_FIND_FILE_NAMES_INFO
:
2011 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
2013 SIVAL(p
,0,reskey
); p
+= 4;
2015 /* this must *not* be null terminated or w2k gets in a loop trying to set an
2016 acl on a dir (tridge) */
2017 status
= srvstr_push(base_data
, flags2
, p
,
2018 fname
, PTR_DIFF(end_data
, p
),
2019 STR_TERMINATE_ASCII
, &len
);
2020 if (!NT_STATUS_IS_OK(status
)) {
2026 len
= PTR_DIFF(p
, pdata
);
2027 pad
= (len
+ (align
-1)) & ~(align
-1);
2029 * offset to the next entry, the caller
2030 * will overwrite it for the last entry
2031 * that's why we always include the padding
2035 * set padding to zero
2038 memset(p
, 0, pad
- len
);
2045 case SMB_FIND_ID_FULL_DIRECTORY_INFO
:
2046 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
2048 SIVAL(p
,0,reskey
); p
+= 4;
2049 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
2050 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
2051 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
2052 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
2053 SOFF_T(p
,0,file_size
); p
+= 8;
2054 SOFF_T(p
,0,allocation_size
); p
+= 8;
2055 SIVAL(p
,0,mode
); p
+= 4;
2056 q
= p
; p
+= 4; /* q is placeholder for name length. */
2057 if (mode
& FILE_ATTRIBUTE_REPARSE_POINT
) {
2058 SIVAL(p
, 0, IO_REPARSE_TAG_DFS
);
2060 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
2062 SIVAL(p
,0,ea_size
); /* Extended attributes */
2065 SIVAL(p
,0,0); p
+= 4; /* Unknown - reserved ? */
2066 SBVAL(p
,0,file_index
); p
+= 8;
2067 status
= srvstr_push(base_data
, flags2
, p
,
2068 fname
, PTR_DIFF(end_data
, p
),
2069 STR_TERMINATE_ASCII
, &len
);
2070 if (!NT_STATUS_IS_OK(status
)) {
2076 len
= PTR_DIFF(p
, pdata
);
2077 pad
= (len
+ (align
-1)) & ~(align
-1);
2079 * offset to the next entry, the caller
2080 * will overwrite it for the last entry
2081 * that's why we always include the padding
2085 * set padding to zero
2088 memset(p
, 0, pad
- len
);
2095 case SMB_FIND_ID_BOTH_DIRECTORY_INFO
:
2096 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
2097 was_8_3
= mangle_is_8_3(fname
, True
, conn
->params
);
2099 SIVAL(p
,0,reskey
); p
+= 4;
2100 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
2101 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
2102 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
2103 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
2104 SOFF_T(p
,0,file_size
); p
+= 8;
2105 SOFF_T(p
,0,allocation_size
); p
+= 8;
2106 SIVAL(p
,0,mode
); p
+= 4;
2107 q
= p
; p
+= 4; /* q is placeholder for name length */
2108 if (mode
& FILE_ATTRIBUTE_REPARSE_POINT
) {
2109 SIVAL(p
, 0, IO_REPARSE_TAG_DFS
);
2110 } else if (readdir_attr_data
&&
2111 readdir_attr_data
->type
== RDATTR_AAPL
) {
2113 * OS X specific SMB2 extension negotiated via
2114 * AAPL create context: return max_access in
2117 SIVAL(p
, 0, readdir_attr_data
->attr_data
.aapl
.max_access
);
2119 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
2121 SIVAL(p
,0,ea_size
); /* Extended attributes */
2125 if (readdir_attr_data
&&
2126 readdir_attr_data
->type
== RDATTR_AAPL
) {
2128 * OS X specific SMB2 extension negotiated via
2129 * AAPL create context: return resource fork
2130 * length and compressed FinderInfo in
2133 * According to documentation short_name_len
2134 * should be 0, but on the wire behaviour
2135 * shows its set to 24 by clients.
2139 /* Resourefork length */
2140 SBVAL(p
, 2, readdir_attr_data
->attr_data
.aapl
.rfork_size
);
2142 /* Compressed FinderInfo */
2143 memcpy(p
+ 10, &readdir_attr_data
->attr_data
.aapl
.finder_info
, 16);
2144 } else if (!was_8_3
&& check_mangled_names
) {
2145 char mangled_name
[13]; /* mangled 8.3 name. */
2146 if (!name_to_8_3(fname
,mangled_name
,True
,
2148 /* Error - mangle failed ! */
2149 memset(mangled_name
,'\0',12);
2151 mangled_name
[12] = 0;
2152 status
= srvstr_push(base_data
, flags2
,
2153 p
+2, mangled_name
, 24,
2154 STR_UPPER
|STR_UNICODE
, &len
);
2155 if (!NT_STATUS_IS_OK(status
)) {
2160 memset(p
+ 2 + len
,'\0',24 - len
);
2164 /* Clear the short name buffer. This is
2165 * IMPORTANT as not doing so will trigger
2166 * a Win2k client bug. JRA.
2173 if (readdir_attr_data
&&
2174 readdir_attr_data
->type
== RDATTR_AAPL
) {
2176 * OS X specific SMB2 extension negotiated via
2177 * AAPL create context: return UNIX mode in
2180 uint16_t aapl_mode
= (uint16_t)readdir_attr_data
->attr_data
.aapl
.unix_mode
;
2181 SSVAL(p
, 0, aapl_mode
);
2187 SBVAL(p
,0,file_index
); p
+= 8;
2188 status
= srvstr_push(base_data
, flags2
, p
,
2189 fname
, PTR_DIFF(end_data
, p
),
2190 STR_TERMINATE_ASCII
, &len
);
2191 if (!NT_STATUS_IS_OK(status
)) {
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
);
2216 /* CIFS UNIX Extension. */
2218 case SMB_FIND_FILE_UNIX
:
2219 case SMB_FIND_FILE_UNIX_INFO2
:
2221 SIVAL(p
,0,reskey
); p
+= 4; /* Used for continuing search. */
2223 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
2225 if (info_level
== SMB_FIND_FILE_UNIX
) {
2226 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
2227 p
= store_file_unix_basic(conn
, p
,
2228 NULL
, &smb_fname
->st
);
2229 status
= srvstr_push(base_data
, flags2
, p
,
2230 fname
, PTR_DIFF(end_data
, p
),
2231 STR_TERMINATE
, &len
);
2232 if (!NT_STATUS_IS_OK(status
)) {
2236 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
2237 p
= store_file_unix_basic_info2(conn
, p
,
2238 NULL
, &smb_fname
->st
);
2241 status
= srvstr_push(base_data
, flags2
, p
, fname
,
2242 PTR_DIFF(end_data
, p
), 0, &len
);
2243 if (!NT_STATUS_IS_OK(status
)) {
2246 SIVAL(nameptr
, 0, len
);
2251 len
= PTR_DIFF(p
, pdata
);
2252 pad
= (len
+ (align
-1)) & ~(align
-1);
2254 * offset to the next entry, the caller
2255 * will overwrite it for the last entry
2256 * that's why we always include the padding
2260 * set padding to zero
2263 memset(p
, 0, pad
- len
);
2268 /* End of SMB_QUERY_FILE_UNIX_BASIC */
2273 return NT_STATUS_INVALID_LEVEL
;
2276 if (PTR_DIFF(p
,pdata
) > space_remaining
) {
2277 DEBUG(9,("smbd_marshall_dir_entry: out of space "
2278 "(wanted %u, had %d)\n",
2279 (unsigned int)PTR_DIFF(p
,pdata
),
2281 return STATUS_MORE_ENTRIES
; /* Not finished - just out of space */
2284 /* Setup the last entry pointer, as an offset from base_data */
2285 *last_entry_off
= PTR_DIFF(last_entry_ptr
,base_data
);
2286 /* Advance the data pointer to the next slot */
2289 return NT_STATUS_OK
;
2292 NTSTATUS
smbd_dirptr_lanman2_entry(TALLOC_CTX
*ctx
,
2293 connection_struct
*conn
,
2294 struct dptr_struct
*dirptr
,
2296 const char *path_mask
,
2299 int requires_resume_key
,
2307 int space_remaining
,
2308 bool *got_exact_match
,
2309 int *_last_entry_off
,
2310 struct ea_list
*name_list
)
2313 const char *mask
= NULL
;
2314 long prev_dirpos
= 0;
2317 struct smb_filename
*smb_fname
= NULL
;
2318 struct smbd_dirptr_lanman2_state state
;
2320 uint64_t last_entry_off
= 0;
2325 state
.info_level
= info_level
;
2326 state
.check_mangled_names
= lp_mangled_names(conn
->params
);
2327 state
.has_wild
= dptr_has_wild(dirptr
);
2328 state
.got_exact_match
= false;
2330 *got_exact_match
= false;
2332 p
= strrchr_m(path_mask
,'/');
2343 ok
= smbd_dirptr_get_entry(ctx
,
2349 smbd_dirptr_lanman2_match_fn
,
2350 smbd_dirptr_lanman2_mode_fn
,
2357 return NT_STATUS_END_OF_FILE
;
2360 *got_exact_match
= state
.got_exact_match
;
2362 status
= smbd_marshall_dir_entry(ctx
,
2367 state
.check_mangled_names
,
2368 requires_resume_key
,
2380 TALLOC_FREE(smb_fname
);
2381 if (NT_STATUS_EQUAL(status
, STATUS_MORE_ENTRIES
)) {
2382 dptr_SeekDir(dirptr
, prev_dirpos
);
2385 if (!NT_STATUS_IS_OK(status
)) {
2389 *_last_entry_off
= last_entry_off
;
2390 return NT_STATUS_OK
;
2393 static NTSTATUS
get_lanman2_dir_entry(TALLOC_CTX
*ctx
,
2394 connection_struct
*conn
,
2395 struct dptr_struct
*dirptr
,
2397 const char *path_mask
,
2400 bool requires_resume_key
,
2406 int space_remaining
,
2407 bool *got_exact_match
,
2408 int *last_entry_off
,
2409 struct ea_list
*name_list
)
2412 const bool do_pad
= true;
2414 if (info_level
>= 1 && info_level
<= 3) {
2415 /* No alignment on earlier info levels. */
2419 return smbd_dirptr_lanman2_entry(ctx
, conn
, dirptr
, flags2
,
2420 path_mask
, dirtype
, info_level
,
2421 requires_resume_key
, dont_descend
, ask_sharemode
,
2423 ppdata
, base_data
, end_data
,
2426 last_entry_off
, name_list
);
2429 /****************************************************************************
2430 Reply to a TRANS2_FINDFIRST.
2431 ****************************************************************************/
2433 static void call_trans2findfirst(connection_struct
*conn
,
2434 struct smb_request
*req
,
2435 char **pparams
, int total_params
,
2436 char **ppdata
, int total_data
,
2437 unsigned int max_data_bytes
)
2439 /* We must be careful here that we don't return more than the
2440 allowed number of data bytes. If this means returning fewer than
2441 maxentries then so be it. We assume that the redirector has
2442 enough room for the fixed number of parameter bytes it has
2444 struct smb_filename
*smb_dname
= NULL
;
2445 char *params
= *pparams
;
2446 char *pdata
= *ppdata
;
2450 uint16 findfirst_flags
;
2451 bool close_after_first
;
2453 bool requires_resume_key
;
2455 char *directory
= NULL
;
2458 int last_entry_off
=0;
2462 bool finished
= False
;
2463 bool dont_descend
= False
;
2464 bool out_of_space
= False
;
2465 int space_remaining
;
2466 bool mask_contains_wcard
= False
;
2467 struct ea_list
*ea_list
= NULL
;
2468 NTSTATUS ntstatus
= NT_STATUS_OK
;
2469 bool ask_sharemode
= lp_parm_bool(SNUM(conn
), "smbd", "search ask sharemode", true);
2470 TALLOC_CTX
*ctx
= talloc_tos();
2471 struct dptr_struct
*dirptr
= NULL
;
2472 struct smbd_server_connection
*sconn
= req
->sconn
;
2473 uint32_t ucf_flags
= (UCF_SAVE_LCOMP
| UCF_ALWAYS_ALLOW_WCARD_LCOMP
);
2474 bool backup_priv
= false;
2476 if (total_params
< 13) {
2477 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2481 dirtype
= SVAL(params
,0);
2482 maxentries
= SVAL(params
,2);
2483 findfirst_flags
= SVAL(params
,4);
2484 close_after_first
= (findfirst_flags
& FLAG_TRANS2_FIND_CLOSE
);
2485 close_if_end
= (findfirst_flags
& FLAG_TRANS2_FIND_CLOSE_IF_END
);
2486 requires_resume_key
= (findfirst_flags
& FLAG_TRANS2_FIND_REQUIRE_RESUME
);
2487 backup_priv
= ((findfirst_flags
& FLAG_TRANS2_FIND_BACKUP_INTENT
) &&
2488 security_token_has_privilege(get_current_nttok(conn
),
2491 info_level
= SVAL(params
,6);
2493 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2494 close_if_end = %d requires_resume_key = %d backup_priv = %d level = 0x%x, max_data_bytes = %d\n",
2495 (unsigned int)dirtype
, maxentries
, close_after_first
, close_if_end
, requires_resume_key
,
2497 info_level
, max_data_bytes
));
2500 /* W2K3 seems to treat zero as 1. */
2504 switch (info_level
) {
2505 case SMB_FIND_INFO_STANDARD
:
2506 case SMB_FIND_EA_SIZE
:
2507 case SMB_FIND_EA_LIST
:
2508 case SMB_FIND_FILE_DIRECTORY_INFO
:
2509 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
2510 case SMB_FIND_FILE_NAMES_INFO
:
2511 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
2512 case SMB_FIND_ID_FULL_DIRECTORY_INFO
:
2513 case SMB_FIND_ID_BOTH_DIRECTORY_INFO
:
2515 case SMB_FIND_FILE_UNIX
:
2516 case SMB_FIND_FILE_UNIX_INFO2
:
2517 /* Always use filesystem for UNIX mtime query. */
2518 ask_sharemode
= false;
2519 if (!lp_unix_extensions()) {
2520 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2523 ucf_flags
|= UCF_UNIX_NAME_LOOKUP
;
2526 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2530 srvstr_get_path_wcard(ctx
, params
, req
->flags2
, &directory
,
2531 params
+12, total_params
- 12,
2532 STR_TERMINATE
, &ntstatus
, &mask_contains_wcard
);
2533 if (!NT_STATUS_IS_OK(ntstatus
)) {
2534 reply_nterror(req
, ntstatus
);
2540 ntstatus
= filename_convert_with_privilege(ctx
,
2545 &mask_contains_wcard
,
2548 ntstatus
= filename_convert(ctx
, conn
,
2549 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
2552 &mask_contains_wcard
,
2556 if (!NT_STATUS_IS_OK(ntstatus
)) {
2557 if (NT_STATUS_EQUAL(ntstatus
,NT_STATUS_PATH_NOT_COVERED
)) {
2558 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
2559 ERRSRV
, ERRbadpath
);
2562 reply_nterror(req
, ntstatus
);
2566 mask
= smb_dname
->original_lcomp
;
2568 directory
= smb_dname
->base_name
;
2570 p
= strrchr_m(directory
,'/');
2572 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2573 if((directory
[0] == '.') && (directory
[1] == '\0')) {
2574 mask
= talloc_strdup(ctx
,"*");
2576 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2579 mask_contains_wcard
= True
;
2585 if (p
== NULL
|| p
== directory
) {
2586 /* Ensure we don't have a directory name of "". */
2587 directory
= talloc_strdup(talloc_tos(), ".");
2589 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2594 DEBUG(5,("dir=%s, mask = %s\n",directory
, mask
));
2596 if (info_level
== SMB_FIND_EA_LIST
) {
2599 if (total_data
< 4) {
2600 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2604 ea_size
= IVAL(pdata
,0);
2605 if (ea_size
!= total_data
) {
2606 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2607 total_data=%u (should be %u)\n", (unsigned int)total_data
, (unsigned int)IVAL(pdata
,0) ));
2608 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2612 if (!lp_ea_support(SNUM(conn
))) {
2613 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
2617 /* Pull out the list of names. */
2618 ea_list
= read_ea_name_list(ctx
, pdata
+ 4, ea_size
- 4);
2620 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2625 if (max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
< max_data_bytes
) {
2626 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2630 *ppdata
= (char *)SMB_REALLOC(
2631 *ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
2632 if(*ppdata
== NULL
) {
2633 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2637 data_end
= pdata
+ max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
- 1;
2639 /* Realloc the params space */
2640 *pparams
= (char *)SMB_REALLOC(*pparams
, 10);
2641 if (*pparams
== NULL
) {
2642 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2647 /* Save the wildcard match and attribs we are using on this directory -
2648 needed as lanman2 assumes these are being saved between calls */
2650 ntstatus
= dptr_create(conn
,
2658 mask_contains_wcard
,
2662 if (!NT_STATUS_IS_OK(ntstatus
)) {
2663 reply_nterror(req
, ntstatus
);
2668 /* Remember this in case we have
2669 to do a findnext. */
2670 dptr_set_priv(dirptr
);
2673 dptr_num
= dptr_dnum(dirptr
);
2674 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num
, mask
, dirtype
));
2676 /* Initialize per TRANS2_FIND_FIRST operation data */
2677 dptr_init_search_op(dirptr
);
2679 /* We don't need to check for VOL here as this is returned by
2680 a different TRANS2 call. */
2682 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2683 directory
,lp_dont_descend(ctx
, SNUM(conn
))));
2684 if (in_list(directory
,lp_dont_descend(ctx
, SNUM(conn
)),conn
->case_sensitive
))
2685 dont_descend
= True
;
2688 space_remaining
= max_data_bytes
;
2689 out_of_space
= False
;
2691 for (i
=0;(i
<maxentries
) && !finished
&& !out_of_space
;i
++) {
2692 bool got_exact_match
= False
;
2694 /* this is a heuristic to avoid seeking the dirptr except when
2695 absolutely necessary. It allows for a filename of about 40 chars */
2696 if (space_remaining
< DIRLEN_GUESS
&& numentries
> 0) {
2697 out_of_space
= True
;
2700 ntstatus
= get_lanman2_dir_entry(ctx
,
2704 mask
,dirtype
,info_level
,
2705 requires_resume_key
,dont_descend
,
2710 &last_entry_off
, ea_list
);
2711 if (NT_STATUS_EQUAL(ntstatus
,
2712 NT_STATUS_ILLEGAL_CHARACTER
)) {
2714 * Bad character conversion on name. Ignore this
2719 if (NT_STATUS_EQUAL(ntstatus
, STATUS_MORE_ENTRIES
)) {
2720 out_of_space
= true;
2722 finished
= !NT_STATUS_IS_OK(ntstatus
);
2726 if (!finished
&& !out_of_space
)
2730 * As an optimisation if we know we aren't looking
2731 * for a wildcard name (ie. the name matches the wildcard exactly)
2732 * then we can finish on any (first) match.
2733 * This speeds up large directory searches. JRA.
2739 /* Ensure space_remaining never goes -ve. */
2740 if (PTR_DIFF(p
,pdata
) > max_data_bytes
) {
2741 space_remaining
= 0;
2742 out_of_space
= true;
2744 space_remaining
= max_data_bytes
- PTR_DIFF(p
,pdata
);
2748 /* Check if we can close the dirptr */
2749 if(close_after_first
|| (finished
&& close_if_end
)) {
2750 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num
));
2751 dptr_close(sconn
, &dptr_num
);
2755 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2756 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2757 * the protocol level is less than NT1. Tested with smbclient. JRA.
2758 * This should fix the OS/2 client bug #2335.
2761 if(numentries
== 0) {
2762 dptr_close(sconn
, &dptr_num
);
2763 if (get_Protocol() < PROTOCOL_NT1
) {
2764 reply_force_doserror(req
, ERRDOS
, ERRnofiles
);
2767 reply_botherror(req
, NT_STATUS_NO_SUCH_FILE
,
2768 ERRDOS
, ERRbadfile
);
2773 /* At this point pdata points to numentries directory entries. */
2775 /* Set up the return parameter block */
2776 SSVAL(params
,0,dptr_num
);
2777 SSVAL(params
,2,numentries
);
2778 SSVAL(params
,4,finished
);
2779 SSVAL(params
,6,0); /* Never an EA error */
2780 SSVAL(params
,8,last_entry_off
);
2782 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 10, pdata
, PTR_DIFF(p
,pdata
),
2785 if ((! *directory
) && dptr_path(sconn
, dptr_num
)) {
2786 directory
= talloc_strdup(talloc_tos(),dptr_path(sconn
, dptr_num
));
2788 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2792 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2793 smb_fn_name(req
->cmd
),
2794 mask
, directory
, dirtype
, numentries
) );
2797 * Force a name mangle here to ensure that the
2798 * mask as an 8.3 name is top of the mangled cache.
2799 * The reasons for this are subtle. Don't remove
2800 * this code unless you know what you are doing
2801 * (see PR#13758). JRA.
2804 if(!mangle_is_8_3_wildcards( mask
, False
, conn
->params
)) {
2805 char mangled_name
[13];
2806 name_to_8_3(mask
, mangled_name
, True
, conn
->params
);
2814 TALLOC_FREE(smb_dname
);
2818 /****************************************************************************
2819 Reply to a TRANS2_FINDNEXT.
2820 ****************************************************************************/
2822 static void call_trans2findnext(connection_struct
*conn
,
2823 struct smb_request
*req
,
2824 char **pparams
, int total_params
,
2825 char **ppdata
, int total_data
,
2826 unsigned int max_data_bytes
)
2828 /* We must be careful here that we don't return more than the
2829 allowed number of data bytes. If this means returning fewer than
2830 maxentries then so be it. We assume that the redirector has
2831 enough room for the fixed number of parameter bytes it has
2833 char *params
= *pparams
;
2834 char *pdata
= *ppdata
;
2840 uint16 findnext_flags
;
2841 bool close_after_request
;
2843 bool requires_resume_key
;
2845 bool mask_contains_wcard
= False
;
2846 char *resume_name
= NULL
;
2847 const char *mask
= NULL
;
2848 const char *directory
= NULL
;
2852 int i
, last_entry_off
=0;
2853 bool finished
= False
;
2854 bool dont_descend
= False
;
2855 bool out_of_space
= False
;
2856 int space_remaining
;
2857 struct ea_list
*ea_list
= NULL
;
2858 NTSTATUS ntstatus
= NT_STATUS_OK
;
2859 bool ask_sharemode
= lp_parm_bool(SNUM(conn
), "smbd", "search ask sharemode", true);
2860 TALLOC_CTX
*ctx
= talloc_tos();
2861 struct dptr_struct
*dirptr
;
2862 struct smbd_server_connection
*sconn
= req
->sconn
;
2863 bool backup_priv
= false;
2865 if (total_params
< 13) {
2866 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2870 dptr_num
= SVAL(params
,0);
2871 maxentries
= SVAL(params
,2);
2872 info_level
= SVAL(params
,4);
2873 resume_key
= IVAL(params
,6);
2874 findnext_flags
= SVAL(params
,10);
2875 close_after_request
= (findnext_flags
& FLAG_TRANS2_FIND_CLOSE
);
2876 close_if_end
= (findnext_flags
& FLAG_TRANS2_FIND_CLOSE_IF_END
);
2877 requires_resume_key
= (findnext_flags
& FLAG_TRANS2_FIND_REQUIRE_RESUME
);
2878 continue_bit
= (findnext_flags
& FLAG_TRANS2_FIND_CONTINUE
);
2880 if (!continue_bit
) {
2881 /* We only need resume_name if continue_bit is zero. */
2882 srvstr_get_path_wcard(ctx
, params
, req
->flags2
, &resume_name
,
2884 total_params
- 12, STR_TERMINATE
, &ntstatus
,
2885 &mask_contains_wcard
);
2886 if (!NT_STATUS_IS_OK(ntstatus
)) {
2887 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2888 complain (it thinks we're asking for the directory above the shared
2889 path or an invalid name). Catch this as the resume name is only compared, never used in
2890 a file access. JRA. */
2891 srvstr_pull_talloc(ctx
, params
, req
->flags2
,
2892 &resume_name
, params
+12,
2896 if (!resume_name
|| !(ISDOT(resume_name
) || ISDOTDOT(resume_name
))) {
2897 reply_nterror(req
, ntstatus
);
2903 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2904 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2905 resume_key = %d resume name = %s continue=%d level = %d\n",
2906 dptr_num
, max_data_bytes
, maxentries
, close_after_request
, close_if_end
,
2907 requires_resume_key
, resume_key
,
2908 resume_name
? resume_name
: "(NULL)", continue_bit
, info_level
));
2911 /* W2K3 seems to treat zero as 1. */
2915 switch (info_level
) {
2916 case SMB_FIND_INFO_STANDARD
:
2917 case SMB_FIND_EA_SIZE
:
2918 case SMB_FIND_EA_LIST
:
2919 case SMB_FIND_FILE_DIRECTORY_INFO
:
2920 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
2921 case SMB_FIND_FILE_NAMES_INFO
:
2922 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
2923 case SMB_FIND_ID_FULL_DIRECTORY_INFO
:
2924 case SMB_FIND_ID_BOTH_DIRECTORY_INFO
:
2926 case SMB_FIND_FILE_UNIX
:
2927 case SMB_FIND_FILE_UNIX_INFO2
:
2928 /* Always use filesystem for UNIX mtime query. */
2929 ask_sharemode
= false;
2930 if (!lp_unix_extensions()) {
2931 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2936 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2940 if (info_level
== SMB_FIND_EA_LIST
) {
2943 if (total_data
< 4) {
2944 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2948 ea_size
= IVAL(pdata
,0);
2949 if (ea_size
!= total_data
) {
2950 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2951 total_data=%u (should be %u)\n", (unsigned int)total_data
, (unsigned int)IVAL(pdata
,0) ));
2952 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2956 if (!lp_ea_support(SNUM(conn
))) {
2957 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
2961 /* Pull out the list of names. */
2962 ea_list
= read_ea_name_list(ctx
, pdata
+ 4, ea_size
- 4);
2964 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2969 if (max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
< max_data_bytes
) {
2970 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2974 *ppdata
= (char *)SMB_REALLOC(
2975 *ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
2976 if(*ppdata
== NULL
) {
2977 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2982 data_end
= pdata
+ max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
- 1;
2984 /* Realloc the params space */
2985 *pparams
= (char *)SMB_REALLOC(*pparams
, 6*SIZEOFWORD
);
2986 if(*pparams
== NULL
) {
2987 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2993 /* Check that the dptr is valid */
2994 if(!(dirptr
= dptr_fetch_lanman2(sconn
, dptr_num
))) {
2995 reply_nterror(req
, STATUS_NO_MORE_FILES
);
2999 directory
= dptr_path(sconn
, dptr_num
);
3001 /* Get the wildcard mask from the dptr */
3002 if((mask
= dptr_wcard(sconn
, dptr_num
))== NULL
) {
3003 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num
));
3004 reply_nterror(req
, STATUS_NO_MORE_FILES
);
3008 /* Get the attr mask from the dptr */
3009 dirtype
= dptr_attr(sconn
, dptr_num
);
3011 backup_priv
= dptr_get_priv(dirptr
);
3013 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld) "
3014 "backup_priv = %d\n",
3015 dptr_num
, mask
, dirtype
,
3017 dptr_TellDir(dirptr
),
3020 /* Initialize per TRANS2_FIND_NEXT operation data */
3021 dptr_init_search_op(dirptr
);
3023 /* We don't need to check for VOL here as this is returned by
3024 a different TRANS2 call. */
3026 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
3027 directory
,lp_dont_descend(ctx
, SNUM(conn
))));
3028 if (in_list(directory
,lp_dont_descend(ctx
, SNUM(conn
)),conn
->case_sensitive
))
3029 dont_descend
= True
;
3032 space_remaining
= max_data_bytes
;
3033 out_of_space
= False
;
3040 * Seek to the correct position. We no longer use the resume key but
3041 * depend on the last file name instead.
3044 if(!continue_bit
&& resume_name
&& *resume_name
) {
3047 long current_pos
= 0;
3049 * Remember, name_to_8_3 is called by
3050 * get_lanman2_dir_entry(), so the resume name
3051 * could be mangled. Ensure we check the unmangled name.
3054 if (mangle_is_mangled(resume_name
, conn
->params
)) {
3055 char *new_resume_name
= NULL
;
3056 mangle_lookup_name_from_8_3(ctx
,
3060 if (new_resume_name
) {
3061 resume_name
= new_resume_name
;
3066 * Fix for NT redirector problem triggered by resume key indexes
3067 * changing between directory scans. We now return a resume key of 0
3068 * and instead look for the filename to continue from (also given
3069 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
3070 * findfirst/findnext (as is usual) then the directory pointer
3071 * should already be at the correct place.
3074 finished
= !dptr_SearchDir(dirptr
, resume_name
, ¤t_pos
, &st
);
3075 } /* end if resume_name && !continue_bit */
3077 for (i
=0;(i
<(int)maxentries
) && !finished
&& !out_of_space
;i
++) {
3078 bool got_exact_match
= False
;
3080 /* this is a heuristic to avoid seeking the dirptr except when
3081 absolutely necessary. It allows for a filename of about 40 chars */
3082 if (space_remaining
< DIRLEN_GUESS
&& numentries
> 0) {
3083 out_of_space
= True
;
3086 ntstatus
= get_lanman2_dir_entry(ctx
,
3090 mask
,dirtype
,info_level
,
3091 requires_resume_key
,dont_descend
,
3096 &last_entry_off
, ea_list
);
3097 if (NT_STATUS_EQUAL(ntstatus
,
3098 NT_STATUS_ILLEGAL_CHARACTER
)) {
3100 * Bad character conversion on name. Ignore this
3105 if (NT_STATUS_EQUAL(ntstatus
, STATUS_MORE_ENTRIES
)) {
3106 out_of_space
= true;
3108 finished
= !NT_STATUS_IS_OK(ntstatus
);
3112 if (!finished
&& !out_of_space
)
3116 * As an optimisation if we know we aren't looking
3117 * for a wildcard name (ie. the name matches the wildcard exactly)
3118 * then we can finish on any (first) match.
3119 * This speeds up large directory searches. JRA.
3125 space_remaining
= max_data_bytes
- PTR_DIFF(p
,pdata
);
3128 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
3129 smb_fn_name(req
->cmd
),
3130 mask
, directory
, dirtype
, numentries
) );
3132 /* Check if we can close the dirptr */
3133 if(close_after_request
|| (finished
&& close_if_end
)) {
3134 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num
));
3135 dptr_close(sconn
, &dptr_num
); /* This frees up the saved mask */
3142 /* Set up the return parameter block */
3143 SSVAL(params
,0,numentries
);
3144 SSVAL(params
,2,finished
);
3145 SSVAL(params
,4,0); /* Never an EA error */
3146 SSVAL(params
,6,last_entry_off
);
3148 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 8, pdata
, PTR_DIFF(p
,pdata
),
3154 unsigned char *create_volume_objectid(connection_struct
*conn
, unsigned char objid
[16])
3156 E_md4hash(lp_servicename(talloc_tos(), SNUM(conn
)),objid
);
3160 static void samba_extended_info_version(struct smb_extended_info
*extended_info
)
3162 SMB_ASSERT(extended_info
!= NULL
);
3164 extended_info
->samba_magic
= SAMBA_EXTENDED_INFO_MAGIC
;
3165 extended_info
->samba_version
= ((SAMBA_VERSION_MAJOR
& 0xff) << 24)
3166 | ((SAMBA_VERSION_MINOR
& 0xff) << 16)
3167 | ((SAMBA_VERSION_RELEASE
& 0xff) << 8);
3168 #ifdef SAMBA_VERSION_REVISION
3169 extended_info
->samba_version
|= (tolower(*SAMBA_VERSION_REVISION
) - 'a' + 1) & 0xff;
3171 extended_info
->samba_subversion
= 0;
3172 #ifdef SAMBA_VERSION_RC_RELEASE
3173 extended_info
->samba_subversion
|= (SAMBA_VERSION_RC_RELEASE
& 0xff) << 24;
3175 #ifdef SAMBA_VERSION_PRE_RELEASE
3176 extended_info
->samba_subversion
|= (SAMBA_VERSION_PRE_RELEASE
& 0xff) << 16;
3179 #ifdef SAMBA_VERSION_VENDOR_PATCH
3180 extended_info
->samba_subversion
|= (SAMBA_VERSION_VENDOR_PATCH
& 0xffff);
3182 extended_info
->samba_gitcommitdate
= 0;
3183 #ifdef SAMBA_VERSION_COMMIT_TIME
3184 unix_to_nt_time(&extended_info
->samba_gitcommitdate
, SAMBA_VERSION_COMMIT_TIME
);
3187 memset(extended_info
->samba_version_string
, 0,
3188 sizeof(extended_info
->samba_version_string
));
3190 snprintf (extended_info
->samba_version_string
,
3191 sizeof(extended_info
->samba_version_string
),
3192 "%s", samba_version_string());
3195 NTSTATUS
smbd_do_qfsinfo(struct smbXsrv_connection
*xconn
,
3196 connection_struct
*conn
,
3197 TALLOC_CTX
*mem_ctx
,
3198 uint16_t info_level
,
3200 unsigned int max_data_bytes
,
3201 size_t *fixed_portion
,
3202 struct smb_filename
*fname
,
3206 char *pdata
, *end_data
;
3209 const char *vname
= volume_label(talloc_tos(), SNUM(conn
));
3210 int snum
= SNUM(conn
);
3211 const char *fstype
= lp_fstype(SNUM(conn
));
3212 const char *filename
= NULL
;
3213 uint32 additional_flags
= 0;
3214 struct smb_filename smb_fname
;
3216 NTSTATUS status
= NT_STATUS_OK
;
3218 if (fname
== NULL
|| fname
->base_name
== NULL
) {
3221 filename
= fname
->base_name
;
3225 if (info_level
!= SMB_QUERY_CIFS_UNIX_INFO
) {
3226 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
3227 "info level (0x%x) on IPC$.\n",
3228 (unsigned int)info_level
));
3229 return NT_STATUS_ACCESS_DENIED
;
3233 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level
));
3235 ZERO_STRUCT(smb_fname
);
3236 smb_fname
.base_name
= discard_const_p(char, filename
);
3238 if(SMB_VFS_STAT(conn
, &smb_fname
) != 0) {
3239 DEBUG(2,("stat of . failed (%s)\n", strerror(errno
)));
3240 return map_nt_error_from_unix(errno
);
3245 if (max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
< max_data_bytes
) {
3246 return NT_STATUS_INVALID_PARAMETER
;
3249 *ppdata
= (char *)SMB_REALLOC(
3250 *ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
3251 if (*ppdata
== NULL
) {
3252 return NT_STATUS_NO_MEMORY
;
3256 memset((char *)pdata
,'\0',max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
3257 end_data
= pdata
+ max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
- 1;
3261 switch (info_level
) {
3262 case SMB_INFO_ALLOCATION
:
3264 uint64_t dfree
,dsize
,bsize
,block_size
,sectors_per_unit
,bytes_per_sector
;
3266 if (get_dfree_info(conn
,filename
,False
,&bsize
,&dfree
,&dsize
) == (uint64_t)-1) {
3267 return map_nt_error_from_unix(errno
);
3270 block_size
= lp_block_size(snum
);
3271 if (bsize
< block_size
) {
3272 uint64_t factor
= block_size
/bsize
;
3277 if (bsize
> block_size
) {
3278 uint64_t factor
= bsize
/block_size
;
3283 bytes_per_sector
= 512;
3284 sectors_per_unit
= bsize
/bytes_per_sector
;
3286 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
3287 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st
.st_ex_dev
, (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
3288 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
3290 SIVAL(pdata
,l1_idFileSystem
,st
.st_ex_dev
);
3291 SIVAL(pdata
,l1_cSectorUnit
,sectors_per_unit
);
3292 SIVAL(pdata
,l1_cUnit
,dsize
);
3293 SIVAL(pdata
,l1_cUnitAvail
,dfree
);
3294 SSVAL(pdata
,l1_cbSector
,bytes_per_sector
);
3298 case SMB_INFO_VOLUME
:
3299 /* Return volume name */
3301 * Add volume serial number - hash of a combination of
3302 * the called hostname and the service name.
3304 SIVAL(pdata
,0,str_checksum(lp_servicename(talloc_tos(), snum
)) ^ (str_checksum(get_local_machine_name())<<16) );
3306 * Win2k3 and previous mess this up by sending a name length
3307 * one byte short. I believe only older clients (OS/2 Win9x) use
3308 * this call so try fixing this by adding a terminating null to
3309 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
3311 status
= srvstr_push(
3313 pdata
+l2_vol_szVolLabel
, vname
,
3314 PTR_DIFF(end_data
, pdata
+l2_vol_szVolLabel
),
3315 STR_NOALIGN
|STR_TERMINATE
, &len
);
3316 if (!NT_STATUS_IS_OK(status
)) {
3319 SCVAL(pdata
,l2_vol_cch
,len
);
3320 data_len
= l2_vol_szVolLabel
+ len
;
3321 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %u, name = %s\n",
3322 (unsigned)convert_timespec_to_time_t(st
.st_ex_ctime
),
3323 (unsigned)len
, vname
));
3326 case SMB_QUERY_FS_ATTRIBUTE_INFO
:
3327 case SMB_FS_ATTRIBUTE_INFORMATION
:
3329 additional_flags
= 0;
3330 #if defined(HAVE_SYS_QUOTAS)
3331 additional_flags
|= FILE_VOLUME_QUOTAS
;
3334 if(lp_nt_acl_support(SNUM(conn
))) {
3335 additional_flags
|= FILE_PERSISTENT_ACLS
;
3338 /* Capabilities are filled in at connection time through STATVFS call */
3339 additional_flags
|= conn
->fs_capabilities
;
3340 additional_flags
|= lp_parm_int(conn
->params
->service
,
3341 "share", "fake_fscaps",
3344 SIVAL(pdata
,0,FILE_CASE_PRESERVED_NAMES
|FILE_CASE_SENSITIVE_SEARCH
|
3345 FILE_SUPPORTS_OBJECT_IDS
|FILE_UNICODE_ON_DISK
|
3346 additional_flags
); /* FS ATTRIBUTES */
3348 SIVAL(pdata
,4,255); /* Max filename component length */
3349 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
3350 and will think we can't do long filenames */
3351 status
= srvstr_push(pdata
, flags2
, pdata
+12, fstype
,
3352 PTR_DIFF(end_data
, pdata
+12),
3354 if (!NT_STATUS_IS_OK(status
)) {
3358 data_len
= 12 + len
;
3359 if (max_data_bytes
>= 16 && data_len
> max_data_bytes
) {
3360 /* the client only requested a portion of the
3362 data_len
= max_data_bytes
;
3363 status
= STATUS_BUFFER_OVERFLOW
;
3365 *fixed_portion
= 16;
3368 case SMB_QUERY_FS_LABEL_INFO
:
3369 case SMB_FS_LABEL_INFORMATION
:
3370 status
= srvstr_push(pdata
, flags2
, pdata
+4, vname
,
3371 PTR_DIFF(end_data
, pdata
+4), 0, &len
);
3372 if (!NT_STATUS_IS_OK(status
)) {
3379 case SMB_QUERY_FS_VOLUME_INFO
:
3380 case SMB_FS_VOLUME_INFORMATION
:
3383 * Add volume serial number - hash of a combination of
3384 * the called hostname and the service name.
3386 SIVAL(pdata
,8,str_checksum(lp_servicename(talloc_tos(), snum
)) ^
3387 (str_checksum(get_local_machine_name())<<16));
3389 /* Max label len is 32 characters. */
3390 status
= srvstr_push(pdata
, flags2
, pdata
+18, vname
,
3391 PTR_DIFF(end_data
, pdata
+18),
3393 if (!NT_STATUS_IS_OK(status
)) {
3396 SIVAL(pdata
,12,len
);
3399 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3400 (int)strlen(vname
),vname
,
3401 lp_servicename(talloc_tos(), snum
)));
3402 if (max_data_bytes
>= 24 && data_len
> max_data_bytes
) {
3403 /* the client only requested a portion of the
3405 data_len
= max_data_bytes
;
3406 status
= STATUS_BUFFER_OVERFLOW
;
3408 *fixed_portion
= 24;
3411 case SMB_QUERY_FS_SIZE_INFO
:
3412 case SMB_FS_SIZE_INFORMATION
:
3414 uint64_t dfree
,dsize
,bsize
,block_size
,sectors_per_unit
,bytes_per_sector
;
3416 if (get_dfree_info(conn
,filename
,False
,&bsize
,&dfree
,&dsize
) == (uint64_t)-1) {
3417 return map_nt_error_from_unix(errno
);
3419 block_size
= lp_block_size(snum
);
3420 if (bsize
< block_size
) {
3421 uint64_t factor
= block_size
/bsize
;
3426 if (bsize
> block_size
) {
3427 uint64_t factor
= bsize
/block_size
;
3432 bytes_per_sector
= 512;
3433 sectors_per_unit
= bsize
/bytes_per_sector
;
3434 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3435 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
3436 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
3437 SBIG_UINT(pdata
,0,dsize
);
3438 SBIG_UINT(pdata
,8,dfree
);
3439 SIVAL(pdata
,16,sectors_per_unit
);
3440 SIVAL(pdata
,20,bytes_per_sector
);
3441 *fixed_portion
= 24;
3445 case SMB_FS_FULL_SIZE_INFORMATION
:
3447 uint64_t dfree
,dsize
,bsize
,block_size
,sectors_per_unit
,bytes_per_sector
;
3449 if (get_dfree_info(conn
,filename
,False
,&bsize
,&dfree
,&dsize
) == (uint64_t)-1) {
3450 return map_nt_error_from_unix(errno
);
3452 block_size
= lp_block_size(snum
);
3453 if (bsize
< block_size
) {
3454 uint64_t factor
= block_size
/bsize
;
3459 if (bsize
> block_size
) {
3460 uint64_t factor
= bsize
/block_size
;
3465 bytes_per_sector
= 512;
3466 sectors_per_unit
= bsize
/bytes_per_sector
;
3467 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3468 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
3469 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
3470 SBIG_UINT(pdata
,0,dsize
); /* Total Allocation units. */
3471 SBIG_UINT(pdata
,8,dfree
); /* Caller available allocation units. */
3472 SBIG_UINT(pdata
,16,dfree
); /* Actual available allocation units. */
3473 SIVAL(pdata
,24,sectors_per_unit
); /* Sectors per allocation unit. */
3474 SIVAL(pdata
,28,bytes_per_sector
); /* Bytes per sector. */
3475 *fixed_portion
= 32;
3479 case SMB_QUERY_FS_DEVICE_INFO
:
3480 case SMB_FS_DEVICE_INFORMATION
:
3482 uint32_t characteristics
= FILE_DEVICE_IS_MOUNTED
;
3484 if (!CAN_WRITE(conn
)) {
3485 characteristics
|= FILE_READ_ONLY_DEVICE
;
3488 SIVAL(pdata
,0,FILE_DEVICE_DISK
); /* dev type */
3489 SIVAL(pdata
,4,characteristics
);
3494 #ifdef HAVE_SYS_QUOTAS
3495 case SMB_FS_QUOTA_INFORMATION
:
3497 * what we have to send --metze:
3499 * Unknown1: 24 NULL bytes
3500 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3501 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3502 * Quota Flags: 2 byte :
3503 * Unknown3: 6 NULL bytes
3507 * details for Quota Flags:
3509 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3510 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3511 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3512 * 0x0001 Enable Quotas: enable quota for this fs
3516 /* we need to fake up a fsp here,
3517 * because its not send in this call
3520 SMB_NTQUOTA_STRUCT quotas
;
3523 ZERO_STRUCT(quotas
);
3526 fsp
.fnum
= FNUM_FIELD_INVALID
;
3529 if (get_current_uid(conn
) != 0) {
3530 DEBUG(0,("get_user_quota: access_denied "
3531 "service [%s] user [%s]\n",
3532 lp_servicename(talloc_tos(), SNUM(conn
)),
3533 conn
->session_info
->unix_info
->unix_name
));
3534 return NT_STATUS_ACCESS_DENIED
;
3537 if (vfs_get_ntquota(&fsp
, SMB_USER_FS_QUOTA_TYPE
, NULL
, "as
)!=0) {
3538 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn
))));
3539 return map_nt_error_from_unix(errno
);
3544 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3545 lp_servicename(talloc_tos(), SNUM(conn
))));
3547 /* Unknown1 24 NULL bytes*/
3548 SBIG_UINT(pdata
,0,(uint64_t)0);
3549 SBIG_UINT(pdata
,8,(uint64_t)0);
3550 SBIG_UINT(pdata
,16,(uint64_t)0);
3552 /* Default Soft Quota 8 bytes */
3553 SBIG_UINT(pdata
,24,quotas
.softlim
);
3555 /* Default Hard Quota 8 bytes */
3556 SBIG_UINT(pdata
,32,quotas
.hardlim
);
3558 /* Quota flag 2 bytes */
3559 SSVAL(pdata
,40,quotas
.qflags
);
3561 /* Unknown3 6 NULL bytes */
3567 #endif /* HAVE_SYS_QUOTAS */
3568 case SMB_FS_OBJECTID_INFORMATION
:
3570 unsigned char objid
[16];
3571 struct smb_extended_info extended_info
;
3572 memcpy(pdata
,create_volume_objectid(conn
, objid
),16);
3573 samba_extended_info_version (&extended_info
);
3574 SIVAL(pdata
,16,extended_info
.samba_magic
);
3575 SIVAL(pdata
,20,extended_info
.samba_version
);
3576 SIVAL(pdata
,24,extended_info
.samba_subversion
);
3577 SBIG_UINT(pdata
,28,extended_info
.samba_gitcommitdate
);
3578 memcpy(pdata
+36,extended_info
.samba_version_string
,28);
3584 * Query the version and capabilities of the CIFS UNIX extensions
3588 case SMB_QUERY_CIFS_UNIX_INFO
:
3590 bool large_write
= lp_min_receive_file_size() &&
3591 !srv_is_signing_active(xconn
);
3592 bool large_read
= !srv_is_signing_active(xconn
);
3593 int encrypt_caps
= 0;
3595 if (!lp_unix_extensions()) {
3596 return NT_STATUS_INVALID_LEVEL
;
3599 switch (conn
->encrypt_level
) {
3600 case SMB_SIGNING_OFF
:
3603 case SMB_SIGNING_IF_REQUIRED
:
3604 case SMB_SIGNING_DEFAULT
:
3605 encrypt_caps
= CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP
;
3607 case SMB_SIGNING_REQUIRED
:
3608 encrypt_caps
= CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP
|
3609 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP
;
3610 large_write
= false;
3616 SSVAL(pdata
,0,CIFS_UNIX_MAJOR_VERSION
);
3617 SSVAL(pdata
,2,CIFS_UNIX_MINOR_VERSION
);
3619 /* We have POSIX ACLs, pathname, encryption,
3620 * large read/write, and locking capability. */
3622 SBIG_UINT(pdata
,4,((uint64_t)(
3623 CIFS_UNIX_POSIX_ACLS_CAP
|
3624 CIFS_UNIX_POSIX_PATHNAMES_CAP
|
3625 CIFS_UNIX_FCNTL_LOCKS_CAP
|
3626 CIFS_UNIX_EXTATTR_CAP
|
3627 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP
|
3629 (large_read
? CIFS_UNIX_LARGE_READ_CAP
: 0) |
3631 CIFS_UNIX_LARGE_WRITE_CAP
: 0))));
3635 case SMB_QUERY_POSIX_FS_INFO
:
3638 vfs_statvfs_struct svfs
;
3640 if (!lp_unix_extensions()) {
3641 return NT_STATUS_INVALID_LEVEL
;
3644 rc
= SMB_VFS_STATVFS(conn
, filename
, &svfs
);
3648 SIVAL(pdata
,0,svfs
.OptimalTransferSize
);
3649 SIVAL(pdata
,4,svfs
.BlockSize
);
3650 SBIG_UINT(pdata
,8,svfs
.TotalBlocks
);
3651 SBIG_UINT(pdata
,16,svfs
.BlocksAvail
);
3652 SBIG_UINT(pdata
,24,svfs
.UserBlocksAvail
);
3653 SBIG_UINT(pdata
,32,svfs
.TotalFileNodes
);
3654 SBIG_UINT(pdata
,40,svfs
.FreeFileNodes
);
3655 SBIG_UINT(pdata
,48,svfs
.FsIdentifier
);
3656 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3658 } else if (rc
== EOPNOTSUPP
) {
3659 return NT_STATUS_INVALID_LEVEL
;
3660 #endif /* EOPNOTSUPP */
3662 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn
))));
3663 return NT_STATUS_DOS(ERRSRV
, ERRerror
);
3668 case SMB_QUERY_POSIX_WHOAMI
:
3674 if (!lp_unix_extensions()) {
3675 return NT_STATUS_INVALID_LEVEL
;
3678 if (max_data_bytes
< 40) {
3679 return NT_STATUS_BUFFER_TOO_SMALL
;
3682 if (security_session_user_level(conn
->session_info
, NULL
) < SECURITY_USER
) {
3683 flags
|= SMB_WHOAMI_GUEST
;
3686 /* NOTE: 8 bytes for UID/GID, irrespective of native
3687 * platform size. This matches
3688 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3690 data_len
= 4 /* flags */
3697 + 4 /* pad/reserved */
3698 + (conn
->session_info
->unix_token
->ngroups
* 8)
3700 + (conn
->session_info
->security_token
->num_sids
*
3704 SIVAL(pdata
, 0, flags
);
3705 SIVAL(pdata
, 4, SMB_WHOAMI_MASK
);
3707 (uint64_t)conn
->session_info
->unix_token
->uid
);
3708 SBIG_UINT(pdata
, 16,
3709 (uint64_t)conn
->session_info
->unix_token
->gid
);
3712 if (data_len
>= max_data_bytes
) {
3713 /* Potential overflow, skip the GIDs and SIDs. */
3715 SIVAL(pdata
, 24, 0); /* num_groups */
3716 SIVAL(pdata
, 28, 0); /* num_sids */
3717 SIVAL(pdata
, 32, 0); /* num_sid_bytes */
3718 SIVAL(pdata
, 36, 0); /* reserved */
3724 SIVAL(pdata
, 24, conn
->session_info
->unix_token
->ngroups
);
3725 SIVAL(pdata
, 28, conn
->session_info
->security_token
->num_sids
);
3727 /* We walk the SID list twice, but this call is fairly
3728 * infrequent, and I don't expect that it's performance
3729 * sensitive -- jpeach
3731 for (i
= 0, sid_bytes
= 0;
3732 i
< conn
->session_info
->security_token
->num_sids
; ++i
) {
3733 sid_bytes
+= ndr_size_dom_sid(
3734 &conn
->session_info
->security_token
->sids
[i
],
3738 /* SID list byte count */
3739 SIVAL(pdata
, 32, sid_bytes
);
3741 /* 4 bytes pad/reserved - must be zero */
3742 SIVAL(pdata
, 36, 0);
3746 for (i
= 0; i
< conn
->session_info
->unix_token
->ngroups
; ++i
) {
3747 SBIG_UINT(pdata
, data_len
,
3748 (uint64_t)conn
->session_info
->unix_token
->groups
[i
]);
3754 i
< conn
->session_info
->security_token
->num_sids
; ++i
) {
3755 int sid_len
= ndr_size_dom_sid(
3756 &conn
->session_info
->security_token
->sids
[i
],
3759 sid_linearize(pdata
+ data_len
, sid_len
,
3760 &conn
->session_info
->security_token
->sids
[i
]);
3761 data_len
+= sid_len
;
3767 case SMB_MAC_QUERY_FS_INFO
:
3769 * Thursby MAC extension... ONLY on NTFS filesystems
3770 * once we do streams then we don't need this
3772 if (strequal(lp_fstype(SNUM(conn
)),"NTFS")) {
3774 SIVAL(pdata
,84,0x100); /* Don't support mac... */
3779 return NT_STATUS_INVALID_LEVEL
;
3782 *ret_data_len
= data_len
;
3786 /****************************************************************************
3787 Reply to a TRANS2_QFSINFO (query filesystem info).
3788 ****************************************************************************/
3790 static void call_trans2qfsinfo(connection_struct
*conn
,
3791 struct smb_request
*req
,
3792 char **pparams
, int total_params
,
3793 char **ppdata
, int total_data
,
3794 unsigned int max_data_bytes
)
3796 char *params
= *pparams
;
3797 uint16_t info_level
;
3799 size_t fixed_portion
;
3802 if (total_params
< 2) {
3803 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3807 info_level
= SVAL(params
,0);
3809 if (ENCRYPTION_REQUIRED(conn
) && !req
->encrypted
) {
3810 if (info_level
!= SMB_QUERY_CIFS_UNIX_INFO
) {
3811 DEBUG(0,("call_trans2qfsinfo: encryption required "
3812 "and info level 0x%x sent.\n",
3813 (unsigned int)info_level
));
3814 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3819 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level
));
3821 status
= smbd_do_qfsinfo(req
->xconn
, conn
, req
,
3828 if (!NT_STATUS_IS_OK(status
)) {
3829 reply_nterror(req
, status
);
3833 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 0, *ppdata
, data_len
,
3836 DEBUG( 4, ( "%s info_level = %d\n",
3837 smb_fn_name(req
->cmd
), info_level
) );
3842 /****************************************************************************
3843 Reply to a TRANS2_SETFSINFO (set filesystem info).
3844 ****************************************************************************/
3846 static void call_trans2setfsinfo(connection_struct
*conn
,
3847 struct smb_request
*req
,
3848 char **pparams
, int total_params
,
3849 char **ppdata
, int total_data
,
3850 unsigned int max_data_bytes
)
3852 struct smbXsrv_connection
*xconn
= req
->xconn
;
3853 char *pdata
= *ppdata
;
3854 char *params
= *pparams
;
3857 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",
3858 lp_servicename(talloc_tos(), SNUM(conn
))));
3861 if (total_params
< 4) {
3862 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3864 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3868 info_level
= SVAL(params
,2);
3871 if (info_level
!= SMB_REQUEST_TRANSPORT_ENCRYPTION
&&
3872 info_level
!= SMB_SET_CIFS_UNIX_INFO
) {
3873 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3874 "info level (0x%x) on IPC$.\n",
3875 (unsigned int)info_level
));
3876 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3881 if (ENCRYPTION_REQUIRED(conn
) && !req
->encrypted
) {
3882 if (info_level
!= SMB_REQUEST_TRANSPORT_ENCRYPTION
) {
3883 DEBUG(0,("call_trans2setfsinfo: encryption required "
3884 "and info level 0x%x sent.\n",
3885 (unsigned int)info_level
));
3886 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3891 switch(info_level
) {
3892 case SMB_SET_CIFS_UNIX_INFO
:
3893 if (!lp_unix_extensions()) {
3894 DEBUG(2,("call_trans2setfsinfo: "
3895 "SMB_SET_CIFS_UNIX_INFO is invalid with "
3896 "unix extensions off\n"));
3898 NT_STATUS_INVALID_LEVEL
);
3902 /* There should be 12 bytes of capabilities set. */
3903 if (total_data
< 12) {
3906 NT_STATUS_INVALID_PARAMETER
);
3909 xconn
->smb1
.unix_info
.client_major
= SVAL(pdata
,0);
3910 xconn
->smb1
.unix_info
.client_minor
= SVAL(pdata
,2);
3911 xconn
->smb1
.unix_info
.client_cap_low
= IVAL(pdata
,4);
3912 xconn
->smb1
.unix_info
.client_cap_high
= IVAL(pdata
,8);
3913 /* Just print these values for now. */
3914 DEBUG(10, ("call_trans2setfsinfo: set unix_info info. "
3915 "major = %u, minor = %u cap_low = 0x%x, "
3917 (unsigned int)xconn
->
3918 smb1
.unix_info
.client_major
,
3919 (unsigned int)xconn
->
3920 smb1
.unix_info
.client_minor
,
3921 (unsigned int)xconn
->
3922 smb1
.unix_info
.client_cap_low
,
3923 (unsigned int)xconn
->
3924 smb1
.unix_info
.client_cap_high
));
3926 /* Here is where we must switch to posix pathname processing... */
3927 if (xconn
->smb1
.unix_info
.client_cap_low
& CIFS_UNIX_POSIX_PATHNAMES_CAP
) {
3928 lp_set_posix_pathnames();
3929 mangle_change_to_posix();
3932 if ((xconn
->smb1
.unix_info
.client_cap_low
& CIFS_UNIX_FCNTL_LOCKS_CAP
) &&
3933 !(xconn
->smb1
.unix_info
.client_cap_low
& CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP
)) {
3934 /* Client that knows how to do posix locks,
3935 * but not posix open/mkdir operations. Set a
3936 * default type for read/write checks. */
3938 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK
);
3943 case SMB_REQUEST_TRANSPORT_ENCRYPTION
:
3946 size_t param_len
= 0;
3947 size_t data_len
= total_data
;
3949 if (!lp_unix_extensions()) {
3952 NT_STATUS_INVALID_LEVEL
);
3956 if (lp_smb_encrypt(SNUM(conn
)) == SMB_SIGNING_OFF
) {
3959 NT_STATUS_NOT_SUPPORTED
);
3963 if (xconn
->smb1
.echo_handler
.trusted_fde
) {
3964 DEBUG( 2,("call_trans2setfsinfo: "
3965 "request transport encryption disabled"
3966 "with 'fork echo handler = yes'\n"));
3969 NT_STATUS_NOT_SUPPORTED
);
3973 DEBUG( 4,("call_trans2setfsinfo: "
3974 "request transport encryption.\n"));
3976 status
= srv_request_encryption_setup(conn
,
3977 (unsigned char **)ppdata
,
3979 (unsigned char **)pparams
,
3982 if (!NT_STATUS_EQUAL(status
, NT_STATUS_MORE_PROCESSING_REQUIRED
) &&
3983 !NT_STATUS_IS_OK(status
)) {
3984 reply_nterror(req
, status
);
3988 send_trans2_replies(conn
, req
,
3996 if (NT_STATUS_IS_OK(status
)) {
3997 /* Server-side transport
3998 * encryption is now *on*. */
3999 status
= srv_encryption_start(conn
);
4000 if (!NT_STATUS_IS_OK(status
)) {
4001 char *reason
= talloc_asprintf(talloc_tos(),
4002 "Failure in setting "
4003 "up encrypted transport: %s",
4005 exit_server_cleanly(reason
);
4011 case SMB_FS_QUOTA_INFORMATION
:
4013 files_struct
*fsp
= NULL
;
4014 SMB_NTQUOTA_STRUCT quotas
;
4016 ZERO_STRUCT(quotas
);
4019 if ((get_current_uid(conn
) != 0) || !CAN_WRITE(conn
)) {
4020 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
4021 lp_servicename(talloc_tos(), SNUM(conn
)),
4022 conn
->session_info
->unix_info
->unix_name
));
4023 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
4027 /* note: normaly there're 48 bytes,
4028 * but we didn't use the last 6 bytes for now
4031 fsp
= file_fsp(req
, SVAL(params
,0));
4033 if (!check_fsp_ntquota_handle(conn
, req
,
4035 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
4037 req
, NT_STATUS_INVALID_HANDLE
);
4041 if (total_data
< 42) {
4042 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
4046 NT_STATUS_INVALID_PARAMETER
);
4050 /* unknown_1 24 NULL bytes in pdata*/
4052 /* the soft quotas 8 bytes (uint64_t)*/
4053 quotas
.softlim
= BVAL(pdata
,24);
4055 /* the hard quotas 8 bytes (uint64_t)*/
4056 quotas
.hardlim
= BVAL(pdata
,32);
4058 /* quota_flags 2 bytes **/
4059 quotas
.qflags
= SVAL(pdata
,40);
4061 /* unknown_2 6 NULL bytes follow*/
4063 /* now set the quotas */
4064 if (vfs_set_ntquota(fsp
, SMB_USER_FS_QUOTA_TYPE
, NULL
, "as
)!=0) {
4065 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn
))));
4066 reply_nterror(req
, map_nt_error_from_unix(errno
));
4073 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
4075 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
4081 * sending this reply works fine,
4082 * but I'm not sure it's the same
4083 * like windows do...
4086 reply_outbuf(req
, 10, 0);
4089 #if defined(HAVE_POSIX_ACLS)
4090 /****************************************************************************
4091 Utility function to count the number of entries in a POSIX acl.
4092 ****************************************************************************/
4094 static unsigned int count_acl_entries(connection_struct
*conn
, SMB_ACL_T posix_acl
)
4096 unsigned int ace_count
= 0;
4097 int entry_id
= SMB_ACL_FIRST_ENTRY
;
4098 SMB_ACL_ENTRY_T entry
;
4100 while ( posix_acl
&& (sys_acl_get_entry(posix_acl
, entry_id
, &entry
) == 1)) {
4102 if (entry_id
== SMB_ACL_FIRST_ENTRY
) {
4103 entry_id
= SMB_ACL_NEXT_ENTRY
;
4110 /****************************************************************************
4111 Utility function to marshall a POSIX acl into wire format.
4112 ****************************************************************************/
4114 static bool marshall_posix_acl(connection_struct
*conn
, char *pdata
, SMB_STRUCT_STAT
*pst
, SMB_ACL_T posix_acl
)
4116 int entry_id
= SMB_ACL_FIRST_ENTRY
;
4117 SMB_ACL_ENTRY_T entry
;
4119 while ( posix_acl
&& (sys_acl_get_entry(posix_acl
, entry_id
, &entry
) == 1)) {
4120 SMB_ACL_TAG_T tagtype
;
4121 SMB_ACL_PERMSET_T permset
;
4122 unsigned char perms
= 0;
4123 unsigned int own_grp
;
4126 if (entry_id
== SMB_ACL_FIRST_ENTRY
) {
4127 entry_id
= SMB_ACL_NEXT_ENTRY
;
4130 if (sys_acl_get_tag_type(entry
, &tagtype
) == -1) {
4131 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
4135 if (sys_acl_get_permset(entry
, &permset
) == -1) {
4136 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
4140 perms
|= (sys_acl_get_perm(permset
, SMB_ACL_READ
) ? SMB_POSIX_ACL_READ
: 0);
4141 perms
|= (sys_acl_get_perm(permset
, SMB_ACL_WRITE
) ? SMB_POSIX_ACL_WRITE
: 0);
4142 perms
|= (sys_acl_get_perm(permset
, SMB_ACL_EXECUTE
) ? SMB_POSIX_ACL_EXECUTE
: 0);
4144 SCVAL(pdata
,1,perms
);
4147 case SMB_ACL_USER_OBJ
:
4148 SCVAL(pdata
,0,SMB_POSIX_ACL_USER_OBJ
);
4149 own_grp
= (unsigned int)pst
->st_ex_uid
;
4150 SIVAL(pdata
,2,own_grp
);
4155 uid_t
*puid
= (uid_t
*)sys_acl_get_qualifier(entry
);
4157 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
4160 own_grp
= (unsigned int)*puid
;
4161 SCVAL(pdata
,0,SMB_POSIX_ACL_USER
);
4162 SIVAL(pdata
,2,own_grp
);
4166 case SMB_ACL_GROUP_OBJ
:
4167 SCVAL(pdata
,0,SMB_POSIX_ACL_GROUP_OBJ
);
4168 own_grp
= (unsigned int)pst
->st_ex_gid
;
4169 SIVAL(pdata
,2,own_grp
);
4174 gid_t
*pgid
= (gid_t
*)sys_acl_get_qualifier(entry
);
4176 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
4179 own_grp
= (unsigned int)*pgid
;
4180 SCVAL(pdata
,0,SMB_POSIX_ACL_GROUP
);
4181 SIVAL(pdata
,2,own_grp
);
4186 SCVAL(pdata
,0,SMB_POSIX_ACL_MASK
);
4187 SIVAL(pdata
,2,0xFFFFFFFF);
4188 SIVAL(pdata
,6,0xFFFFFFFF);
4191 SCVAL(pdata
,0,SMB_POSIX_ACL_OTHER
);
4192 SIVAL(pdata
,2,0xFFFFFFFF);
4193 SIVAL(pdata
,6,0xFFFFFFFF);
4196 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
4199 pdata
+= SMB_POSIX_ACL_ENTRY_SIZE
;
4206 /****************************************************************************
4207 Store the FILE_UNIX_BASIC info.
4208 ****************************************************************************/
4210 static char *store_file_unix_basic(connection_struct
*conn
,
4213 const SMB_STRUCT_STAT
*psbuf
)
4215 uint64_t file_index
= get_FileIndex(conn
, psbuf
);
4218 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
4219 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf
->st_ex_mode
));
4221 SOFF_T(pdata
,0,get_file_size_stat(psbuf
)); /* File size 64 Bit */
4224 SOFF_T(pdata
,0,SMB_VFS_GET_ALLOC_SIZE(conn
,fsp
,psbuf
)); /* Number of bytes used on disk - 64 Bit */
4227 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER
, pdata
, psbuf
->st_ex_ctime
); /* Change Time 64 Bit */
4228 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER
,pdata
+8, psbuf
->st_ex_atime
); /* Last access time 64 Bit */
4229 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER
, pdata
+16, psbuf
->st_ex_mtime
); /* Last modification time 64 Bit */
4232 SIVAL(pdata
,0,psbuf
->st_ex_uid
); /* user id for the owner */
4236 SIVAL(pdata
,0,psbuf
->st_ex_gid
); /* group id of owner */
4240 SIVAL(pdata
,0,unix_filetype(psbuf
->st_ex_mode
));
4243 if (S_ISBLK(psbuf
->st_ex_mode
) || S_ISCHR(psbuf
->st_ex_mode
)) {
4244 devno
= psbuf
->st_ex_rdev
;
4246 devno
= psbuf
->st_ex_dev
;
4249 SIVAL(pdata
,0,unix_dev_major(devno
)); /* Major device number if type is device */
4253 SIVAL(pdata
,0,unix_dev_minor(devno
)); /* Minor device number if type is device */
4257 SINO_T_VAL(pdata
,0,(SMB_INO_T
)file_index
); /* inode number */
4260 SIVAL(pdata
,0, unix_perms_to_wire(psbuf
->st_ex_mode
)); /* Standard UNIX file permissions */
4264 SIVAL(pdata
,0,psbuf
->st_ex_nlink
); /* number of hard links */
4271 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
4272 * the chflags(2) (or equivalent) flags.
4274 * XXX: this really should be behind the VFS interface. To do this, we would
4275 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
4276 * Each VFS module could then implement its own mapping as appropriate for the
4277 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
4279 static const struct {unsigned stat_fflag
; unsigned smb_fflag
;}
4283 { UF_NODUMP
, EXT_DO_NOT_BACKUP
},
4287 { UF_IMMUTABLE
, EXT_IMMUTABLE
},
4291 { UF_APPEND
, EXT_OPEN_APPEND_ONLY
},
4295 { UF_HIDDEN
, EXT_HIDDEN
},
4298 /* Do not remove. We need to guarantee that this array has at least one
4299 * entry to build on HP-UX.
4305 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT
*psbuf
,
4306 uint32
*smb_fflags
, uint32
*smb_fmask
)
4310 for (i
= 0; i
< ARRAY_SIZE(info2_flags_map
); ++i
) {
4311 *smb_fmask
|= info2_flags_map
[i
].smb_fflag
;
4312 if (psbuf
->st_ex_flags
& info2_flags_map
[i
].stat_fflag
) {
4313 *smb_fflags
|= info2_flags_map
[i
].smb_fflag
;
4318 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT
*psbuf
,
4319 const uint32 smb_fflags
,
4320 const uint32 smb_fmask
,
4323 uint32 max_fmask
= 0;
4326 *stat_fflags
= psbuf
->st_ex_flags
;
4328 /* For each flags requested in smb_fmask, check the state of the
4329 * corresponding flag in smb_fflags and set or clear the matching
4333 for (i
= 0; i
< ARRAY_SIZE(info2_flags_map
); ++i
) {
4334 max_fmask
|= info2_flags_map
[i
].smb_fflag
;
4335 if (smb_fmask
& info2_flags_map
[i
].smb_fflag
) {
4336 if (smb_fflags
& info2_flags_map
[i
].smb_fflag
) {
4337 *stat_fflags
|= info2_flags_map
[i
].stat_fflag
;
4339 *stat_fflags
&= ~info2_flags_map
[i
].stat_fflag
;
4344 /* If smb_fmask is asking to set any bits that are not supported by
4345 * our flag mappings, we should fail.
4347 if ((smb_fmask
& max_fmask
) != smb_fmask
) {
4355 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
4356 * of file flags and birth (create) time.
4358 static char *store_file_unix_basic_info2(connection_struct
*conn
,
4361 const SMB_STRUCT_STAT
*psbuf
)
4363 uint32 file_flags
= 0;
4364 uint32 flags_mask
= 0;
4366 pdata
= store_file_unix_basic(conn
, pdata
, fsp
, psbuf
);
4368 /* Create (birth) time 64 bit */
4369 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER
,pdata
, psbuf
->st_ex_btime
);
4372 map_info2_flags_from_sbuf(psbuf
, &file_flags
, &flags_mask
);
4373 SIVAL(pdata
, 0, file_flags
); /* flags */
4374 SIVAL(pdata
, 4, flags_mask
); /* mask */
4380 static NTSTATUS
marshall_stream_info(unsigned int num_streams
,
4381 const struct stream_struct
*streams
,
4383 unsigned int max_data_bytes
,
4384 unsigned int *data_size
)
4387 unsigned int ofs
= 0;
4389 if (max_data_bytes
< 32) {
4390 return NT_STATUS_INFO_LENGTH_MISMATCH
;
4393 for (i
= 0; i
< num_streams
; i
++) {
4394 unsigned int next_offset
;
4396 smb_ucs2_t
*namebuf
;
4398 if (!push_ucs2_talloc(talloc_tos(), &namebuf
,
4399 streams
[i
].name
, &namelen
) ||
4402 return NT_STATUS_INVALID_PARAMETER
;
4406 * name_buf is now null-terminated, we need to marshall as not
4413 * We cannot overflow ...
4415 if ((ofs
+ 24 + namelen
) > max_data_bytes
) {
4416 DEBUG(10, ("refusing to overflow reply at stream %u\n",
4418 TALLOC_FREE(namebuf
);
4419 return STATUS_BUFFER_OVERFLOW
;
4422 SIVAL(data
, ofs
+4, namelen
);
4423 SOFF_T(data
, ofs
+8, streams
[i
].size
);
4424 SOFF_T(data
, ofs
+16, streams
[i
].alloc_size
);
4425 memcpy(data
+ofs
+24, namebuf
, namelen
);
4426 TALLOC_FREE(namebuf
);
4428 next_offset
= ofs
+ 24 + namelen
;
4430 if (i
== num_streams
-1) {
4431 SIVAL(data
, ofs
, 0);
4434 unsigned int align
= ndr_align_size(next_offset
, 8);
4436 if ((next_offset
+ align
) > max_data_bytes
) {
4437 DEBUG(10, ("refusing to overflow align "
4438 "reply at stream %u\n",
4440 TALLOC_FREE(namebuf
);
4441 return STATUS_BUFFER_OVERFLOW
;
4444 memset(data
+next_offset
, 0, align
);
4445 next_offset
+= align
;
4447 SIVAL(data
, ofs
, next_offset
- ofs
);
4454 DEBUG(10, ("max_data: %u, data_size: %u\n", max_data_bytes
, ofs
));
4458 return NT_STATUS_OK
;
4461 /****************************************************************************
4462 Reply to a TRANSACT2_QFILEINFO on a PIPE !
4463 ****************************************************************************/
4465 static void call_trans2qpipeinfo(connection_struct
*conn
,
4466 struct smb_request
*req
,
4467 unsigned int tran_call
,
4468 char **pparams
, int total_params
,
4469 char **ppdata
, int total_data
,
4470 unsigned int max_data_bytes
)
4472 char *params
= *pparams
;
4473 char *pdata
= *ppdata
;
4474 unsigned int data_size
= 0;
4475 unsigned int param_size
= 2;
4480 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4484 if (total_params
< 4) {
4485 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4489 fsp
= file_fsp(req
, SVAL(params
,0));
4490 if (!fsp_is_np(fsp
)) {
4491 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
4495 info_level
= SVAL(params
,2);
4497 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
4498 if (*pparams
== NULL
) {
4499 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
4504 if (max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
< max_data_bytes
) {
4505 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4508 data_size
= max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
;
4509 *ppdata
= (char *)SMB_REALLOC(*ppdata
, data_size
);
4510 if (*ppdata
== NULL
) {
4511 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
4516 switch (info_level
) {
4517 case SMB_FILE_STANDARD_INFORMATION
:
4519 SOFF_T(pdata
,0,4096LL);
4526 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
4530 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, param_size
, *ppdata
, data_size
,
4536 NTSTATUS
smbd_do_qfilepathinfo(connection_struct
*conn
,
4537 TALLOC_CTX
*mem_ctx
,
4538 uint16_t info_level
,
4540 struct smb_filename
*smb_fname
,
4541 bool delete_pending
,
4542 struct timespec write_time_ts
,
4543 struct ea_list
*ea_list
,
4544 int lock_data_count
,
4547 unsigned int max_data_bytes
,
4548 size_t *fixed_portion
,
4550 unsigned int *pdata_size
)
4552 char *pdata
= *ppdata
;
4553 char *dstart
, *dend
;
4554 unsigned int data_size
;
4555 struct timespec create_time_ts
, mtime_ts
, atime_ts
, ctime_ts
;
4556 time_t create_time
, mtime
, atime
, c_time
;
4557 SMB_STRUCT_STAT
*psbuf
= &smb_fname
->st
;
4564 uint64_t file_size
= 0;
4566 uint64_t allocation_size
= 0;
4567 uint64_t file_index
= 0;
4568 uint32_t access_mask
= 0;
4571 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
4572 return NT_STATUS_INVALID_LEVEL
;
4575 DEBUG(5,("smbd_do_qfilepathinfo: %s (%s) level=%d max_data=%u\n",
4576 smb_fname_str_dbg(smb_fname
),
4578 info_level
, max_data_bytes
));
4580 mode
= dos_mode(conn
, smb_fname
);
4581 nlink
= psbuf
->st_ex_nlink
;
4583 if (nlink
&& (mode
&FILE_ATTRIBUTE_DIRECTORY
)) {
4587 if ((nlink
> 0) && delete_pending
) {
4591 if (max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
< max_data_bytes
) {
4592 return NT_STATUS_INVALID_PARAMETER
;
4595 data_size
= max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
;
4596 *ppdata
= (char *)SMB_REALLOC(*ppdata
, data_size
);
4597 if (*ppdata
== NULL
) {
4598 return NT_STATUS_NO_MEMORY
;
4602 dend
= dstart
+ data_size
- 1;
4604 if (!null_timespec(write_time_ts
) && !INFO_LEVEL_IS_UNIX(info_level
)) {
4605 update_stat_ex_mtime(psbuf
, write_time_ts
);
4608 create_time_ts
= get_create_timespec(conn
, fsp
, smb_fname
);
4609 mtime_ts
= psbuf
->st_ex_mtime
;
4610 atime_ts
= psbuf
->st_ex_atime
;
4611 ctime_ts
= get_change_timespec(conn
, fsp
, smb_fname
);
4613 if (lp_dos_filetime_resolution(SNUM(conn
))) {
4614 dos_filetime_timespec(&create_time_ts
);
4615 dos_filetime_timespec(&mtime_ts
);
4616 dos_filetime_timespec(&atime_ts
);
4617 dos_filetime_timespec(&ctime_ts
);
4620 create_time
= convert_timespec_to_time_t(create_time_ts
);
4621 mtime
= convert_timespec_to_time_t(mtime_ts
);
4622 atime
= convert_timespec_to_time_t(atime_ts
);
4623 c_time
= convert_timespec_to_time_t(ctime_ts
);
4625 p
= strrchr_m(smb_fname
->base_name
,'/');
4627 base_name
= smb_fname
->base_name
;
4631 /* NT expects the name to be in an exact form of the *full*
4632 filename. See the trans2 torture test */
4633 if (ISDOT(base_name
)) {
4634 dos_fname
= talloc_strdup(mem_ctx
, "\\");
4636 return NT_STATUS_NO_MEMORY
;
4639 dos_fname
= talloc_asprintf(mem_ctx
,
4641 smb_fname
->base_name
);
4643 return NT_STATUS_NO_MEMORY
;
4645 if (is_ntfs_stream_smb_fname(smb_fname
)) {
4646 dos_fname
= talloc_asprintf(dos_fname
, "%s",
4647 smb_fname
->stream_name
);
4649 return NT_STATUS_NO_MEMORY
;
4653 string_replace(dos_fname
, '/', '\\');
4656 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
, fsp
, psbuf
);
4659 /* Do we have this path open ? */
4661 struct file_id fileid
= vfs_file_id_from_sbuf(conn
, psbuf
);
4662 fsp1
= file_find_di_first(conn
->sconn
, fileid
);
4663 if (fsp1
&& fsp1
->initial_allocation_size
) {
4664 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
, fsp1
, psbuf
);
4668 if (!(mode
& FILE_ATTRIBUTE_DIRECTORY
)) {
4669 file_size
= get_file_size_stat(psbuf
);
4673 pos
= fsp
->fh
->position_information
;
4677 access_mask
= fsp
->access_mask
;
4679 /* GENERIC_EXECUTE mapping from Windows */
4680 access_mask
= 0x12019F;
4683 /* This should be an index number - looks like
4686 I think this causes us to fail the IFSKIT
4687 BasicFileInformationTest. -tpot */
4688 file_index
= get_FileIndex(conn
, psbuf
);
4692 switch (info_level
) {
4693 case SMB_INFO_STANDARD
:
4694 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4696 srv_put_dos_date2(pdata
,l1_fdateCreation
,create_time
);
4697 srv_put_dos_date2(pdata
,l1_fdateLastAccess
,atime
);
4698 srv_put_dos_date2(pdata
,l1_fdateLastWrite
,mtime
); /* write time */
4699 SIVAL(pdata
,l1_cbFile
,(uint32
)file_size
);
4700 SIVAL(pdata
,l1_cbFileAlloc
,(uint32
)allocation_size
);
4701 SSVAL(pdata
,l1_attrFile
,mode
);
4704 case SMB_INFO_QUERY_EA_SIZE
:
4706 unsigned int ea_size
=
4707 estimate_ea_size(conn
, fsp
,
4709 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4711 srv_put_dos_date2(pdata
,0,create_time
);
4712 srv_put_dos_date2(pdata
,4,atime
);
4713 srv_put_dos_date2(pdata
,8,mtime
); /* write time */
4714 SIVAL(pdata
,12,(uint32
)file_size
);
4715 SIVAL(pdata
,16,(uint32
)allocation_size
);
4716 SSVAL(pdata
,20,mode
);
4717 SIVAL(pdata
,22,ea_size
);
4721 case SMB_INFO_IS_NAME_VALID
:
4722 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4724 /* os/2 needs this ? really ?*/
4725 return NT_STATUS_DOS(ERRDOS
, ERRbadfunc
);
4727 /* This is only reached for qpathinfo */
4731 case SMB_INFO_QUERY_EAS_FROM_LIST
:
4733 size_t total_ea_len
= 0;
4734 struct ea_list
*ea_file_list
= NULL
;
4735 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4738 get_ea_list_from_file(mem_ctx
, conn
, fsp
,
4740 &total_ea_len
, &ea_file_list
);
4741 if (!NT_STATUS_IS_OK(status
)) {
4745 ea_list
= ea_list_union(ea_list
, ea_file_list
, &total_ea_len
);
4747 if (!ea_list
|| (total_ea_len
> data_size
)) {
4749 SIVAL(pdata
,0,4); /* EA List Length must be set to 4 if no EA's. */
4753 data_size
= fill_ea_buffer(mem_ctx
, pdata
, data_size
, conn
, ea_list
);
4757 case SMB_INFO_QUERY_ALL_EAS
:
4759 /* We have data_size bytes to put EA's into. */
4760 size_t total_ea_len
= 0;
4761 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4763 status
= get_ea_list_from_file(mem_ctx
, conn
, fsp
,
4765 &total_ea_len
, &ea_list
);
4766 if (!NT_STATUS_IS_OK(status
)) {
4770 if (!ea_list
|| (total_ea_len
> data_size
)) {
4772 SIVAL(pdata
,0,4); /* EA List Length must be set to 4 if no EA's. */
4776 data_size
= fill_ea_buffer(mem_ctx
, pdata
, data_size
, conn
, ea_list
);
4780 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
4782 /* This is FileFullEaInformation - 0xF which maps to
4783 * 1015 (decimal) in smbd_do_setfilepathinfo. */
4785 /* We have data_size bytes to put EA's into. */
4786 size_t total_ea_len
= 0;
4787 struct ea_list
*ea_file_list
= NULL
;
4789 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
4791 /*TODO: add filtering and index handling */
4794 get_ea_list_from_file(mem_ctx
, conn
, fsp
,
4796 &total_ea_len
, &ea_file_list
);
4797 if (!NT_STATUS_IS_OK(status
)) {
4800 if (!ea_file_list
) {
4801 return NT_STATUS_NO_EAS_ON_FILE
;
4804 status
= fill_ea_chained_buffer(mem_ctx
,
4808 conn
, ea_file_list
);
4809 if (!NT_STATUS_IS_OK(status
)) {
4815 case SMB_FILE_BASIC_INFORMATION
:
4816 case SMB_QUERY_FILE_BASIC_INFO
:
4818 if (info_level
== SMB_QUERY_FILE_BASIC_INFO
) {
4819 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4820 data_size
= 36; /* w95 returns 40 bytes not 36 - why ?. */
4822 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4826 put_long_date_timespec(conn
->ts_res
,pdata
,create_time_ts
);
4827 put_long_date_timespec(conn
->ts_res
,pdata
+8,atime_ts
);
4828 put_long_date_timespec(conn
->ts_res
,pdata
+16,mtime_ts
); /* write time */
4829 put_long_date_timespec(conn
->ts_res
,pdata
+24,ctime_ts
); /* change time */
4830 SIVAL(pdata
,32,mode
);
4832 DEBUG(5,("SMB_QFBI - "));
4833 DEBUG(5,("create: %s ", ctime(&create_time
)));
4834 DEBUG(5,("access: %s ", ctime(&atime
)));
4835 DEBUG(5,("write: %s ", ctime(&mtime
)));
4836 DEBUG(5,("change: %s ", ctime(&c_time
)));
4837 DEBUG(5,("mode: %x\n", mode
));
4838 *fixed_portion
= data_size
;
4841 case SMB_FILE_STANDARD_INFORMATION
:
4842 case SMB_QUERY_FILE_STANDARD_INFO
:
4844 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4846 SOFF_T(pdata
,0,allocation_size
);
4847 SOFF_T(pdata
,8,file_size
);
4848 SIVAL(pdata
,16,nlink
);
4849 SCVAL(pdata
,20,delete_pending
?1:0);
4850 SCVAL(pdata
,21,(mode
&FILE_ATTRIBUTE_DIRECTORY
)?1:0);
4851 SSVAL(pdata
,22,0); /* Padding. */
4852 *fixed_portion
= 24;
4855 case SMB_FILE_EA_INFORMATION
:
4856 case SMB_QUERY_FILE_EA_INFO
:
4858 unsigned int ea_size
=
4859 estimate_ea_size(conn
, fsp
, smb_fname
);
4860 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4863 SIVAL(pdata
,0,ea_size
);
4867 /* Get the 8.3 name - used if NT SMB was negotiated. */
4868 case SMB_QUERY_FILE_ALT_NAME_INFO
:
4869 case SMB_FILE_ALTERNATE_NAME_INFORMATION
:
4871 char mangled_name
[13];
4872 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4873 if (!name_to_8_3(base_name
,mangled_name
,
4874 True
,conn
->params
)) {
4875 return NT_STATUS_NO_MEMORY
;
4877 status
= srvstr_push(dstart
, flags2
,
4878 pdata
+4, mangled_name
,
4879 PTR_DIFF(dend
, pdata
+4),
4881 if (!NT_STATUS_IS_OK(status
)) {
4884 data_size
= 4 + len
;
4890 case SMB_QUERY_FILE_NAME_INFO
:
4893 this must be *exactly* right for ACLs on mapped drives to work
4895 status
= srvstr_push(dstart
, flags2
,
4897 PTR_DIFF(dend
, pdata
+4),
4899 if (!NT_STATUS_IS_OK(status
)) {
4902 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4903 data_size
= 4 + len
;
4908 case SMB_FILE_ALLOCATION_INFORMATION
:
4909 case SMB_QUERY_FILE_ALLOCATION_INFO
:
4910 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4912 SOFF_T(pdata
,0,allocation_size
);
4915 case SMB_FILE_END_OF_FILE_INFORMATION
:
4916 case SMB_QUERY_FILE_END_OF_FILEINFO
:
4917 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4919 SOFF_T(pdata
,0,file_size
);
4922 case SMB_QUERY_FILE_ALL_INFO
:
4923 case SMB_FILE_ALL_INFORMATION
:
4925 unsigned int ea_size
=
4926 estimate_ea_size(conn
, fsp
, smb_fname
);
4927 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4928 put_long_date_timespec(conn
->ts_res
,pdata
,create_time_ts
);
4929 put_long_date_timespec(conn
->ts_res
,pdata
+8,atime_ts
);
4930 put_long_date_timespec(conn
->ts_res
,pdata
+16,mtime_ts
); /* write time */
4931 put_long_date_timespec(conn
->ts_res
,pdata
+24,ctime_ts
); /* change time */
4932 SIVAL(pdata
,32,mode
);
4933 SIVAL(pdata
,36,0); /* padding. */
4935 SOFF_T(pdata
,0,allocation_size
);
4936 SOFF_T(pdata
,8,file_size
);
4937 SIVAL(pdata
,16,nlink
);
4938 SCVAL(pdata
,20,delete_pending
);
4939 SCVAL(pdata
,21,(mode
&FILE_ATTRIBUTE_DIRECTORY
)?1:0);
4942 SIVAL(pdata
,0,ea_size
);
4943 pdata
+= 4; /* EA info */
4944 status
= srvstr_push(dstart
, flags2
,
4946 PTR_DIFF(dend
, pdata
+4),
4948 if (!NT_STATUS_IS_OK(status
)) {
4953 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4954 *fixed_portion
= 10;
4958 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
4960 unsigned int ea_size
=
4961 estimate_ea_size(conn
, fsp
, smb_fname
);
4962 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
4963 put_long_date_timespec(conn
->ts_res
,pdata
+0x00,create_time_ts
);
4964 put_long_date_timespec(conn
->ts_res
,pdata
+0x08,atime_ts
);
4965 put_long_date_timespec(conn
->ts_res
,pdata
+0x10,mtime_ts
); /* write time */
4966 put_long_date_timespec(conn
->ts_res
,pdata
+0x18,ctime_ts
); /* change time */
4967 SIVAL(pdata
, 0x20, mode
);
4968 SIVAL(pdata
, 0x24, 0); /* padding. */
4969 SBVAL(pdata
, 0x28, allocation_size
);
4970 SBVAL(pdata
, 0x30, file_size
);
4971 SIVAL(pdata
, 0x38, nlink
);
4972 SCVAL(pdata
, 0x3C, delete_pending
);
4973 SCVAL(pdata
, 0x3D, (mode
&FILE_ATTRIBUTE_DIRECTORY
)?1:0);
4974 SSVAL(pdata
, 0x3E, 0); /* padding */
4975 SBVAL(pdata
, 0x40, file_index
);
4976 SIVAL(pdata
, 0x48, ea_size
);
4977 SIVAL(pdata
, 0x4C, access_mask
);
4978 SBVAL(pdata
, 0x50, pos
);
4979 SIVAL(pdata
, 0x58, mode
); /*TODO: mode != mode fix this!!! */
4980 SIVAL(pdata
, 0x5C, 0); /* No alignment needed. */
4984 status
= srvstr_push(dstart
, flags2
,
4986 PTR_DIFF(dend
, pdata
+4),
4988 if (!NT_STATUS_IS_OK(status
)) {
4993 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4994 *fixed_portion
= 104;
4997 case SMB_FILE_INTERNAL_INFORMATION
:
4999 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
5000 SBVAL(pdata
, 0, file_index
);
5005 case SMB_FILE_ACCESS_INFORMATION
:
5006 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
5007 SIVAL(pdata
, 0, access_mask
);
5012 case SMB_FILE_NAME_INFORMATION
:
5013 /* Pathname with leading '\'. */
5016 byte_len
= dos_PutUniCode(pdata
+4,dos_fname
,(size_t)max_data_bytes
,False
);
5017 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
5018 SIVAL(pdata
,0,byte_len
);
5019 data_size
= 4 + byte_len
;
5023 case SMB_FILE_DISPOSITION_INFORMATION
:
5024 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
5026 SCVAL(pdata
,0,delete_pending
);
5030 case SMB_FILE_POSITION_INFORMATION
:
5031 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
5033 SOFF_T(pdata
,0,pos
);
5037 case SMB_FILE_MODE_INFORMATION
:
5038 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
5039 SIVAL(pdata
,0,mode
);
5044 case SMB_FILE_ALIGNMENT_INFORMATION
:
5045 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
5046 SIVAL(pdata
,0,0); /* No alignment needed. */
5052 * NT4 server just returns "invalid query" to this - if we try
5053 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
5056 /* The first statement above is false - verified using Thursby
5057 * client against NT4 -- gcolley.
5059 case SMB_QUERY_FILE_STREAM_INFO
:
5060 case SMB_FILE_STREAM_INFORMATION
: {
5061 unsigned int num_streams
= 0;
5062 struct stream_struct
*streams
= NULL
;
5064 DEBUG(10,("smbd_do_qfilepathinfo: "
5065 "SMB_FILE_STREAM_INFORMATION\n"));
5067 if (is_ntfs_stream_smb_fname(smb_fname
)) {
5068 return NT_STATUS_INVALID_PARAMETER
;
5071 status
= vfs_streaminfo(conn
, fsp
, smb_fname
->base_name
,
5072 talloc_tos(), &num_streams
, &streams
);
5074 if (!NT_STATUS_IS_OK(status
)) {
5075 DEBUG(10, ("could not get stream info: %s\n",
5076 nt_errstr(status
)));
5080 status
= marshall_stream_info(num_streams
, streams
,
5081 pdata
, max_data_bytes
,
5084 if (!NT_STATUS_IS_OK(status
)) {
5085 DEBUG(10, ("marshall_stream_info failed: %s\n",
5086 nt_errstr(status
)));
5087 TALLOC_FREE(streams
);
5091 TALLOC_FREE(streams
);
5093 *fixed_portion
= 32;
5097 case SMB_QUERY_COMPRESSION_INFO
:
5098 case SMB_FILE_COMPRESSION_INFORMATION
:
5099 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
5100 SOFF_T(pdata
,0,file_size
);
5101 SIVAL(pdata
,8,0); /* ??? */
5102 SIVAL(pdata
,12,0); /* ??? */
5104 *fixed_portion
= 16;
5107 case SMB_FILE_NETWORK_OPEN_INFORMATION
:
5108 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
5109 put_long_date_timespec(conn
->ts_res
,pdata
,create_time_ts
);
5110 put_long_date_timespec(conn
->ts_res
,pdata
+8,atime_ts
);
5111 put_long_date_timespec(conn
->ts_res
,pdata
+16,mtime_ts
); /* write time */
5112 put_long_date_timespec(conn
->ts_res
,pdata
+24,ctime_ts
); /* change time */
5113 SOFF_T(pdata
,32,allocation_size
);
5114 SOFF_T(pdata
,40,file_size
);
5115 SIVAL(pdata
,48,mode
);
5116 SIVAL(pdata
,52,0); /* ??? */
5118 *fixed_portion
= 56;
5121 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION
:
5122 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
5123 SIVAL(pdata
,0,mode
);
5130 * CIFS UNIX Extensions.
5133 case SMB_QUERY_FILE_UNIX_BASIC
:
5135 pdata
= store_file_unix_basic(conn
, pdata
, fsp
, psbuf
);
5136 data_size
= PTR_DIFF(pdata
,(*ppdata
));
5138 DEBUG(4,("smbd_do_qfilepathinfo: "
5139 "SMB_QUERY_FILE_UNIX_BASIC\n"));
5140 dump_data(4, (uint8_t *)(*ppdata
), data_size
);
5144 case SMB_QUERY_FILE_UNIX_INFO2
:
5146 pdata
= store_file_unix_basic_info2(conn
, pdata
, fsp
, psbuf
);
5147 data_size
= PTR_DIFF(pdata
,(*ppdata
));
5151 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
5153 for (i
=0; i
<100; i
++)
5154 DEBUG(4,("%d=%x, ",i
, (*ppdata
)[i
]));
5160 case SMB_QUERY_FILE_UNIX_LINK
:
5163 char *buffer
= talloc_array(mem_ctx
, char, PATH_MAX
+1);
5166 return NT_STATUS_NO_MEMORY
;
5169 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
5171 if(!S_ISLNK(psbuf
->st_ex_mode
)) {
5172 return NT_STATUS_DOS(ERRSRV
, ERRbadlink
);
5175 return NT_STATUS_DOS(ERRDOS
, ERRbadlink
);
5177 link_len
= SMB_VFS_READLINK(conn
,
5178 smb_fname
->base_name
,
5180 if (link_len
== -1) {
5181 return map_nt_error_from_unix(errno
);
5183 buffer
[link_len
] = 0;
5184 status
= srvstr_push(dstart
, flags2
,
5186 PTR_DIFF(dend
, pdata
),
5187 STR_TERMINATE
, &len
);
5188 if (!NT_STATUS_IS_OK(status
)) {
5192 data_size
= PTR_DIFF(pdata
,(*ppdata
));
5197 #if defined(HAVE_POSIX_ACLS)
5198 case SMB_QUERY_POSIX_ACL
:
5200 SMB_ACL_T file_acl
= NULL
;
5201 SMB_ACL_T def_acl
= NULL
;
5202 uint16 num_file_acls
= 0;
5203 uint16 num_def_acls
= 0;
5205 if (fsp
&& fsp
->fh
->fd
!= -1) {
5206 file_acl
= SMB_VFS_SYS_ACL_GET_FD(fsp
,
5210 SMB_VFS_SYS_ACL_GET_FILE(conn
,
5211 smb_fname
->base_name
,
5212 SMB_ACL_TYPE_ACCESS
,
5216 if (file_acl
== NULL
&& no_acl_syscall_error(errno
)) {
5217 DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
5218 "not implemented on "
5219 "filesystem containing %s\n",
5220 smb_fname
->base_name
));
5221 return NT_STATUS_NOT_IMPLEMENTED
;
5224 if (S_ISDIR(psbuf
->st_ex_mode
)) {
5225 if (fsp
&& fsp
->is_directory
) {
5227 SMB_VFS_SYS_ACL_GET_FILE(
5229 fsp
->fsp_name
->base_name
,
5230 SMB_ACL_TYPE_DEFAULT
,
5234 SMB_VFS_SYS_ACL_GET_FILE(
5236 smb_fname
->base_name
,
5237 SMB_ACL_TYPE_DEFAULT
,
5240 def_acl
= free_empty_sys_acl(conn
, def_acl
);
5243 num_file_acls
= count_acl_entries(conn
, file_acl
);
5244 num_def_acls
= count_acl_entries(conn
, def_acl
);
5246 if ( data_size
< (num_file_acls
+ num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
+ SMB_POSIX_ACL_HEADER_SIZE
) {
5247 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
5249 (unsigned int)((num_file_acls
+ num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
+
5250 SMB_POSIX_ACL_HEADER_SIZE
) ));
5252 TALLOC_FREE(file_acl
);
5255 TALLOC_FREE(def_acl
);
5257 return NT_STATUS_BUFFER_TOO_SMALL
;
5260 SSVAL(pdata
,0,SMB_POSIX_ACL_VERSION
);
5261 SSVAL(pdata
,2,num_file_acls
);
5262 SSVAL(pdata
,4,num_def_acls
);
5263 if (!marshall_posix_acl(conn
, pdata
+ SMB_POSIX_ACL_HEADER_SIZE
, psbuf
, file_acl
)) {
5265 TALLOC_FREE(file_acl
);
5268 TALLOC_FREE(def_acl
);
5270 return NT_STATUS_INTERNAL_ERROR
;
5272 if (!marshall_posix_acl(conn
, pdata
+ SMB_POSIX_ACL_HEADER_SIZE
+ (num_file_acls
*SMB_POSIX_ACL_ENTRY_SIZE
), psbuf
, def_acl
)) {
5274 TALLOC_FREE(file_acl
);
5277 TALLOC_FREE(def_acl
);
5279 return NT_STATUS_INTERNAL_ERROR
;
5283 TALLOC_FREE(file_acl
);
5286 TALLOC_FREE(def_acl
);
5288 data_size
= (num_file_acls
+ num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
+ SMB_POSIX_ACL_HEADER_SIZE
;
5294 case SMB_QUERY_POSIX_LOCK
:
5299 enum brl_type lock_type
;
5301 /* We need an open file with a real fd for this. */
5302 if (!fsp
|| fsp
->fh
->fd
== -1) {
5303 return NT_STATUS_INVALID_LEVEL
;
5306 if (lock_data_count
!= POSIX_LOCK_DATA_SIZE
) {
5307 return NT_STATUS_INVALID_PARAMETER
;
5310 switch (SVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
)) {
5311 case POSIX_LOCK_TYPE_READ
:
5312 lock_type
= READ_LOCK
;
5314 case POSIX_LOCK_TYPE_WRITE
:
5315 lock_type
= WRITE_LOCK
;
5317 case POSIX_LOCK_TYPE_UNLOCK
:
5319 /* There's no point in asking for an unlock... */
5320 return NT_STATUS_INVALID_PARAMETER
;
5323 smblctx
= (uint64_t)IVAL(pdata
, POSIX_LOCK_PID_OFFSET
);
5324 offset
= BVAL(pdata
,POSIX_LOCK_START_OFFSET
);
5325 count
= BVAL(pdata
,POSIX_LOCK_LEN_OFFSET
);
5327 status
= query_lock(fsp
,
5334 if (ERROR_WAS_LOCK_DENIED(status
)) {
5335 /* Here we need to report who has it locked... */
5336 data_size
= POSIX_LOCK_DATA_SIZE
;
5338 SSVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
, lock_type
);
5339 SSVAL(pdata
, POSIX_LOCK_FLAGS_OFFSET
, 0);
5340 SIVAL(pdata
, POSIX_LOCK_PID_OFFSET
, (uint32_t)smblctx
);
5341 SBVAL(pdata
, POSIX_LOCK_START_OFFSET
, offset
);
5342 SBVAL(pdata
, POSIX_LOCK_LEN_OFFSET
, count
);
5344 } else if (NT_STATUS_IS_OK(status
)) {
5345 /* For success we just return a copy of what we sent
5346 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
5347 data_size
= POSIX_LOCK_DATA_SIZE
;
5348 memcpy(pdata
, lock_data
, POSIX_LOCK_DATA_SIZE
);
5349 SSVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
, POSIX_LOCK_TYPE_UNLOCK
);
5357 return NT_STATUS_INVALID_LEVEL
;
5360 *pdata_size
= data_size
;
5361 return NT_STATUS_OK
;
5364 /****************************************************************************
5365 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
5366 file name or file id).
5367 ****************************************************************************/
5369 static void call_trans2qfilepathinfo(connection_struct
*conn
,
5370 struct smb_request
*req
,
5371 unsigned int tran_call
,
5372 char **pparams
, int total_params
,
5373 char **ppdata
, int total_data
,
5374 unsigned int max_data_bytes
)
5376 char *params
= *pparams
;
5377 char *pdata
= *ppdata
;
5379 unsigned int data_size
= 0;
5380 unsigned int param_size
= 2;
5381 struct smb_filename
*smb_fname
= NULL
;
5382 bool delete_pending
= False
;
5383 struct timespec write_time_ts
;
5384 files_struct
*fsp
= NULL
;
5385 struct file_id fileid
;
5386 struct ea_list
*ea_list
= NULL
;
5387 int lock_data_count
= 0;
5388 char *lock_data
= NULL
;
5389 size_t fixed_portion
;
5390 NTSTATUS status
= NT_STATUS_OK
;
5393 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5397 ZERO_STRUCT(write_time_ts
);
5399 if (tran_call
== TRANSACT2_QFILEINFO
) {
5400 if (total_params
< 4) {
5401 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5406 call_trans2qpipeinfo(conn
, req
, tran_call
,
5407 pparams
, total_params
,
5413 fsp
= file_fsp(req
, SVAL(params
,0));
5414 info_level
= SVAL(params
,2);
5416 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level
));
5418 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
5419 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
5423 /* Initial check for valid fsp ptr. */
5424 if (!check_fsp_open(conn
, req
, fsp
)) {
5428 smb_fname
= cp_smb_filename(talloc_tos(), fsp
->fsp_name
);
5429 if (smb_fname
== NULL
) {
5430 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5434 if(fsp
->fake_file_handle
) {
5436 * This is actually for the QUOTA_FAKE_FILE --metze
5439 /* We know this name is ok, it's already passed the checks. */
5441 } else if(fsp
->fh
->fd
== -1) {
5443 * This is actually a QFILEINFO on a directory
5444 * handle (returned from an NT SMB). NT5.0 seems
5445 * to do this call. JRA.
5448 if (INFO_LEVEL_IS_UNIX(info_level
)) {
5449 /* Always do lstat for UNIX calls. */
5450 if (SMB_VFS_LSTAT(conn
, smb_fname
)) {
5451 DEBUG(3,("call_trans2qfilepathinfo: "
5452 "SMB_VFS_LSTAT of %s failed "
5454 smb_fname_str_dbg(smb_fname
),
5457 map_nt_error_from_unix(errno
));
5460 } else if (SMB_VFS_STAT(conn
, smb_fname
)) {
5461 DEBUG(3,("call_trans2qfilepathinfo: "
5462 "SMB_VFS_STAT of %s failed (%s)\n",
5463 smb_fname_str_dbg(smb_fname
),
5466 map_nt_error_from_unix(errno
));
5470 fileid
= vfs_file_id_from_sbuf(conn
, &smb_fname
->st
);
5471 get_file_infos(fileid
, fsp
->name_hash
, &delete_pending
, &write_time_ts
);
5474 * Original code - this is an open file.
5476 if (SMB_VFS_FSTAT(fsp
, &smb_fname
->st
) != 0) {
5477 DEBUG(3, ("fstat of %s failed (%s)\n",
5478 fsp_fnum_dbg(fsp
), strerror(errno
)));
5480 map_nt_error_from_unix(errno
));
5483 fileid
= vfs_file_id_from_sbuf(conn
, &smb_fname
->st
);
5484 get_file_infos(fileid
, fsp
->name_hash
, &delete_pending
, &write_time_ts
);
5490 uint32_t ucf_flags
= 0;
5493 if (total_params
< 7) {
5494 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5498 info_level
= SVAL(params
,0);
5500 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level
));
5502 if (INFO_LEVEL_IS_UNIX(info_level
)) {
5503 if (!lp_unix_extensions()) {
5504 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
5507 if (info_level
== SMB_QUERY_FILE_UNIX_BASIC
||
5508 info_level
== SMB_QUERY_FILE_UNIX_INFO2
||
5509 info_level
== SMB_QUERY_FILE_UNIX_LINK
) {
5510 ucf_flags
|= UCF_UNIX_NAME_LOOKUP
;
5514 srvstr_get_path(req
, params
, req
->flags2
, &fname
, ¶ms
[6],
5516 STR_TERMINATE
, &status
);
5517 if (!NT_STATUS_IS_OK(status
)) {
5518 reply_nterror(req
, status
);
5522 status
= filename_convert(req
,
5524 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
5529 if (!NT_STATUS_IS_OK(status
)) {
5530 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
5531 reply_botherror(req
,
5532 NT_STATUS_PATH_NOT_COVERED
,
5533 ERRSRV
, ERRbadpath
);
5536 reply_nterror(req
, status
);
5540 /* If this is a stream, check if there is a delete_pending. */
5541 if ((conn
->fs_capabilities
& FILE_NAMED_STREAMS
)
5542 && is_ntfs_stream_smb_fname(smb_fname
)) {
5543 struct smb_filename
*smb_fname_base
;
5545 /* Create an smb_filename with stream_name == NULL. */
5546 smb_fname_base
= synthetic_smb_fname(
5547 talloc_tos(), smb_fname
->base_name
,
5549 if (smb_fname_base
== NULL
) {
5550 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5554 if (INFO_LEVEL_IS_UNIX(info_level
)) {
5555 /* Always do lstat for UNIX calls. */
5556 if (SMB_VFS_LSTAT(conn
, smb_fname_base
) != 0) {
5557 DEBUG(3,("call_trans2qfilepathinfo: "
5558 "SMB_VFS_LSTAT of %s failed "
5560 smb_fname_str_dbg(smb_fname_base
),
5562 TALLOC_FREE(smb_fname_base
);
5564 map_nt_error_from_unix(errno
));
5568 if (SMB_VFS_STAT(conn
, smb_fname_base
) != 0) {
5569 DEBUG(3,("call_trans2qfilepathinfo: "
5570 "fileinfo of %s failed "
5572 smb_fname_str_dbg(smb_fname_base
),
5574 TALLOC_FREE(smb_fname_base
);
5576 map_nt_error_from_unix(errno
));
5581 status
= file_name_hash(conn
,
5582 smb_fname_str_dbg(smb_fname_base
),
5584 if (!NT_STATUS_IS_OK(status
)) {
5585 TALLOC_FREE(smb_fname_base
);
5586 reply_nterror(req
, status
);
5590 fileid
= vfs_file_id_from_sbuf(conn
,
5591 &smb_fname_base
->st
);
5592 TALLOC_FREE(smb_fname_base
);
5593 get_file_infos(fileid
, name_hash
, &delete_pending
, NULL
);
5594 if (delete_pending
) {
5595 reply_nterror(req
, NT_STATUS_DELETE_PENDING
);
5600 if (INFO_LEVEL_IS_UNIX(info_level
)) {
5601 /* Always do lstat for UNIX calls. */
5602 if (SMB_VFS_LSTAT(conn
, smb_fname
)) {
5603 DEBUG(3,("call_trans2qfilepathinfo: "
5604 "SMB_VFS_LSTAT of %s failed (%s)\n",
5605 smb_fname_str_dbg(smb_fname
),
5608 map_nt_error_from_unix(errno
));
5613 if (SMB_VFS_STAT(conn
, smb_fname
) != 0) {
5614 DEBUG(3,("call_trans2qfilepathinfo: "
5615 "SMB_VFS_STAT of %s failed (%s)\n",
5616 smb_fname_str_dbg(smb_fname
),
5619 map_nt_error_from_unix(errno
));
5624 status
= file_name_hash(conn
,
5625 smb_fname_str_dbg(smb_fname
),
5627 if (!NT_STATUS_IS_OK(status
)) {
5628 reply_nterror(req
, status
);
5632 fileid
= vfs_file_id_from_sbuf(conn
, &smb_fname
->st
);
5633 get_file_infos(fileid
, name_hash
, &delete_pending
, &write_time_ts
);
5634 if (delete_pending
) {
5635 reply_nterror(req
, NT_STATUS_DELETE_PENDING
);
5640 DEBUG(3,("call_trans2qfilepathinfo %s (%s) level=%d call=%d "
5641 "total_data=%d\n", smb_fname_str_dbg(smb_fname
),
5643 info_level
,tran_call
,total_data
));
5645 /* Pull out any data sent here before we realloc. */
5646 switch (info_level
) {
5647 case SMB_INFO_QUERY_EAS_FROM_LIST
:
5649 /* Pull any EA list from the data portion. */
5652 if (total_data
< 4) {
5654 req
, NT_STATUS_INVALID_PARAMETER
);
5657 ea_size
= IVAL(pdata
,0);
5659 if (total_data
> 0 && ea_size
!= total_data
) {
5660 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5661 total_data=%u (should be %u)\n", (unsigned int)total_data
, (unsigned int)IVAL(pdata
,0) ));
5663 req
, NT_STATUS_INVALID_PARAMETER
);
5667 if (!lp_ea_support(SNUM(conn
))) {
5668 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
5672 /* Pull out the list of names. */
5673 ea_list
= read_ea_name_list(req
, pdata
+ 4, ea_size
- 4);
5676 req
, NT_STATUS_INVALID_PARAMETER
);
5682 case SMB_QUERY_POSIX_LOCK
:
5684 if (fsp
== NULL
|| fsp
->fh
->fd
== -1) {
5685 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
5689 if (total_data
!= POSIX_LOCK_DATA_SIZE
) {
5691 req
, NT_STATUS_INVALID_PARAMETER
);
5695 /* Copy the lock range data. */
5696 lock_data
= (char *)talloc_memdup(
5697 req
, pdata
, total_data
);
5699 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5702 lock_data_count
= total_data
;
5708 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
5709 if (*pparams
== NULL
) {
5710 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5717 * draft-leach-cifs-v1-spec-02.txt
5718 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
5721 * The requested information is placed in the Data portion of the
5722 * transaction response. For the information levels greater than 0x100,
5723 * the transaction response has 1 parameter word which should be
5724 * ignored by the client.
5726 * However Windows only follows this rule for the IS_NAME_VALID call.
5728 switch (info_level
) {
5729 case SMB_INFO_IS_NAME_VALID
:
5734 if ((info_level
& 0xFF00) == 0xFF00) {
5736 * We use levels that start with 0xFF00
5737 * internally to represent SMB2 specific levels
5739 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
5743 status
= smbd_do_qfilepathinfo(conn
, req
, info_level
,
5745 delete_pending
, write_time_ts
,
5747 lock_data_count
, lock_data
,
5748 req
->flags2
, max_data_bytes
,
5750 ppdata
, &data_size
);
5751 if (!NT_STATUS_IS_OK(status
)) {
5752 reply_nterror(req
, status
);
5755 if (fixed_portion
> max_data_bytes
) {
5756 reply_nterror(req
, NT_STATUS_INFO_LENGTH_MISMATCH
);
5760 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, param_size
, *ppdata
, data_size
,
5766 /****************************************************************************
5767 Set a hard link (called by UNIX extensions and by NT rename with HARD link
5769 ****************************************************************************/
5771 NTSTATUS
hardlink_internals(TALLOC_CTX
*ctx
,
5772 connection_struct
*conn
,
5773 struct smb_request
*req
,
5774 bool overwrite_if_exists
,
5775 const struct smb_filename
*smb_fname_old
,
5776 struct smb_filename
*smb_fname_new
)
5778 NTSTATUS status
= NT_STATUS_OK
;
5780 /* source must already exist. */
5781 if (!VALID_STAT(smb_fname_old
->st
)) {
5782 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5785 if (VALID_STAT(smb_fname_new
->st
)) {
5786 if (overwrite_if_exists
) {
5787 if (S_ISDIR(smb_fname_new
->st
.st_ex_mode
)) {
5788 return NT_STATUS_FILE_IS_A_DIRECTORY
;
5790 status
= unlink_internals(conn
,
5792 FILE_ATTRIBUTE_NORMAL
,
5795 if (!NT_STATUS_IS_OK(status
)) {
5799 /* Disallow if newname already exists. */
5800 return NT_STATUS_OBJECT_NAME_COLLISION
;
5804 /* No links from a directory. */
5805 if (S_ISDIR(smb_fname_old
->st
.st_ex_mode
)) {
5806 return NT_STATUS_FILE_IS_A_DIRECTORY
;
5809 /* Setting a hardlink to/from a stream isn't currently supported. */
5810 if (is_ntfs_stream_smb_fname(smb_fname_old
) ||
5811 is_ntfs_stream_smb_fname(smb_fname_new
)) {
5812 return NT_STATUS_INVALID_PARAMETER
;
5815 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
5816 smb_fname_old
->base_name
, smb_fname_new
->base_name
));
5818 if (SMB_VFS_LINK(conn
, smb_fname_old
->base_name
,
5819 smb_fname_new
->base_name
) != 0) {
5820 status
= map_nt_error_from_unix(errno
);
5821 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
5822 nt_errstr(status
), smb_fname_old
->base_name
,
5823 smb_fname_new
->base_name
));
5828 /****************************************************************************
5829 Deal with setting the time from any of the setfilepathinfo functions.
5830 NOTE !!!! The check for FILE_WRITE_ATTRIBUTES access must be done *before*
5831 calling this function.
5832 ****************************************************************************/
5834 NTSTATUS
smb_set_file_time(connection_struct
*conn
,
5836 const struct smb_filename
*smb_fname
,
5837 struct smb_file_time
*ft
,
5838 bool setting_write_time
)
5840 struct smb_filename smb_fname_base
;
5842 FILE_NOTIFY_CHANGE_LAST_ACCESS
5843 |FILE_NOTIFY_CHANGE_LAST_WRITE
5844 |FILE_NOTIFY_CHANGE_CREATION
;
5846 if (!VALID_STAT(smb_fname
->st
)) {
5847 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5850 /* get some defaults (no modifications) if any info is zero or -1. */
5851 if (null_timespec(ft
->create_time
)) {
5852 action
&= ~FILE_NOTIFY_CHANGE_CREATION
;
5855 if (null_timespec(ft
->atime
)) {
5856 action
&= ~FILE_NOTIFY_CHANGE_LAST_ACCESS
;
5859 if (null_timespec(ft
->mtime
)) {
5860 action
&= ~FILE_NOTIFY_CHANGE_LAST_WRITE
;
5863 if (!setting_write_time
) {
5864 /* ft->mtime comes from change time, not write time. */
5865 action
&= ~FILE_NOTIFY_CHANGE_LAST_WRITE
;
5868 /* Ensure the resolution is the correct for
5869 * what we can store on this filesystem. */
5871 round_timespec(conn
->ts_res
, &ft
->create_time
);
5872 round_timespec(conn
->ts_res
, &ft
->ctime
);
5873 round_timespec(conn
->ts_res
, &ft
->atime
);
5874 round_timespec(conn
->ts_res
, &ft
->mtime
);
5876 DEBUG(5,("smb_set_filetime: actime: %s\n ",
5877 time_to_asc(convert_timespec_to_time_t(ft
->atime
))));
5878 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
5879 time_to_asc(convert_timespec_to_time_t(ft
->mtime
))));
5880 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
5881 time_to_asc(convert_timespec_to_time_t(ft
->ctime
))));
5882 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
5883 time_to_asc(convert_timespec_to_time_t(ft
->create_time
))));
5885 if (setting_write_time
) {
5887 * This was a Windows setfileinfo on an open file.
5888 * NT does this a lot. We also need to
5889 * set the time here, as it can be read by
5890 * FindFirst/FindNext and with the patch for bug #2045
5891 * in smbd/fileio.c it ensures that this timestamp is
5892 * kept sticky even after a write. We save the request
5893 * away and will set it on file close and after a write. JRA.
5896 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
5897 time_to_asc(convert_timespec_to_time_t(ft
->mtime
))));
5900 if (fsp
->base_fsp
) {
5901 set_sticky_write_time_fsp(fsp
->base_fsp
,
5904 set_sticky_write_time_fsp(fsp
, ft
->mtime
);
5907 set_sticky_write_time_path(
5908 vfs_file_id_from_sbuf(conn
, &smb_fname
->st
),
5913 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5915 /* Always call ntimes on the base, even if a stream was passed in. */
5916 smb_fname_base
= *smb_fname
;
5917 smb_fname_base
.stream_name
= NULL
;
5919 if(file_ntimes(conn
, &smb_fname_base
, ft
)!=0) {
5920 return map_nt_error_from_unix(errno
);
5923 notify_fname(conn
, NOTIFY_ACTION_MODIFIED
, action
,
5924 smb_fname
->base_name
);
5925 return NT_STATUS_OK
;
5928 /****************************************************************************
5929 Deal with setting the dosmode from any of the setfilepathinfo functions.
5930 NB. The check for FILE_WRITE_ATTRIBUTES access on this path must have been
5931 done before calling this function.
5932 ****************************************************************************/
5934 static NTSTATUS
smb_set_file_dosmode(connection_struct
*conn
,
5935 const struct smb_filename
*smb_fname
,
5938 struct smb_filename
*smb_fname_base
;
5941 if (!VALID_STAT(smb_fname
->st
)) {
5942 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5945 /* Always operate on the base_name, even if a stream was passed in. */
5946 smb_fname_base
= synthetic_smb_fname(
5947 talloc_tos(), smb_fname
->base_name
, NULL
, &smb_fname
->st
);
5948 if (smb_fname_base
== NULL
) {
5949 return NT_STATUS_NO_MEMORY
;
5953 if (S_ISDIR(smb_fname_base
->st
.st_ex_mode
)) {
5954 dosmode
|= FILE_ATTRIBUTE_DIRECTORY
;
5956 dosmode
&= ~FILE_ATTRIBUTE_DIRECTORY
;
5960 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode
));
5962 /* check the mode isn't different, before changing it */
5963 if ((dosmode
!= 0) && (dosmode
!= dos_mode(conn
, smb_fname_base
))) {
5964 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
5965 "0x%x\n", smb_fname_str_dbg(smb_fname_base
),
5966 (unsigned int)dosmode
));
5968 if(file_set_dosmode(conn
, smb_fname_base
, dosmode
, NULL
,
5970 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
5972 smb_fname_str_dbg(smb_fname_base
),
5974 status
= map_nt_error_from_unix(errno
);
5978 status
= NT_STATUS_OK
;
5980 TALLOC_FREE(smb_fname_base
);
5984 /****************************************************************************
5985 Deal with setting the size from any of the setfilepathinfo functions.
5986 ****************************************************************************/
5988 static NTSTATUS
smb_set_file_size(connection_struct
*conn
,
5989 struct smb_request
*req
,
5991 const struct smb_filename
*smb_fname
,
5992 const SMB_STRUCT_STAT
*psbuf
,
5994 bool fail_after_createfile
)
5996 NTSTATUS status
= NT_STATUS_OK
;
5997 struct smb_filename
*smb_fname_tmp
= NULL
;
5998 files_struct
*new_fsp
= NULL
;
6000 if (!VALID_STAT(*psbuf
)) {
6001 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
6004 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size
));
6006 if (size
== get_file_size_stat(psbuf
)) {
6007 return NT_STATUS_OK
;
6010 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
6011 smb_fname_str_dbg(smb_fname
), (double)size
));
6013 if (fsp
&& fsp
->fh
->fd
!= -1) {
6014 /* Handle based call. */
6015 if (!(fsp
->access_mask
& FILE_WRITE_DATA
)) {
6016 return NT_STATUS_ACCESS_DENIED
;
6019 if (vfs_set_filelen(fsp
, size
) == -1) {
6020 return map_nt_error_from_unix(errno
);
6022 trigger_write_time_update_immediate(fsp
);
6023 return NT_STATUS_OK
;
6026 smb_fname_tmp
= cp_smb_filename(talloc_tos(), smb_fname
);
6027 if (smb_fname_tmp
== NULL
) {
6028 return NT_STATUS_NO_MEMORY
;
6031 smb_fname_tmp
->st
= *psbuf
;
6033 status
= SMB_VFS_CREATE_FILE(
6036 0, /* root_dir_fid */
6037 smb_fname_tmp
, /* fname */
6038 FILE_WRITE_DATA
, /* access_mask */
6039 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
6041 FILE_OPEN
, /* create_disposition*/
6042 0, /* create_options */
6043 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
6044 0, /* oplock_request */
6046 0, /* allocation_size */
6047 0, /* private_flags */
6050 &new_fsp
, /* result */
6052 NULL
, NULL
); /* create context */
6054 TALLOC_FREE(smb_fname_tmp
);
6056 if (!NT_STATUS_IS_OK(status
)) {
6057 /* NB. We check for open_was_deferred in the caller. */
6061 /* See RAW-SFILEINFO-END-OF-FILE */
6062 if (fail_after_createfile
) {
6063 close_file(req
, new_fsp
,NORMAL_CLOSE
);
6064 return NT_STATUS_INVALID_LEVEL
;
6067 if (vfs_set_filelen(new_fsp
, size
) == -1) {
6068 status
= map_nt_error_from_unix(errno
);
6069 close_file(req
, new_fsp
,NORMAL_CLOSE
);
6073 trigger_write_time_update_immediate(new_fsp
);
6074 close_file(req
, new_fsp
,NORMAL_CLOSE
);
6075 return NT_STATUS_OK
;
6078 /****************************************************************************
6079 Deal with SMB_INFO_SET_EA.
6080 ****************************************************************************/
6082 static NTSTATUS
smb_info_set_ea(connection_struct
*conn
,
6086 const struct smb_filename
*smb_fname
)
6088 struct ea_list
*ea_list
= NULL
;
6089 TALLOC_CTX
*ctx
= NULL
;
6090 NTSTATUS status
= NT_STATUS_OK
;
6092 if (total_data
< 10) {
6094 /* OS/2 workplace shell seems to send SET_EA requests of "null"
6095 length. They seem to have no effect. Bug #3212. JRA */
6097 if ((total_data
== 4) && (IVAL(pdata
,0) == 4)) {
6098 /* We're done. We only get EA info in this call. */
6099 return NT_STATUS_OK
;
6102 return NT_STATUS_INVALID_PARAMETER
;
6105 if (IVAL(pdata
,0) > total_data
) {
6106 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
6107 IVAL(pdata
,0), (unsigned int)total_data
));
6108 return NT_STATUS_INVALID_PARAMETER
;
6112 ea_list
= read_ea_list(ctx
, pdata
+ 4, total_data
- 4);
6114 return NT_STATUS_INVALID_PARAMETER
;
6117 status
= set_ea(conn
, fsp
, smb_fname
, ea_list
);
6122 /****************************************************************************
6123 Deal with SMB_FILE_FULL_EA_INFORMATION set.
6124 ****************************************************************************/
6126 static NTSTATUS
smb_set_file_full_ea_info(connection_struct
*conn
,
6131 struct ea_list
*ea_list
= NULL
;
6135 return NT_STATUS_INVALID_HANDLE
;
6138 if (!lp_ea_support(SNUM(conn
))) {
6139 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
6140 "EA's not supported.\n",
6141 (unsigned int)total_data
));
6142 return NT_STATUS_EAS_NOT_SUPPORTED
;
6145 if (total_data
< 10) {
6146 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
6148 (unsigned int)total_data
));
6149 return NT_STATUS_INVALID_PARAMETER
;
6152 ea_list
= read_nttrans_ea_list(talloc_tos(),
6157 return NT_STATUS_INVALID_PARAMETER
;
6160 status
= set_ea(conn
, fsp
, fsp
->fsp_name
, ea_list
);
6162 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
6163 smb_fname_str_dbg(fsp
->fsp_name
),
6164 nt_errstr(status
) ));
6170 /****************************************************************************
6171 Deal with SMB_SET_FILE_DISPOSITION_INFO.
6172 ****************************************************************************/
6174 static NTSTATUS
smb_set_file_disposition_info(connection_struct
*conn
,
6178 struct smb_filename
*smb_fname
)
6180 NTSTATUS status
= NT_STATUS_OK
;
6181 bool delete_on_close
;
6184 if (total_data
< 1) {
6185 return NT_STATUS_INVALID_PARAMETER
;
6189 return NT_STATUS_INVALID_HANDLE
;
6192 delete_on_close
= (CVAL(pdata
,0) ? True
: False
);
6193 dosmode
= dos_mode(conn
, smb_fname
);
6195 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
6196 "delete_on_close = %u\n",
6197 smb_fname_str_dbg(smb_fname
),
6198 (unsigned int)dosmode
,
6199 (unsigned int)delete_on_close
));
6201 if (delete_on_close
) {
6202 status
= can_set_delete_on_close(fsp
, dosmode
);
6203 if (!NT_STATUS_IS_OK(status
)) {
6208 /* The set is across all open files on this dev/inode pair. */
6209 if (!set_delete_on_close(fsp
, delete_on_close
,
6210 conn
->session_info
->security_token
,
6211 conn
->session_info
->unix_token
)) {
6212 return NT_STATUS_ACCESS_DENIED
;
6214 return NT_STATUS_OK
;
6217 /****************************************************************************
6218 Deal with SMB_FILE_POSITION_INFORMATION.
6219 ****************************************************************************/
6221 static NTSTATUS
smb_file_position_information(connection_struct
*conn
,
6226 uint64_t position_information
;
6228 if (total_data
< 8) {
6229 return NT_STATUS_INVALID_PARAMETER
;
6233 /* Ignore on pathname based set. */
6234 return NT_STATUS_OK
;
6237 position_information
= (uint64_t)IVAL(pdata
,0);
6238 position_information
|= (((uint64_t)IVAL(pdata
,4)) << 32);
6240 DEBUG(10,("smb_file_position_information: Set file position "
6241 "information for file %s to %.0f\n", fsp_str_dbg(fsp
),
6242 (double)position_information
));
6243 fsp
->fh
->position_information
= position_information
;
6244 return NT_STATUS_OK
;
6247 /****************************************************************************
6248 Deal with SMB_FILE_MODE_INFORMATION.
6249 ****************************************************************************/
6251 static NTSTATUS
smb_file_mode_information(connection_struct
*conn
,
6257 if (total_data
< 4) {
6258 return NT_STATUS_INVALID_PARAMETER
;
6260 mode
= IVAL(pdata
,0);
6261 if (mode
!= 0 && mode
!= 2 && mode
!= 4 && mode
!= 6) {
6262 return NT_STATUS_INVALID_PARAMETER
;
6264 return NT_STATUS_OK
;
6267 /****************************************************************************
6268 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
6269 ****************************************************************************/
6271 static NTSTATUS
smb_set_file_unix_link(connection_struct
*conn
,
6272 struct smb_request
*req
,
6275 const struct smb_filename
*smb_fname
)
6277 char *link_target
= NULL
;
6278 const char *newname
= smb_fname
->base_name
;
6279 TALLOC_CTX
*ctx
= talloc_tos();
6281 /* Set a symbolic link. */
6282 /* Don't allow this if follow links is false. */
6284 if (total_data
== 0) {
6285 return NT_STATUS_INVALID_PARAMETER
;
6288 if (!lp_follow_symlinks(SNUM(conn
))) {
6289 return NT_STATUS_ACCESS_DENIED
;
6292 srvstr_pull_talloc(ctx
, pdata
, req
->flags2
, &link_target
, pdata
,
6293 total_data
, STR_TERMINATE
);
6296 return NT_STATUS_INVALID_PARAMETER
;
6299 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
6300 newname
, link_target
));
6302 if (SMB_VFS_SYMLINK(conn
,link_target
,newname
) != 0) {
6303 return map_nt_error_from_unix(errno
);
6306 return NT_STATUS_OK
;
6309 /****************************************************************************
6310 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
6311 ****************************************************************************/
6313 static NTSTATUS
smb_set_file_unix_hlink(connection_struct
*conn
,
6314 struct smb_request
*req
,
6315 const char *pdata
, int total_data
,
6316 struct smb_filename
*smb_fname_new
)
6318 char *oldname
= NULL
;
6319 struct smb_filename
*smb_fname_old
= NULL
;
6320 TALLOC_CTX
*ctx
= talloc_tos();
6321 NTSTATUS status
= NT_STATUS_OK
;
6323 /* Set a hard link. */
6324 if (total_data
== 0) {
6325 return NT_STATUS_INVALID_PARAMETER
;
6328 srvstr_get_path(ctx
, pdata
, req
->flags2
, &oldname
, pdata
,
6329 total_data
, STR_TERMINATE
, &status
);
6330 if (!NT_STATUS_IS_OK(status
)) {
6334 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
6335 smb_fname_str_dbg(smb_fname_new
), oldname
));
6337 status
= filename_convert(ctx
,
6339 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6344 if (!NT_STATUS_IS_OK(status
)) {
6348 return hardlink_internals(ctx
, conn
, req
, false,
6349 smb_fname_old
, smb_fname_new
);
6352 /****************************************************************************
6353 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
6354 ****************************************************************************/
6356 static NTSTATUS
smb2_file_rename_information(connection_struct
*conn
,
6357 struct smb_request
*req
,
6361 struct smb_filename
*smb_fname_src
)
6365 char *newname
= NULL
;
6366 struct smb_filename
*smb_fname_dst
= NULL
;
6367 NTSTATUS status
= NT_STATUS_OK
;
6368 TALLOC_CTX
*ctx
= talloc_tos();
6371 return NT_STATUS_INVALID_HANDLE
;
6374 if (total_data
< 20) {
6375 return NT_STATUS_INVALID_PARAMETER
;
6378 overwrite
= (CVAL(pdata
,0) ? True
: False
);
6379 len
= IVAL(pdata
,16);
6381 if (len
> (total_data
- 20) || (len
== 0)) {
6382 return NT_STATUS_INVALID_PARAMETER
;
6385 srvstr_get_path(ctx
, pdata
, req
->flags2
, &newname
,
6386 &pdata
[20], len
, STR_TERMINATE
,
6388 if (!NT_STATUS_IS_OK(status
)) {
6392 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
6395 status
= filename_convert(ctx
,
6397 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6402 if (!NT_STATUS_IS_OK(status
)) {
6406 if (fsp
->base_fsp
) {
6407 /* newname must be a stream name. */
6408 if (newname
[0] != ':') {
6409 return NT_STATUS_NOT_SUPPORTED
;
6412 /* Create an smb_fname to call rename_internals_fsp() with. */
6413 smb_fname_dst
= synthetic_smb_fname(
6414 talloc_tos(), fsp
->base_fsp
->fsp_name
->base_name
,
6416 if (smb_fname_dst
== NULL
) {
6417 status
= NT_STATUS_NO_MEMORY
;
6422 * Set the original last component, since
6423 * rename_internals_fsp() requires it.
6425 smb_fname_dst
->original_lcomp
= talloc_strdup(smb_fname_dst
,
6427 if (smb_fname_dst
->original_lcomp
== NULL
) {
6428 status
= NT_STATUS_NO_MEMORY
;
6434 DEBUG(10,("smb2_file_rename_information: "
6435 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
6436 fsp_fnum_dbg(fsp
), fsp_str_dbg(fsp
),
6437 smb_fname_str_dbg(smb_fname_dst
)));
6438 status
= rename_internals_fsp(conn
, fsp
, smb_fname_dst
,
6439 (FILE_ATTRIBUTE_HIDDEN
|FILE_ATTRIBUTE_SYSTEM
),
6443 TALLOC_FREE(smb_fname_dst
);
6447 static NTSTATUS
smb_file_link_information(connection_struct
*conn
,
6448 struct smb_request
*req
,
6452 struct smb_filename
*smb_fname_src
)
6456 char *newname
= NULL
;
6457 struct smb_filename
*smb_fname_dst
= NULL
;
6458 NTSTATUS status
= NT_STATUS_OK
;
6459 TALLOC_CTX
*ctx
= talloc_tos();
6462 return NT_STATUS_INVALID_HANDLE
;
6465 if (total_data
< 20) {
6466 return NT_STATUS_INVALID_PARAMETER
;
6469 overwrite
= (CVAL(pdata
,0) ? true : false);
6470 len
= IVAL(pdata
,16);
6472 if (len
> (total_data
- 20) || (len
== 0)) {
6473 return NT_STATUS_INVALID_PARAMETER
;
6476 srvstr_get_path(ctx
, pdata
, req
->flags2
, &newname
,
6477 &pdata
[20], len
, STR_TERMINATE
,
6479 if (!NT_STATUS_IS_OK(status
)) {
6483 DEBUG(10,("smb_file_link_information: got name |%s|\n",
6486 status
= filename_convert(ctx
,
6488 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6493 if (!NT_STATUS_IS_OK(status
)) {
6497 if (fsp
->base_fsp
) {
6498 /* No stream names. */
6499 return NT_STATUS_NOT_SUPPORTED
;
6502 DEBUG(10,("smb_file_link_information: "
6503 "SMB_FILE_LINK_INFORMATION (%s) %s -> %s\n",
6504 fsp_fnum_dbg(fsp
), fsp_str_dbg(fsp
),
6505 smb_fname_str_dbg(smb_fname_dst
)));
6506 status
= hardlink_internals(ctx
,
6513 TALLOC_FREE(smb_fname_dst
);
6517 /****************************************************************************
6518 Deal with SMB_FILE_RENAME_INFORMATION.
6519 ****************************************************************************/
6521 static NTSTATUS
smb_file_rename_information(connection_struct
*conn
,
6522 struct smb_request
*req
,
6526 struct smb_filename
*smb_fname_src
)
6531 char *newname
= NULL
;
6532 struct smb_filename
*smb_fname_dst
= NULL
;
6533 bool dest_has_wcard
= False
;
6534 NTSTATUS status
= NT_STATUS_OK
;
6536 TALLOC_CTX
*ctx
= talloc_tos();
6538 if (total_data
< 13) {
6539 return NT_STATUS_INVALID_PARAMETER
;
6542 overwrite
= (CVAL(pdata
,0) ? True
: False
);
6543 root_fid
= IVAL(pdata
,4);
6544 len
= IVAL(pdata
,8);
6546 if (len
> (total_data
- 12) || (len
== 0) || (root_fid
!= 0)) {
6547 return NT_STATUS_INVALID_PARAMETER
;
6550 srvstr_get_path_wcard(ctx
, pdata
, req
->flags2
, &newname
, &pdata
[12],
6553 if (!NT_STATUS_IS_OK(status
)) {
6557 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
6560 status
= resolve_dfspath_wcard(ctx
, conn
,
6561 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6564 !conn
->sconn
->using_smb2
,
6567 if (!NT_STATUS_IS_OK(status
)) {
6571 /* Check the new name has no '/' characters. */
6572 if (strchr_m(newname
, '/')) {
6573 return NT_STATUS_NOT_SUPPORTED
;
6576 if (fsp
&& fsp
->base_fsp
) {
6577 /* newname must be a stream name. */
6578 if (newname
[0] != ':') {
6579 return NT_STATUS_NOT_SUPPORTED
;
6582 /* Create an smb_fname to call rename_internals_fsp() with. */
6583 smb_fname_dst
= synthetic_smb_fname(
6584 talloc_tos(), fsp
->base_fsp
->fsp_name
->base_name
,
6586 if (smb_fname_dst
== NULL
) {
6587 status
= NT_STATUS_NO_MEMORY
;
6592 * Set the original last component, since
6593 * rename_internals_fsp() requires it.
6595 smb_fname_dst
->original_lcomp
= talloc_strdup(smb_fname_dst
,
6597 if (smb_fname_dst
->original_lcomp
== NULL
) {
6598 status
= NT_STATUS_NO_MEMORY
;
6604 * Build up an smb_fname_dst based on the filename passed in.
6605 * We basically just strip off the last component, and put on
6606 * the newname instead.
6608 char *base_name
= NULL
;
6610 /* newname must *not* be a stream name. */
6611 if (newname
[0] == ':') {
6612 return NT_STATUS_NOT_SUPPORTED
;
6616 * Strip off the last component (filename) of the path passed
6619 base_name
= talloc_strdup(ctx
, smb_fname_src
->base_name
);
6621 return NT_STATUS_NO_MEMORY
;
6623 p
= strrchr_m(base_name
, '/');
6627 base_name
= talloc_strdup(ctx
, "");
6629 return NT_STATUS_NO_MEMORY
;
6632 /* Append the new name. */
6633 base_name
= talloc_asprintf_append(base_name
,
6637 return NT_STATUS_NO_MEMORY
;
6640 status
= unix_convert(ctx
, conn
, base_name
, &smb_fname_dst
,
6643 UCF_ALWAYS_ALLOW_WCARD_LCOMP
:
6646 /* If an error we expect this to be
6647 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
6649 if (!NT_STATUS_IS_OK(status
)) {
6650 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND
,
6654 /* Create an smb_fname to call rename_internals_fsp() */
6655 smb_fname_dst
= synthetic_smb_fname(
6656 ctx
, base_name
, NULL
, NULL
);
6657 if (smb_fname_dst
== NULL
) {
6658 status
= NT_STATUS_NO_MEMORY
;
6665 DEBUG(10,("smb_file_rename_information: "
6666 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
6667 fsp_fnum_dbg(fsp
), fsp_str_dbg(fsp
),
6668 smb_fname_str_dbg(smb_fname_dst
)));
6669 status
= rename_internals_fsp(conn
, fsp
, smb_fname_dst
, 0,
6672 DEBUG(10,("smb_file_rename_information: "
6673 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
6674 smb_fname_str_dbg(smb_fname_src
),
6675 smb_fname_str_dbg(smb_fname_dst
)));
6676 status
= rename_internals(ctx
, conn
, req
, smb_fname_src
,
6677 smb_fname_dst
, 0, overwrite
, false,
6679 FILE_WRITE_ATTRIBUTES
);
6682 TALLOC_FREE(smb_fname_dst
);
6686 /****************************************************************************
6687 Deal with SMB_SET_POSIX_ACL.
6688 ****************************************************************************/
6690 #if defined(HAVE_POSIX_ACLS)
6691 static NTSTATUS
smb_set_posix_acl(connection_struct
*conn
,
6695 const struct smb_filename
*smb_fname
)
6697 uint16 posix_acl_version
;
6698 uint16 num_file_acls
;
6699 uint16 num_def_acls
;
6700 bool valid_file_acls
= True
;
6701 bool valid_def_acls
= True
;
6703 if (total_data
< SMB_POSIX_ACL_HEADER_SIZE
) {
6704 return NT_STATUS_INVALID_PARAMETER
;
6706 posix_acl_version
= SVAL(pdata
,0);
6707 num_file_acls
= SVAL(pdata
,2);
6708 num_def_acls
= SVAL(pdata
,4);
6710 if (num_file_acls
== SMB_POSIX_IGNORE_ACE_ENTRIES
) {
6711 valid_file_acls
= False
;
6715 if (num_def_acls
== SMB_POSIX_IGNORE_ACE_ENTRIES
) {
6716 valid_def_acls
= False
;
6720 if (posix_acl_version
!= SMB_POSIX_ACL_VERSION
) {
6721 return NT_STATUS_INVALID_PARAMETER
;
6724 if (total_data
< SMB_POSIX_ACL_HEADER_SIZE
+
6725 (num_file_acls
+num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
) {
6726 return NT_STATUS_INVALID_PARAMETER
;
6729 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
6730 smb_fname
? smb_fname_str_dbg(smb_fname
) : fsp_str_dbg(fsp
),
6731 (unsigned int)num_file_acls
,
6732 (unsigned int)num_def_acls
));
6734 if (valid_file_acls
&& !set_unix_posix_acl(conn
, fsp
,
6735 smb_fname
->base_name
, num_file_acls
,
6736 pdata
+ SMB_POSIX_ACL_HEADER_SIZE
)) {
6737 return map_nt_error_from_unix(errno
);
6740 if (valid_def_acls
&& !set_unix_posix_default_acl(conn
,
6741 smb_fname
->base_name
, &smb_fname
->st
, num_def_acls
,
6742 pdata
+ SMB_POSIX_ACL_HEADER_SIZE
+
6743 (num_file_acls
*SMB_POSIX_ACL_ENTRY_SIZE
))) {
6744 return map_nt_error_from_unix(errno
);
6746 return NT_STATUS_OK
;
6750 /****************************************************************************
6751 Deal with SMB_SET_POSIX_LOCK.
6752 ****************************************************************************/
6754 static NTSTATUS
smb_set_posix_lock(connection_struct
*conn
,
6755 struct smb_request
*req
,
6763 bool blocking_lock
= False
;
6764 enum brl_type lock_type
;
6766 NTSTATUS status
= NT_STATUS_OK
;
6768 if (fsp
== NULL
|| fsp
->fh
->fd
== -1) {
6769 return NT_STATUS_INVALID_HANDLE
;
6772 if (total_data
!= POSIX_LOCK_DATA_SIZE
) {
6773 return NT_STATUS_INVALID_PARAMETER
;
6776 switch (SVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
)) {
6777 case POSIX_LOCK_TYPE_READ
:
6778 lock_type
= READ_LOCK
;
6780 case POSIX_LOCK_TYPE_WRITE
:
6781 /* Return the right POSIX-mappable error code for files opened read-only. */
6782 if (!fsp
->can_write
) {
6783 return NT_STATUS_INVALID_HANDLE
;
6785 lock_type
= WRITE_LOCK
;
6787 case POSIX_LOCK_TYPE_UNLOCK
:
6788 lock_type
= UNLOCK_LOCK
;
6791 return NT_STATUS_INVALID_PARAMETER
;
6794 if (SVAL(pdata
,POSIX_LOCK_FLAGS_OFFSET
) == POSIX_LOCK_FLAG_NOWAIT
) {
6795 blocking_lock
= False
;
6796 } else if (SVAL(pdata
,POSIX_LOCK_FLAGS_OFFSET
) == POSIX_LOCK_FLAG_WAIT
) {
6797 blocking_lock
= True
;
6799 return NT_STATUS_INVALID_PARAMETER
;
6802 if (!lp_blocking_locks(SNUM(conn
))) {
6803 blocking_lock
= False
;
6806 smblctx
= (uint64_t)IVAL(pdata
, POSIX_LOCK_PID_OFFSET
);
6807 offset
= (((uint64_t) IVAL(pdata
,(POSIX_LOCK_START_OFFSET
+4))) << 32) |
6808 ((uint64_t) IVAL(pdata
,POSIX_LOCK_START_OFFSET
));
6809 count
= (((uint64_t) IVAL(pdata
,(POSIX_LOCK_LEN_OFFSET
+4))) << 32) |
6810 ((uint64_t) IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
));
6812 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
6813 "smblctx = %llu, count = %.0f, offset = %.0f\n",
6815 (unsigned int)lock_type
,
6816 (unsigned long long)smblctx
,
6820 if (lock_type
== UNLOCK_LOCK
) {
6821 status
= do_unlock(req
->sconn
->msg_ctx
,
6828 uint64_t block_smblctx
;
6830 struct byte_range_lock
*br_lck
= do_lock(req
->sconn
->msg_ctx
,
6841 if (br_lck
&& blocking_lock
&& ERROR_WAS_LOCK_DENIED(status
)) {
6843 * A blocking lock was requested. Package up
6844 * this smb into a queued request and push it
6845 * onto the blocking lock queue.
6847 if(push_blocking_lock_request(br_lck
,
6850 -1, /* infinite timeout. */
6858 TALLOC_FREE(br_lck
);
6862 TALLOC_FREE(br_lck
);
6868 /****************************************************************************
6869 Deal with SMB_SET_FILE_BASIC_INFO.
6870 ****************************************************************************/
6872 static NTSTATUS
smb_set_file_basic_info(connection_struct
*conn
,
6876 const struct smb_filename
*smb_fname
)
6878 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
6879 struct smb_file_time ft
;
6881 NTSTATUS status
= NT_STATUS_OK
;
6885 if (total_data
< 36) {
6886 return NT_STATUS_INVALID_PARAMETER
;
6889 status
= check_access(conn
, fsp
, smb_fname
, FILE_WRITE_ATTRIBUTES
);
6890 if (!NT_STATUS_IS_OK(status
)) {
6894 /* Set the attributes */
6895 dosmode
= IVAL(pdata
,32);
6896 status
= smb_set_file_dosmode(conn
, smb_fname
, dosmode
);
6897 if (!NT_STATUS_IS_OK(status
)) {
6902 ft
.create_time
= interpret_long_date(pdata
);
6905 ft
.atime
= interpret_long_date(pdata
+8);
6908 ft
.mtime
= interpret_long_date(pdata
+16);
6911 ft
.ctime
= interpret_long_date(pdata
+24);
6913 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
6914 smb_fname_str_dbg(smb_fname
)));
6916 return smb_set_file_time(conn
, fsp
, smb_fname
, &ft
,
6920 /****************************************************************************
6921 Deal with SMB_INFO_STANDARD.
6922 ****************************************************************************/
6924 static NTSTATUS
smb_set_info_standard(connection_struct
*conn
,
6928 const struct smb_filename
*smb_fname
)
6931 struct smb_file_time ft
;
6935 if (total_data
< 12) {
6936 return NT_STATUS_INVALID_PARAMETER
;
6940 ft
.create_time
= convert_time_t_to_timespec(srv_make_unix_date2(pdata
));
6942 ft
.atime
= convert_time_t_to_timespec(srv_make_unix_date2(pdata
+4));
6944 ft
.mtime
= convert_time_t_to_timespec(srv_make_unix_date2(pdata
+8));
6946 DEBUG(10,("smb_set_info_standard: file %s\n",
6947 smb_fname_str_dbg(smb_fname
)));
6949 status
= check_access(conn
, fsp
, smb_fname
, FILE_WRITE_ATTRIBUTES
);
6950 if (!NT_STATUS_IS_OK(status
)) {
6954 return smb_set_file_time(conn
,
6961 /****************************************************************************
6962 Deal with SMB_SET_FILE_ALLOCATION_INFO.
6963 ****************************************************************************/
6965 static NTSTATUS
smb_set_file_allocation_info(connection_struct
*conn
,
6966 struct smb_request
*req
,
6970 struct smb_filename
*smb_fname
)
6972 uint64_t allocation_size
= 0;
6973 NTSTATUS status
= NT_STATUS_OK
;
6974 files_struct
*new_fsp
= NULL
;
6976 if (!VALID_STAT(smb_fname
->st
)) {
6977 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
6980 if (total_data
< 8) {
6981 return NT_STATUS_INVALID_PARAMETER
;
6984 allocation_size
= (uint64_t)IVAL(pdata
,0);
6985 allocation_size
|= (((uint64_t)IVAL(pdata
,4)) << 32);
6986 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
6987 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname
),
6988 (double)allocation_size
));
6990 if (allocation_size
) {
6991 allocation_size
= smb_roundup(conn
, allocation_size
);
6994 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
6995 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname
),
6996 (double)allocation_size
));
6998 if (fsp
&& fsp
->fh
->fd
!= -1) {
6999 /* Open file handle. */
7000 if (!(fsp
->access_mask
& FILE_WRITE_DATA
)) {
7001 return NT_STATUS_ACCESS_DENIED
;
7004 /* Only change if needed. */
7005 if (allocation_size
!= get_file_size_stat(&smb_fname
->st
)) {
7006 if (vfs_allocate_file_space(fsp
, allocation_size
) == -1) {
7007 return map_nt_error_from_unix(errno
);
7010 /* But always update the time. */
7012 * This is equivalent to a write. Ensure it's seen immediately
7013 * if there are no pending writes.
7015 trigger_write_time_update_immediate(fsp
);
7016 return NT_STATUS_OK
;
7019 /* Pathname or stat or directory file. */
7020 status
= SMB_VFS_CREATE_FILE(
7023 0, /* root_dir_fid */
7024 smb_fname
, /* fname */
7025 FILE_WRITE_DATA
, /* access_mask */
7026 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
7028 FILE_OPEN
, /* create_disposition*/
7029 0, /* create_options */
7030 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
7031 0, /* oplock_request */
7033 0, /* allocation_size */
7034 0, /* private_flags */
7037 &new_fsp
, /* result */
7039 NULL
, NULL
); /* create context */
7041 if (!NT_STATUS_IS_OK(status
)) {
7042 /* NB. We check for open_was_deferred in the caller. */
7046 /* Only change if needed. */
7047 if (allocation_size
!= get_file_size_stat(&smb_fname
->st
)) {
7048 if (vfs_allocate_file_space(new_fsp
, allocation_size
) == -1) {
7049 status
= map_nt_error_from_unix(errno
);
7050 close_file(req
, new_fsp
, NORMAL_CLOSE
);
7055 /* Changing the allocation size should set the last mod time. */
7057 * This is equivalent to a write. Ensure it's seen immediately
7058 * if there are no pending writes.
7060 trigger_write_time_update_immediate(new_fsp
);
7061 close_file(req
, new_fsp
, NORMAL_CLOSE
);
7062 return NT_STATUS_OK
;
7065 /****************************************************************************
7066 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
7067 ****************************************************************************/
7069 static NTSTATUS
smb_set_file_end_of_file_info(connection_struct
*conn
,
7070 struct smb_request
*req
,
7074 const struct smb_filename
*smb_fname
,
7075 bool fail_after_createfile
)
7079 if (total_data
< 8) {
7080 return NT_STATUS_INVALID_PARAMETER
;
7083 size
= IVAL(pdata
,0);
7084 size
|= (((off_t
)IVAL(pdata
,4)) << 32);
7085 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
7086 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname
),
7089 return smb_set_file_size(conn
, req
,
7094 fail_after_createfile
);
7097 /****************************************************************************
7098 Allow a UNIX info mknod.
7099 ****************************************************************************/
7101 static NTSTATUS
smb_unix_mknod(connection_struct
*conn
,
7104 const struct smb_filename
*smb_fname
)
7106 uint32 file_type
= IVAL(pdata
,56);
7107 #if defined(HAVE_MAKEDEV)
7108 uint32 dev_major
= IVAL(pdata
,60);
7109 uint32 dev_minor
= IVAL(pdata
,68);
7111 SMB_DEV_T dev
= (SMB_DEV_T
)0;
7112 uint32 raw_unixmode
= IVAL(pdata
,84);
7116 if (total_data
< 100) {
7117 return NT_STATUS_INVALID_PARAMETER
;
7120 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
7121 PERM_NEW_FILE
, &unixmode
);
7122 if (!NT_STATUS_IS_OK(status
)) {
7126 #if defined(HAVE_MAKEDEV)
7127 dev
= makedev(dev_major
, dev_minor
);
7130 switch (file_type
) {
7131 #if defined(S_IFIFO)
7132 case UNIX_TYPE_FIFO
:
7133 unixmode
|= S_IFIFO
;
7136 #if defined(S_IFSOCK)
7137 case UNIX_TYPE_SOCKET
:
7138 unixmode
|= S_IFSOCK
;
7141 #if defined(S_IFCHR)
7142 case UNIX_TYPE_CHARDEV
:
7143 unixmode
|= S_IFCHR
;
7146 #if defined(S_IFBLK)
7147 case UNIX_TYPE_BLKDEV
:
7148 unixmode
|= S_IFBLK
;
7152 return NT_STATUS_INVALID_PARAMETER
;
7155 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
7156 "%.0f mode 0%o for file %s\n", (double)dev
,
7157 (unsigned int)unixmode
, smb_fname_str_dbg(smb_fname
)));
7159 /* Ok - do the mknod. */
7160 if (SMB_VFS_MKNOD(conn
, smb_fname
->base_name
, unixmode
, dev
) != 0) {
7161 return map_nt_error_from_unix(errno
);
7164 /* If any of the other "set" calls fail we
7165 * don't want to end up with a half-constructed mknod.
7168 if (lp_inherit_permissions(SNUM(conn
))) {
7170 if (!parent_dirname(talloc_tos(), smb_fname
->base_name
,
7172 return NT_STATUS_NO_MEMORY
;
7174 inherit_access_posix_acl(conn
, parent
, smb_fname
->base_name
,
7176 TALLOC_FREE(parent
);
7179 return NT_STATUS_OK
;
7182 /****************************************************************************
7183 Deal with SMB_SET_FILE_UNIX_BASIC.
7184 ****************************************************************************/
7186 static NTSTATUS
smb_set_file_unix_basic(connection_struct
*conn
,
7187 struct smb_request
*req
,
7191 const struct smb_filename
*smb_fname
)
7193 struct smb_file_time ft
;
7194 uint32 raw_unixmode
;
7197 uid_t set_owner
= (uid_t
)SMB_UID_NO_CHANGE
;
7198 gid_t set_grp
= (uid_t
)SMB_GID_NO_CHANGE
;
7199 NTSTATUS status
= NT_STATUS_OK
;
7200 bool delete_on_fail
= False
;
7201 enum perm_type ptype
;
7202 files_struct
*all_fsps
= NULL
;
7203 bool modify_mtime
= true;
7205 struct smb_filename
*smb_fname_tmp
= NULL
;
7206 SMB_STRUCT_STAT sbuf
;
7210 if (total_data
< 100) {
7211 return NT_STATUS_INVALID_PARAMETER
;
7214 if(IVAL(pdata
, 0) != SMB_SIZE_NO_CHANGE_LO
&&
7215 IVAL(pdata
, 4) != SMB_SIZE_NO_CHANGE_HI
) {
7216 size
=IVAL(pdata
,0); /* first 8 Bytes are size */
7217 size
|= (((off_t
)IVAL(pdata
,4)) << 32);
7220 ft
.atime
= interpret_long_date(pdata
+24); /* access_time */
7221 ft
.mtime
= interpret_long_date(pdata
+32); /* modification_time */
7222 set_owner
= (uid_t
)IVAL(pdata
,40);
7223 set_grp
= (gid_t
)IVAL(pdata
,48);
7224 raw_unixmode
= IVAL(pdata
,84);
7226 if (VALID_STAT(smb_fname
->st
)) {
7227 if (S_ISDIR(smb_fname
->st
.st_ex_mode
)) {
7228 ptype
= PERM_EXISTING_DIR
;
7230 ptype
= PERM_EXISTING_FILE
;
7233 ptype
= PERM_NEW_FILE
;
7236 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
7238 if (!NT_STATUS_IS_OK(status
)) {
7242 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
7243 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
7244 smb_fname_str_dbg(smb_fname
), (double)size
,
7245 (unsigned int)set_owner
, (unsigned int)set_grp
,
7246 (int)raw_unixmode
));
7248 sbuf
= smb_fname
->st
;
7250 if (!VALID_STAT(sbuf
)) {
7252 * The only valid use of this is to create character and block
7253 * devices, and named pipes. This is deprecated (IMHO) and
7254 * a new info level should be used for mknod. JRA.
7257 status
= smb_unix_mknod(conn
,
7261 if (!NT_STATUS_IS_OK(status
)) {
7265 smb_fname_tmp
= cp_smb_filename(talloc_tos(), smb_fname
);
7266 if (smb_fname_tmp
== NULL
) {
7267 return NT_STATUS_NO_MEMORY
;
7270 if (SMB_VFS_STAT(conn
, smb_fname_tmp
) != 0) {
7271 status
= map_nt_error_from_unix(errno
);
7272 TALLOC_FREE(smb_fname_tmp
);
7273 SMB_VFS_UNLINK(conn
, smb_fname
);
7277 sbuf
= smb_fname_tmp
->st
;
7278 smb_fname
= smb_fname_tmp
;
7280 /* Ensure we don't try and change anything else. */
7281 raw_unixmode
= SMB_MODE_NO_CHANGE
;
7282 size
= get_file_size_stat(&sbuf
);
7283 ft
.atime
= sbuf
.st_ex_atime
;
7284 ft
.mtime
= sbuf
.st_ex_mtime
;
7286 * We continue here as we might want to change the
7289 delete_on_fail
= True
;
7293 /* Horrible backwards compatibility hack as an old server bug
7294 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
7298 size
= get_file_size_stat(&sbuf
);
7303 * Deal with the UNIX specific mode set.
7306 if (raw_unixmode
!= SMB_MODE_NO_CHANGE
) {
7309 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7310 "setting mode 0%o for file %s\n",
7311 (unsigned int)unixmode
,
7312 smb_fname_str_dbg(smb_fname
)));
7313 if (fsp
&& fsp
->fh
->fd
!= -1) {
7314 ret
= SMB_VFS_FCHMOD(fsp
, unixmode
);
7316 ret
= SMB_VFS_CHMOD(conn
, smb_fname
->base_name
, unixmode
);
7319 return map_nt_error_from_unix(errno
);
7324 * Deal with the UNIX specific uid set.
7327 if ((set_owner
!= (uid_t
)SMB_UID_NO_CHANGE
) &&
7328 (sbuf
.st_ex_uid
!= set_owner
)) {
7331 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7332 "changing owner %u for path %s\n",
7333 (unsigned int)set_owner
,
7334 smb_fname_str_dbg(smb_fname
)));
7336 if (fsp
&& fsp
->fh
->fd
!= -1) {
7337 ret
= SMB_VFS_FCHOWN(fsp
, set_owner
, (gid_t
)-1);
7340 * UNIX extensions calls must always operate
7343 ret
= SMB_VFS_LCHOWN(conn
, smb_fname
->base_name
,
7344 set_owner
, (gid_t
)-1);
7348 status
= map_nt_error_from_unix(errno
);
7349 if (delete_on_fail
) {
7350 SMB_VFS_UNLINK(conn
, smb_fname
);
7357 * Deal with the UNIX specific gid set.
7360 if ((set_grp
!= (uid_t
)SMB_GID_NO_CHANGE
) &&
7361 (sbuf
.st_ex_gid
!= set_grp
)) {
7364 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7365 "changing group %u for file %s\n",
7366 (unsigned int)set_owner
,
7367 smb_fname_str_dbg(smb_fname
)));
7368 if (fsp
&& fsp
->fh
->fd
!= -1) {
7369 ret
= SMB_VFS_FCHOWN(fsp
, set_owner
, (gid_t
)-1);
7372 * UNIX extensions calls must always operate
7375 ret
= SMB_VFS_LCHOWN(conn
, smb_fname
->base_name
, (uid_t
)-1,
7379 status
= map_nt_error_from_unix(errno
);
7380 if (delete_on_fail
) {
7381 SMB_VFS_UNLINK(conn
, smb_fname
);
7387 /* Deal with any size changes. */
7389 status
= smb_set_file_size(conn
, req
,
7395 if (!NT_STATUS_IS_OK(status
)) {
7399 /* Deal with any time changes. */
7400 if (null_timespec(ft
.mtime
) && null_timespec(ft
.atime
)) {
7401 /* No change, don't cancel anything. */
7405 id
= vfs_file_id_from_sbuf(conn
, &sbuf
);
7406 for(all_fsps
= file_find_di_first(conn
->sconn
, id
); all_fsps
;
7407 all_fsps
= file_find_di_next(all_fsps
)) {
7409 * We're setting the time explicitly for UNIX.
7410 * Cancel any pending changes over all handles.
7412 all_fsps
->update_write_time_on_close
= false;
7413 TALLOC_FREE(all_fsps
->update_write_time_event
);
7417 * Override the "setting_write_time"
7418 * parameter here as it almost does what
7419 * we need. Just remember if we modified
7420 * mtime and send the notify ourselves.
7422 if (null_timespec(ft
.mtime
)) {
7423 modify_mtime
= false;
7426 status
= smb_set_file_time(conn
,
7432 notify_fname(conn
, NOTIFY_ACTION_MODIFIED
,
7433 FILE_NOTIFY_CHANGE_LAST_WRITE
, smb_fname
->base_name
);
7438 /****************************************************************************
7439 Deal with SMB_SET_FILE_UNIX_INFO2.
7440 ****************************************************************************/
7442 static NTSTATUS
smb_set_file_unix_info2(connection_struct
*conn
,
7443 struct smb_request
*req
,
7447 const struct smb_filename
*smb_fname
)
7453 if (total_data
< 116) {
7454 return NT_STATUS_INVALID_PARAMETER
;
7457 /* Start by setting all the fields that are common between UNIX_BASIC
7460 status
= smb_set_file_unix_basic(conn
, req
, pdata
, total_data
,
7462 if (!NT_STATUS_IS_OK(status
)) {
7466 smb_fflags
= IVAL(pdata
, 108);
7467 smb_fmask
= IVAL(pdata
, 112);
7469 /* NB: We should only attempt to alter the file flags if the client
7470 * sends a non-zero mask.
7472 if (smb_fmask
!= 0) {
7473 int stat_fflags
= 0;
7475 if (!map_info2_flags_to_sbuf(&smb_fname
->st
, smb_fflags
,
7476 smb_fmask
, &stat_fflags
)) {
7477 /* Client asked to alter a flag we don't understand. */
7478 return NT_STATUS_INVALID_PARAMETER
;
7481 if (fsp
&& fsp
->fh
->fd
!= -1) {
7482 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
7483 return NT_STATUS_NOT_SUPPORTED
;
7485 if (SMB_VFS_CHFLAGS(conn
, smb_fname
->base_name
,
7486 stat_fflags
) != 0) {
7487 return map_nt_error_from_unix(errno
);
7492 /* XXX: need to add support for changing the create_time here. You
7493 * can do this for paths on Darwin with setattrlist(2). The right way
7494 * to hook this up is probably by extending the VFS utimes interface.
7497 return NT_STATUS_OK
;
7500 /****************************************************************************
7501 Create a directory with POSIX semantics.
7502 ****************************************************************************/
7504 static NTSTATUS
smb_posix_mkdir(connection_struct
*conn
,
7505 struct smb_request
*req
,
7508 struct smb_filename
*smb_fname
,
7509 int *pdata_return_size
)
7511 NTSTATUS status
= NT_STATUS_OK
;
7512 uint32 raw_unixmode
= 0;
7513 uint32 mod_unixmode
= 0;
7514 mode_t unixmode
= (mode_t
)0;
7515 files_struct
*fsp
= NULL
;
7516 uint16 info_level_return
= 0;
7518 char *pdata
= *ppdata
;
7520 if (total_data
< 18) {
7521 return NT_STATUS_INVALID_PARAMETER
;
7524 raw_unixmode
= IVAL(pdata
,8);
7525 /* Next 4 bytes are not yet defined. */
7527 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
7528 PERM_NEW_DIR
, &unixmode
);
7529 if (!NT_STATUS_IS_OK(status
)) {
7533 mod_unixmode
= (uint32
)unixmode
| FILE_FLAG_POSIX_SEMANTICS
;
7535 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
7536 smb_fname_str_dbg(smb_fname
), (unsigned int)unixmode
));
7538 status
= SMB_VFS_CREATE_FILE(
7541 0, /* root_dir_fid */
7542 smb_fname
, /* fname */
7543 FILE_READ_ATTRIBUTES
, /* access_mask */
7544 FILE_SHARE_NONE
, /* share_access */
7545 FILE_CREATE
, /* create_disposition*/
7546 FILE_DIRECTORY_FILE
, /* create_options */
7547 mod_unixmode
, /* file_attributes */
7548 0, /* oplock_request */
7550 0, /* allocation_size */
7551 0, /* private_flags */
7556 NULL
, NULL
); /* create context */
7558 if (NT_STATUS_IS_OK(status
)) {
7559 close_file(req
, fsp
, NORMAL_CLOSE
);
7562 info_level_return
= SVAL(pdata
,16);
7564 if (info_level_return
== SMB_QUERY_FILE_UNIX_BASIC
) {
7565 *pdata_return_size
= 12 + SMB_FILE_UNIX_BASIC_SIZE
;
7566 } else if (info_level_return
== SMB_QUERY_FILE_UNIX_INFO2
) {
7567 *pdata_return_size
= 12 + SMB_FILE_UNIX_INFO2_SIZE
;
7569 *pdata_return_size
= 12;
7572 /* Realloc the data size */
7573 *ppdata
= (char *)SMB_REALLOC(*ppdata
,*pdata_return_size
);
7574 if (*ppdata
== NULL
) {
7575 *pdata_return_size
= 0;
7576 return NT_STATUS_NO_MEMORY
;
7580 SSVAL(pdata
,0,NO_OPLOCK_RETURN
);
7581 SSVAL(pdata
,2,0); /* No fnum. */
7582 SIVAL(pdata
,4,info
); /* Was directory created. */
7584 switch (info_level_return
) {
7585 case SMB_QUERY_FILE_UNIX_BASIC
:
7586 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_BASIC
);
7587 SSVAL(pdata
,10,0); /* Padding. */
7588 store_file_unix_basic(conn
, pdata
+ 12, fsp
,
7591 case SMB_QUERY_FILE_UNIX_INFO2
:
7592 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_INFO2
);
7593 SSVAL(pdata
,10,0); /* Padding. */
7594 store_file_unix_basic_info2(conn
, pdata
+ 12, fsp
,
7598 SSVAL(pdata
,8,SMB_NO_INFO_LEVEL_RETURNED
);
7599 SSVAL(pdata
,10,0); /* Padding. */
7606 /****************************************************************************
7607 Open/Create a file with POSIX semantics.
7608 ****************************************************************************/
7610 #define SMB_O_RDONLY_MAPPING (FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA)
7611 #define SMB_O_WRONLY_MAPPING (FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA)
7613 static NTSTATUS
smb_posix_open(connection_struct
*conn
,
7614 struct smb_request
*req
,
7617 struct smb_filename
*smb_fname
,
7618 int *pdata_return_size
)
7620 bool extended_oplock_granted
= False
;
7621 char *pdata
= *ppdata
;
7623 uint32 wire_open_mode
= 0;
7624 uint32 raw_unixmode
= 0;
7625 uint32 mod_unixmode
= 0;
7626 uint32 create_disp
= 0;
7627 uint32 access_mask
= 0;
7628 uint32 create_options
= FILE_NON_DIRECTORY_FILE
;
7629 NTSTATUS status
= NT_STATUS_OK
;
7630 mode_t unixmode
= (mode_t
)0;
7631 files_struct
*fsp
= NULL
;
7632 int oplock_request
= 0;
7634 uint16 info_level_return
= 0;
7636 if (total_data
< 18) {
7637 return NT_STATUS_INVALID_PARAMETER
;
7640 flags
= IVAL(pdata
,0);
7641 oplock_request
= (flags
& REQUEST_OPLOCK
) ? EXCLUSIVE_OPLOCK
: 0;
7642 if (oplock_request
) {
7643 oplock_request
|= (flags
& REQUEST_BATCH_OPLOCK
) ? BATCH_OPLOCK
: 0;
7646 wire_open_mode
= IVAL(pdata
,4);
7648 if (wire_open_mode
== (SMB_O_CREAT
|SMB_O_DIRECTORY
)) {
7649 return smb_posix_mkdir(conn
, req
,
7656 switch (wire_open_mode
& SMB_ACCMODE
) {
7658 access_mask
= SMB_O_RDONLY_MAPPING
;
7661 access_mask
= SMB_O_WRONLY_MAPPING
;
7664 access_mask
= (SMB_O_RDONLY_MAPPING
|
7665 SMB_O_WRONLY_MAPPING
);
7668 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
7669 (unsigned int)wire_open_mode
));
7670 return NT_STATUS_INVALID_PARAMETER
;
7673 wire_open_mode
&= ~SMB_ACCMODE
;
7675 /* First take care of O_CREAT|O_EXCL interactions. */
7676 switch (wire_open_mode
& (SMB_O_CREAT
| SMB_O_EXCL
)) {
7677 case (SMB_O_CREAT
| SMB_O_EXCL
):
7678 /* File exists fail. File not exist create. */
7679 create_disp
= FILE_CREATE
;
7682 /* File exists open. File not exist create. */
7683 create_disp
= FILE_OPEN_IF
;
7686 /* O_EXCL on its own without O_CREAT is undefined.
7687 We deliberately ignore it as some versions of
7688 Linux CIFSFS can send a bare O_EXCL on the
7689 wire which other filesystems in the kernel
7690 ignore. See bug 9519 for details. */
7695 /* File exists open. File not exist fail. */
7696 create_disp
= FILE_OPEN
;
7699 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
7700 (unsigned int)wire_open_mode
));
7701 return NT_STATUS_INVALID_PARAMETER
;
7704 /* Next factor in the effects of O_TRUNC. */
7705 wire_open_mode
&= ~(SMB_O_CREAT
| SMB_O_EXCL
);
7707 if (wire_open_mode
& SMB_O_TRUNC
) {
7708 switch (create_disp
) {
7710 /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
7711 /* Leave create_disp alone as
7712 (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
7714 /* File exists fail. File not exist create. */
7717 /* SMB_O_CREAT | SMB_O_TRUNC */
7718 /* File exists overwrite. File not exist create. */
7719 create_disp
= FILE_OVERWRITE_IF
;
7723 /* File exists overwrite. File not exist fail. */
7724 create_disp
= FILE_OVERWRITE
;
7727 /* Cannot get here. */
7728 smb_panic("smb_posix_open: logic error");
7729 return NT_STATUS_INVALID_PARAMETER
;
7733 raw_unixmode
= IVAL(pdata
,8);
7734 /* Next 4 bytes are not yet defined. */
7736 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
7737 (VALID_STAT(smb_fname
->st
) ?
7738 PERM_EXISTING_FILE
: PERM_NEW_FILE
),
7741 if (!NT_STATUS_IS_OK(status
)) {
7745 mod_unixmode
= (uint32
)unixmode
| FILE_FLAG_POSIX_SEMANTICS
;
7747 if (wire_open_mode
& SMB_O_SYNC
) {
7748 create_options
|= FILE_WRITE_THROUGH
;
7750 if (wire_open_mode
& SMB_O_APPEND
) {
7751 access_mask
|= FILE_APPEND_DATA
;
7753 if (wire_open_mode
& SMB_O_DIRECT
) {
7754 mod_unixmode
|= FILE_FLAG_NO_BUFFERING
;
7757 if ((wire_open_mode
& SMB_O_DIRECTORY
) ||
7758 VALID_STAT_OF_DIR(smb_fname
->st
)) {
7759 if (access_mask
!= SMB_O_RDONLY_MAPPING
) {
7760 return NT_STATUS_FILE_IS_A_DIRECTORY
;
7762 create_options
&= ~FILE_NON_DIRECTORY_FILE
;
7763 create_options
|= FILE_DIRECTORY_FILE
;
7766 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
7767 smb_fname_str_dbg(smb_fname
),
7768 (unsigned int)wire_open_mode
,
7769 (unsigned int)unixmode
));
7771 status
= SMB_VFS_CREATE_FILE(
7774 0, /* root_dir_fid */
7775 smb_fname
, /* fname */
7776 access_mask
, /* access_mask */
7777 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
7779 create_disp
, /* create_disposition*/
7780 create_options
, /* create_options */
7781 mod_unixmode
, /* file_attributes */
7782 oplock_request
, /* oplock_request */
7784 0, /* allocation_size */
7785 0, /* private_flags */
7790 NULL
, NULL
); /* create context */
7792 if (!NT_STATUS_IS_OK(status
)) {
7796 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
7797 extended_oplock_granted
= True
;
7800 if(oplock_request
&& EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
7801 extended_oplock_granted
= True
;
7804 info_level_return
= SVAL(pdata
,16);
7806 /* Allocate the correct return size. */
7808 if (info_level_return
== SMB_QUERY_FILE_UNIX_BASIC
) {
7809 *pdata_return_size
= 12 + SMB_FILE_UNIX_BASIC_SIZE
;
7810 } else if (info_level_return
== SMB_QUERY_FILE_UNIX_INFO2
) {
7811 *pdata_return_size
= 12 + SMB_FILE_UNIX_INFO2_SIZE
;
7813 *pdata_return_size
= 12;
7816 /* Realloc the data size */
7817 *ppdata
= (char *)SMB_REALLOC(*ppdata
,*pdata_return_size
);
7818 if (*ppdata
== NULL
) {
7819 close_file(req
, fsp
, ERROR_CLOSE
);
7820 *pdata_return_size
= 0;
7821 return NT_STATUS_NO_MEMORY
;
7825 if (extended_oplock_granted
) {
7826 if (flags
& REQUEST_BATCH_OPLOCK
) {
7827 SSVAL(pdata
,0, BATCH_OPLOCK_RETURN
);
7829 SSVAL(pdata
,0, EXCLUSIVE_OPLOCK_RETURN
);
7831 } else if (fsp
->oplock_type
== LEVEL_II_OPLOCK
) {
7832 SSVAL(pdata
,0, LEVEL_II_OPLOCK_RETURN
);
7834 SSVAL(pdata
,0,NO_OPLOCK_RETURN
);
7837 SSVAL(pdata
,2,fsp
->fnum
);
7838 SIVAL(pdata
,4,info
); /* Was file created etc. */
7840 switch (info_level_return
) {
7841 case SMB_QUERY_FILE_UNIX_BASIC
:
7842 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_BASIC
);
7843 SSVAL(pdata
,10,0); /* padding. */
7844 store_file_unix_basic(conn
, pdata
+ 12, fsp
,
7847 case SMB_QUERY_FILE_UNIX_INFO2
:
7848 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_INFO2
);
7849 SSVAL(pdata
,10,0); /* padding. */
7850 store_file_unix_basic_info2(conn
, pdata
+ 12, fsp
,
7854 SSVAL(pdata
,8,SMB_NO_INFO_LEVEL_RETURNED
);
7855 SSVAL(pdata
,10,0); /* padding. */
7858 return NT_STATUS_OK
;
7861 /****************************************************************************
7862 Delete a file with POSIX semantics.
7863 ****************************************************************************/
7865 static NTSTATUS
smb_posix_unlink(connection_struct
*conn
,
7866 struct smb_request
*req
,
7869 struct smb_filename
*smb_fname
)
7871 NTSTATUS status
= NT_STATUS_OK
;
7872 files_struct
*fsp
= NULL
;
7876 int create_options
= 0;
7878 struct share_mode_lock
*lck
= NULL
;
7880 if (total_data
< 2) {
7881 return NT_STATUS_INVALID_PARAMETER
;
7884 flags
= SVAL(pdata
,0);
7886 if (!VALID_STAT(smb_fname
->st
)) {
7887 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
7890 if ((flags
== SMB_POSIX_UNLINK_DIRECTORY_TARGET
) &&
7891 !VALID_STAT_OF_DIR(smb_fname
->st
)) {
7892 return NT_STATUS_NOT_A_DIRECTORY
;
7895 DEBUG(10,("smb_posix_unlink: %s %s\n",
7896 (flags
== SMB_POSIX_UNLINK_DIRECTORY_TARGET
) ? "directory" : "file",
7897 smb_fname_str_dbg(smb_fname
)));
7899 if (VALID_STAT_OF_DIR(smb_fname
->st
)) {
7900 create_options
|= FILE_DIRECTORY_FILE
;
7903 status
= SMB_VFS_CREATE_FILE(
7906 0, /* root_dir_fid */
7907 smb_fname
, /* fname */
7908 DELETE_ACCESS
, /* access_mask */
7909 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
7911 FILE_OPEN
, /* create_disposition*/
7912 create_options
, /* create_options */
7913 FILE_FLAG_POSIX_SEMANTICS
|0777, /* file_attributes */
7914 0, /* oplock_request */
7916 0, /* allocation_size */
7917 0, /* private_flags */
7922 NULL
, NULL
); /* create context */
7924 if (!NT_STATUS_IS_OK(status
)) {
7929 * Don't lie to client. If we can't really delete due to
7930 * non-POSIX opens return SHARING_VIOLATION.
7933 lck
= get_existing_share_mode_lock(talloc_tos(), fsp
->file_id
);
7935 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
7936 "lock for file %s\n", fsp_str_dbg(fsp
)));
7937 close_file(req
, fsp
, NORMAL_CLOSE
);
7938 return NT_STATUS_INVALID_PARAMETER
;
7942 * See if others still have the file open. If this is the case, then
7943 * don't delete. If all opens are POSIX delete we can set the delete
7944 * on close disposition.
7946 for (i
=0; i
<lck
->data
->num_share_modes
; i
++) {
7947 struct share_mode_entry
*e
= &lck
->data
->share_modes
[i
];
7948 if (is_valid_share_mode_entry(e
)) {
7949 if (e
->flags
& SHARE_MODE_FLAG_POSIX_OPEN
) {
7952 if (share_mode_stale_pid(lck
->data
, i
)) {
7955 /* Fail with sharing violation. */
7957 close_file(req
, fsp
, NORMAL_CLOSE
);
7958 return NT_STATUS_SHARING_VIOLATION
;
7963 * Set the delete on close.
7965 status
= smb_set_file_disposition_info(conn
,
7973 if (!NT_STATUS_IS_OK(status
)) {
7974 close_file(req
, fsp
, NORMAL_CLOSE
);
7977 return close_file(req
, fsp
, NORMAL_CLOSE
);
7980 NTSTATUS
smbd_do_setfilepathinfo(connection_struct
*conn
,
7981 struct smb_request
*req
,
7982 TALLOC_CTX
*mem_ctx
,
7983 uint16_t info_level
,
7985 struct smb_filename
*smb_fname
,
7986 char **ppdata
, int total_data
,
7989 char *pdata
= *ppdata
;
7990 NTSTATUS status
= NT_STATUS_OK
;
7991 int data_return_size
= 0;
7995 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
7996 return NT_STATUS_INVALID_LEVEL
;
7999 if (!CAN_WRITE(conn
)) {
8000 /* Allow POSIX opens. The open path will deny
8001 * any non-readonly opens. */
8002 if (info_level
!= SMB_POSIX_PATH_OPEN
) {
8003 return NT_STATUS_DOS(ERRSRV
, ERRaccess
);
8007 DEBUG(3,("smbd_do_setfilepathinfo: %s (%s) info_level=%d "
8008 "totdata=%d\n", smb_fname_str_dbg(smb_fname
),
8010 info_level
, total_data
));
8012 switch (info_level
) {
8014 case SMB_INFO_STANDARD
:
8016 status
= smb_set_info_standard(conn
,
8024 case SMB_INFO_SET_EA
:
8026 status
= smb_info_set_ea(conn
,
8034 case SMB_SET_FILE_BASIC_INFO
:
8035 case SMB_FILE_BASIC_INFORMATION
:
8037 status
= smb_set_file_basic_info(conn
,
8045 case SMB_FILE_ALLOCATION_INFORMATION
:
8046 case SMB_SET_FILE_ALLOCATION_INFO
:
8048 status
= smb_set_file_allocation_info(conn
, req
,
8056 case SMB_FILE_END_OF_FILE_INFORMATION
:
8057 case SMB_SET_FILE_END_OF_FILE_INFO
:
8060 * XP/Win7 both fail after the createfile with
8061 * SMB_SET_FILE_END_OF_FILE_INFO but not
8062 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
8063 * The level is known here, so pass it down
8067 (info_level
== SMB_SET_FILE_END_OF_FILE_INFO
);
8069 status
= smb_set_file_end_of_file_info(conn
, req
,
8078 case SMB_FILE_DISPOSITION_INFORMATION
:
8079 case SMB_SET_FILE_DISPOSITION_INFO
: /* Set delete on close for open file. */
8082 /* JRA - We used to just ignore this on a path ?
8083 * Shouldn't this be invalid level on a pathname
8086 if (tran_call
!= TRANSACT2_SETFILEINFO
) {
8087 return ERROR_NT(NT_STATUS_INVALID_LEVEL
);
8090 status
= smb_set_file_disposition_info(conn
,
8098 case SMB_FILE_POSITION_INFORMATION
:
8100 status
= smb_file_position_information(conn
,
8107 case SMB_FILE_FULL_EA_INFORMATION
:
8109 status
= smb_set_file_full_ea_info(conn
,
8116 /* From tridge Samba4 :
8117 * MODE_INFORMATION in setfileinfo (I have no
8118 * idea what "mode information" on a file is - it takes a value of 0,
8119 * 2, 4 or 6. What could it be?).
8122 case SMB_FILE_MODE_INFORMATION
:
8124 status
= smb_file_mode_information(conn
,
8131 * CIFS UNIX extensions.
8134 case SMB_SET_FILE_UNIX_BASIC
:
8136 status
= smb_set_file_unix_basic(conn
, req
,
8144 case SMB_SET_FILE_UNIX_INFO2
:
8146 status
= smb_set_file_unix_info2(conn
, req
,
8154 case SMB_SET_FILE_UNIX_LINK
:
8157 /* We must have a pathname for this. */
8158 return NT_STATUS_INVALID_LEVEL
;
8160 status
= smb_set_file_unix_link(conn
, req
, pdata
,
8161 total_data
, smb_fname
);
8165 case SMB_SET_FILE_UNIX_HLINK
:
8168 /* We must have a pathname for this. */
8169 return NT_STATUS_INVALID_LEVEL
;
8171 status
= smb_set_file_unix_hlink(conn
, req
,
8177 case SMB_FILE_RENAME_INFORMATION
:
8179 status
= smb_file_rename_information(conn
, req
,
8185 case SMB2_FILE_RENAME_INFORMATION_INTERNAL
:
8187 /* SMB2 rename information. */
8188 status
= smb2_file_rename_information(conn
, req
,
8194 case SMB_FILE_LINK_INFORMATION
:
8196 status
= smb_file_link_information(conn
, req
,
8202 #if defined(HAVE_POSIX_ACLS)
8203 case SMB_SET_POSIX_ACL
:
8205 status
= smb_set_posix_acl(conn
,
8214 case SMB_SET_POSIX_LOCK
:
8217 return NT_STATUS_INVALID_LEVEL
;
8219 status
= smb_set_posix_lock(conn
, req
,
8220 pdata
, total_data
, fsp
);
8224 case SMB_POSIX_PATH_OPEN
:
8227 /* We must have a pathname for this. */
8228 return NT_STATUS_INVALID_LEVEL
;
8231 status
= smb_posix_open(conn
, req
,
8239 case SMB_POSIX_PATH_UNLINK
:
8242 /* We must have a pathname for this. */
8243 return NT_STATUS_INVALID_LEVEL
;
8246 status
= smb_posix_unlink(conn
, req
,
8254 return NT_STATUS_INVALID_LEVEL
;
8257 if (!NT_STATUS_IS_OK(status
)) {
8261 *ret_data_size
= data_return_size
;
8262 return NT_STATUS_OK
;
8265 /****************************************************************************
8266 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
8267 ****************************************************************************/
8269 static void call_trans2setfilepathinfo(connection_struct
*conn
,
8270 struct smb_request
*req
,
8271 unsigned int tran_call
,
8272 char **pparams
, int total_params
,
8273 char **ppdata
, int total_data
,
8274 unsigned int max_data_bytes
)
8276 char *params
= *pparams
;
8277 char *pdata
= *ppdata
;
8279 struct smb_filename
*smb_fname
= NULL
;
8280 files_struct
*fsp
= NULL
;
8281 NTSTATUS status
= NT_STATUS_OK
;
8282 int data_return_size
= 0;
8285 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8289 if (tran_call
== TRANSACT2_SETFILEINFO
) {
8290 if (total_params
< 4) {
8291 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8295 fsp
= file_fsp(req
, SVAL(params
,0));
8296 /* Basic check for non-null fsp. */
8297 if (!check_fsp_open(conn
, req
, fsp
)) {
8300 info_level
= SVAL(params
,2);
8302 smb_fname
= cp_smb_filename(talloc_tos(), fsp
->fsp_name
);
8303 if (smb_fname
== NULL
) {
8304 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8308 if(fsp
->fh
->fd
== -1) {
8310 * This is actually a SETFILEINFO on a directory
8311 * handle (returned from an NT SMB). NT5.0 seems
8312 * to do this call. JRA.
8314 if (INFO_LEVEL_IS_UNIX(info_level
)) {
8315 /* Always do lstat for UNIX calls. */
8316 if (SMB_VFS_LSTAT(conn
, smb_fname
)) {
8317 DEBUG(3,("call_trans2setfilepathinfo: "
8318 "SMB_VFS_LSTAT of %s failed "
8320 smb_fname_str_dbg(smb_fname
),
8322 reply_nterror(req
, map_nt_error_from_unix(errno
));
8326 if (SMB_VFS_STAT(conn
, smb_fname
) != 0) {
8327 DEBUG(3,("call_trans2setfilepathinfo: "
8328 "fileinfo of %s failed (%s)\n",
8329 smb_fname_str_dbg(smb_fname
),
8331 reply_nterror(req
, map_nt_error_from_unix(errno
));
8335 } else if (fsp
->print_file
) {
8337 * Doing a DELETE_ON_CLOSE should cancel a print job.
8339 if ((info_level
== SMB_SET_FILE_DISPOSITION_INFO
) && CVAL(pdata
,0)) {
8340 fsp
->fh
->private_options
|= NTCREATEX_OPTIONS_PRIVATE_DELETE_ON_CLOSE
;
8342 DEBUG(3,("call_trans2setfilepathinfo: "
8343 "Cancelling print job (%s)\n",
8347 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 2,
8353 NT_STATUS_OBJECT_PATH_NOT_FOUND
);
8358 * Original code - this is an open file.
8360 if (SMB_VFS_FSTAT(fsp
, &smb_fname
->st
) != 0) {
8361 DEBUG(3,("call_trans2setfilepathinfo: fstat "
8362 "of %s failed (%s)\n", fsp_fnum_dbg(fsp
),
8364 reply_nterror(req
, map_nt_error_from_unix(errno
));
8370 uint32_t ucf_flags
= 0;
8373 if (total_params
< 7) {
8374 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8378 info_level
= SVAL(params
,0);
8379 srvstr_get_path(req
, params
, req
->flags2
, &fname
, ¶ms
[6],
8380 total_params
- 6, STR_TERMINATE
,
8382 if (!NT_STATUS_IS_OK(status
)) {
8383 reply_nterror(req
, status
);
8387 if (info_level
== SMB_SET_FILE_UNIX_BASIC
||
8388 info_level
== SMB_SET_FILE_UNIX_INFO2
||
8389 info_level
== SMB_FILE_RENAME_INFORMATION
||
8390 info_level
== SMB_POSIX_PATH_UNLINK
) {
8391 ucf_flags
|= UCF_UNIX_NAME_LOOKUP
;
8394 status
= filename_convert(req
, conn
,
8395 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
8400 if (!NT_STATUS_IS_OK(status
)) {
8401 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
8402 reply_botherror(req
,
8403 NT_STATUS_PATH_NOT_COVERED
,
8404 ERRSRV
, ERRbadpath
);
8407 reply_nterror(req
, status
);
8411 if (INFO_LEVEL_IS_UNIX(info_level
)) {
8413 * For CIFS UNIX extensions the target name may not exist.
8416 /* Always do lstat for UNIX calls. */
8417 SMB_VFS_LSTAT(conn
, smb_fname
);
8419 } else if (!VALID_STAT(smb_fname
->st
) &&
8420 SMB_VFS_STAT(conn
, smb_fname
)) {
8421 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
8423 smb_fname_str_dbg(smb_fname
),
8425 reply_nterror(req
, map_nt_error_from_unix(errno
));
8430 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (%s) info_level=%d "
8431 "totdata=%d\n", tran_call
, smb_fname_str_dbg(smb_fname
),
8433 info_level
,total_data
));
8435 /* Realloc the parameter size */
8436 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
8437 if (*pparams
== NULL
) {
8438 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8445 status
= smbd_do_setfilepathinfo(conn
, req
, req
,
8451 if (!NT_STATUS_IS_OK(status
)) {
8452 if (open_was_deferred(req
->xconn
, req
->mid
)) {
8453 /* We have re-scheduled this call. */
8456 if (blocking_lock_was_deferred_smb1(req
->sconn
, req
->mid
)) {
8457 /* We have re-scheduled this call. */
8460 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
8461 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
8462 ERRSRV
, ERRbadpath
);
8465 if (info_level
== SMB_POSIX_PATH_OPEN
) {
8466 reply_openerror(req
, status
);
8471 * Invalid EA name needs to return 2 param bytes,
8472 * not a zero-length error packet.
8474 if (NT_STATUS_EQUAL(status
, STATUS_INVALID_EA_NAME
)) {
8475 send_trans2_replies(conn
, req
, status
, params
, 2, NULL
, 0,
8478 reply_nterror(req
, status
);
8483 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 2, *ppdata
, data_return_size
,
8489 /****************************************************************************
8490 Reply to a TRANS2_MKDIR (make directory with extended attributes).
8491 ****************************************************************************/
8493 static void call_trans2mkdir(connection_struct
*conn
, struct smb_request
*req
,
8494 char **pparams
, int total_params
,
8495 char **ppdata
, int total_data
,
8496 unsigned int max_data_bytes
)
8498 struct smb_filename
*smb_dname
= NULL
;
8499 char *params
= *pparams
;
8500 char *pdata
= *ppdata
;
8501 char *directory
= NULL
;
8502 NTSTATUS status
= NT_STATUS_OK
;
8503 struct ea_list
*ea_list
= NULL
;
8504 TALLOC_CTX
*ctx
= talloc_tos();
8506 if (!CAN_WRITE(conn
)) {
8507 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
8511 if (total_params
< 5) {
8512 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8516 srvstr_get_path(ctx
, params
, req
->flags2
, &directory
, ¶ms
[4],
8517 total_params
- 4, STR_TERMINATE
,
8519 if (!NT_STATUS_IS_OK(status
)) {
8520 reply_nterror(req
, status
);
8524 DEBUG(3,("call_trans2mkdir : name = %s\n", directory
));
8526 status
= filename_convert(ctx
,
8528 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
8534 if (!NT_STATUS_IS_OK(status
)) {
8535 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
8536 reply_botherror(req
,
8537 NT_STATUS_PATH_NOT_COVERED
,
8538 ERRSRV
, ERRbadpath
);
8541 reply_nterror(req
, status
);
8546 * OS/2 workplace shell seems to send SET_EA requests of "null"
8547 * length (4 bytes containing IVAL 4).
8548 * They seem to have no effect. Bug #3212. JRA.
8551 if (total_data
&& (total_data
!= 4)) {
8552 /* Any data in this call is an EA list. */
8553 if (total_data
< 10) {
8554 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8558 if (IVAL(pdata
,0) > total_data
) {
8559 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
8560 IVAL(pdata
,0), (unsigned int)total_data
));
8561 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8565 ea_list
= read_ea_list(talloc_tos(), pdata
+ 4,
8568 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8572 if (!lp_ea_support(SNUM(conn
))) {
8573 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
8577 /* If total_data == 4 Windows doesn't care what values
8578 * are placed in that field, it just ignores them.
8579 * The System i QNTC IBM SMB client puts bad values here,
8580 * so ignore them. */
8582 status
= create_directory(conn
, req
, smb_dname
);
8584 if (!NT_STATUS_IS_OK(status
)) {
8585 reply_nterror(req
, status
);
8589 /* Try and set any given EA. */
8591 status
= set_ea(conn
, NULL
, smb_dname
, ea_list
);
8592 if (!NT_STATUS_IS_OK(status
)) {
8593 reply_nterror(req
, status
);
8598 /* Realloc the parameter and data sizes */
8599 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
8600 if(*pparams
== NULL
) {
8601 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8608 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 2, *ppdata
, 0, max_data_bytes
);
8611 TALLOC_FREE(smb_dname
);
8615 /****************************************************************************
8616 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
8617 We don't actually do this - we just send a null response.
8618 ****************************************************************************/
8620 static void call_trans2findnotifyfirst(connection_struct
*conn
,
8621 struct smb_request
*req
,
8622 char **pparams
, int total_params
,
8623 char **ppdata
, int total_data
,
8624 unsigned int max_data_bytes
)
8626 char *params
= *pparams
;
8629 if (total_params
< 6) {
8630 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8634 info_level
= SVAL(params
,4);
8635 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level
));
8637 switch (info_level
) {
8642 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
8646 /* Realloc the parameter and data sizes */
8647 *pparams
= (char *)SMB_REALLOC(*pparams
,6);
8648 if (*pparams
== NULL
) {
8649 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8654 SSVAL(params
,0,fnf_handle
);
8655 SSVAL(params
,2,0); /* No changes */
8656 SSVAL(params
,4,0); /* No EA errors */
8663 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 6, *ppdata
, 0, max_data_bytes
);
8668 /****************************************************************************
8669 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
8670 changes). Currently this does nothing.
8671 ****************************************************************************/
8673 static void call_trans2findnotifynext(connection_struct
*conn
,
8674 struct smb_request
*req
,
8675 char **pparams
, int total_params
,
8676 char **ppdata
, int total_data
,
8677 unsigned int max_data_bytes
)
8679 char *params
= *pparams
;
8681 DEBUG(3,("call_trans2findnotifynext\n"));
8683 /* Realloc the parameter and data sizes */
8684 *pparams
= (char *)SMB_REALLOC(*pparams
,4);
8685 if (*pparams
== NULL
) {
8686 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8691 SSVAL(params
,0,0); /* No changes */
8692 SSVAL(params
,2,0); /* No EA errors */
8694 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 4, *ppdata
, 0, max_data_bytes
);
8699 /****************************************************************************
8700 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
8701 ****************************************************************************/
8703 static void call_trans2getdfsreferral(connection_struct
*conn
,
8704 struct smb_request
*req
,
8705 char **pparams
, int total_params
,
8706 char **ppdata
, int total_data
,
8707 unsigned int max_data_bytes
)
8709 char *params
= *pparams
;
8710 char *pathname
= NULL
;
8712 int max_referral_level
;
8713 NTSTATUS status
= NT_STATUS_OK
;
8714 TALLOC_CTX
*ctx
= talloc_tos();
8716 DEBUG(10,("call_trans2getdfsreferral\n"));
8718 if (total_params
< 3) {
8719 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8723 max_referral_level
= SVAL(params
,0);
8725 if(!lp_host_msdfs()) {
8726 reply_nterror(req
, NT_STATUS_NOT_IMPLEMENTED
);
8730 srvstr_pull_talloc(ctx
, params
, req
->flags2
, &pathname
, ¶ms
[2],
8731 total_params
- 2, STR_TERMINATE
);
8733 reply_nterror(req
, NT_STATUS_NOT_FOUND
);
8736 if((reply_size
= setup_dfs_referral(conn
, pathname
, max_referral_level
,
8737 ppdata
,&status
)) < 0) {
8738 reply_nterror(req
, status
);
8742 SSVAL((discard_const_p(uint8_t, req
->inbuf
)), smb_flg2
,
8743 SVAL(req
->inbuf
,smb_flg2
) | FLAGS2_DFS_PATHNAMES
);
8744 send_trans2_replies(conn
, req
, NT_STATUS_OK
, 0,0,*ppdata
,reply_size
, max_data_bytes
);
8749 #define LMCAT_SPL 0x53
8750 #define LMFUNC_GETJOBID 0x60
8752 /****************************************************************************
8753 Reply to a TRANS2_IOCTL - used for OS/2 printing.
8754 ****************************************************************************/
8756 static void call_trans2ioctl(connection_struct
*conn
,
8757 struct smb_request
*req
,
8758 char **pparams
, int total_params
,
8759 char **ppdata
, int total_data
,
8760 unsigned int max_data_bytes
)
8762 char *pdata
= *ppdata
;
8763 files_struct
*fsp
= file_fsp(req
, SVAL(req
->vwv
+15, 0));
8767 /* check for an invalid fid before proceeding */
8770 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
8774 if ((SVAL(req
->vwv
+16, 0) == LMCAT_SPL
)
8775 && (SVAL(req
->vwv
+17, 0) == LMFUNC_GETJOBID
)) {
8776 *ppdata
= (char *)SMB_REALLOC(*ppdata
, 32);
8777 if (*ppdata
== NULL
) {
8778 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8783 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
8784 CAN ACCEPT THIS IN UNICODE. JRA. */
8787 SSVAL(pdata
, 0, print_spool_rap_jobid(fsp
->print_file
));
8789 status
= srvstr_push(pdata
, req
->flags2
, pdata
+ 2,
8790 lp_netbios_name(), 15,
8791 STR_ASCII
|STR_TERMINATE
, &len
); /* Our NetBIOS name */
8792 if (!NT_STATUS_IS_OK(status
)) {
8793 reply_nterror(req
, status
);
8796 status
= srvstr_push(pdata
, req
->flags2
, pdata
+18,
8797 lp_servicename(talloc_tos(), SNUM(conn
)), 13,
8798 STR_ASCII
|STR_TERMINATE
, &len
); /* Service name */
8799 if (!NT_STATUS_IS_OK(status
)) {
8800 reply_nterror(req
, status
);
8803 send_trans2_replies(conn
, req
, NT_STATUS_OK
, *pparams
, 0, *ppdata
, 32,
8808 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
8809 reply_nterror(req
, NT_STATUS_NOT_IMPLEMENTED
);
8812 /****************************************************************************
8813 Reply to a SMBfindclose (stop trans2 directory search).
8814 ****************************************************************************/
8816 void reply_findclose(struct smb_request
*req
)
8819 struct smbd_server_connection
*sconn
= req
->sconn
;
8821 START_PROFILE(SMBfindclose
);
8824 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8825 END_PROFILE(SMBfindclose
);
8829 dptr_num
= SVALS(req
->vwv
+0, 0);
8831 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num
));
8833 dptr_close(sconn
, &dptr_num
);
8835 reply_outbuf(req
, 0, 0);
8837 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num
));
8839 END_PROFILE(SMBfindclose
);
8843 /****************************************************************************
8844 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
8845 ****************************************************************************/
8847 void reply_findnclose(struct smb_request
*req
)
8851 START_PROFILE(SMBfindnclose
);
8854 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8855 END_PROFILE(SMBfindnclose
);
8859 dptr_num
= SVAL(req
->vwv
+0, 0);
8861 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num
));
8863 /* We never give out valid handles for a
8864 findnotifyfirst - so any dptr_num is ok here.
8867 reply_outbuf(req
, 0, 0);
8869 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num
));
8871 END_PROFILE(SMBfindnclose
);
8875 static void handle_trans2(connection_struct
*conn
, struct smb_request
*req
,
8876 struct trans_state
*state
)
8878 if (get_Protocol() >= PROTOCOL_NT1
) {
8879 req
->flags2
|= 0x40; /* IS_LONG_NAME */
8880 SSVAL((discard_const_p(uint8_t, req
->inbuf
)),smb_flg2
,req
->flags2
);
8883 if (ENCRYPTION_REQUIRED(conn
) && !req
->encrypted
) {
8884 if (state
->call
!= TRANSACT2_QFSINFO
&&
8885 state
->call
!= TRANSACT2_SETFSINFO
) {
8886 DEBUG(0,("handle_trans2: encryption required "
8888 (unsigned int)state
->call
));
8889 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
8894 SMB_PERFCOUNT_SET_SUBOP(&req
->pcd
, state
->call
);
8896 /* Now we must call the relevant TRANS2 function */
8897 switch(state
->call
) {
8898 case TRANSACT2_OPEN
:
8900 START_PROFILE(Trans2_open
);
8901 call_trans2open(conn
, req
,
8902 &state
->param
, state
->total_param
,
8903 &state
->data
, state
->total_data
,
8904 state
->max_data_return
);
8905 END_PROFILE(Trans2_open
);
8909 case TRANSACT2_FINDFIRST
:
8911 START_PROFILE(Trans2_findfirst
);
8912 call_trans2findfirst(conn
, req
,
8913 &state
->param
, state
->total_param
,
8914 &state
->data
, state
->total_data
,
8915 state
->max_data_return
);
8916 END_PROFILE(Trans2_findfirst
);
8920 case TRANSACT2_FINDNEXT
:
8922 START_PROFILE(Trans2_findnext
);
8923 call_trans2findnext(conn
, req
,
8924 &state
->param
, state
->total_param
,
8925 &state
->data
, state
->total_data
,
8926 state
->max_data_return
);
8927 END_PROFILE(Trans2_findnext
);
8931 case TRANSACT2_QFSINFO
:
8933 START_PROFILE(Trans2_qfsinfo
);
8934 call_trans2qfsinfo(conn
, req
,
8935 &state
->param
, state
->total_param
,
8936 &state
->data
, state
->total_data
,
8937 state
->max_data_return
);
8938 END_PROFILE(Trans2_qfsinfo
);
8942 case TRANSACT2_SETFSINFO
:
8944 START_PROFILE(Trans2_setfsinfo
);
8945 call_trans2setfsinfo(conn
, req
,
8946 &state
->param
, state
->total_param
,
8947 &state
->data
, state
->total_data
,
8948 state
->max_data_return
);
8949 END_PROFILE(Trans2_setfsinfo
);
8953 case TRANSACT2_QPATHINFO
:
8954 case TRANSACT2_QFILEINFO
:
8956 START_PROFILE(Trans2_qpathinfo
);
8957 call_trans2qfilepathinfo(conn
, req
, state
->call
,
8958 &state
->param
, state
->total_param
,
8959 &state
->data
, state
->total_data
,
8960 state
->max_data_return
);
8961 END_PROFILE(Trans2_qpathinfo
);
8965 case TRANSACT2_SETPATHINFO
:
8966 case TRANSACT2_SETFILEINFO
:
8968 START_PROFILE(Trans2_setpathinfo
);
8969 call_trans2setfilepathinfo(conn
, req
, state
->call
,
8970 &state
->param
, state
->total_param
,
8971 &state
->data
, state
->total_data
,
8972 state
->max_data_return
);
8973 END_PROFILE(Trans2_setpathinfo
);
8977 case TRANSACT2_FINDNOTIFYFIRST
:
8979 START_PROFILE(Trans2_findnotifyfirst
);
8980 call_trans2findnotifyfirst(conn
, req
,
8981 &state
->param
, state
->total_param
,
8982 &state
->data
, state
->total_data
,
8983 state
->max_data_return
);
8984 END_PROFILE(Trans2_findnotifyfirst
);
8988 case TRANSACT2_FINDNOTIFYNEXT
:
8990 START_PROFILE(Trans2_findnotifynext
);
8991 call_trans2findnotifynext(conn
, req
,
8992 &state
->param
, state
->total_param
,
8993 &state
->data
, state
->total_data
,
8994 state
->max_data_return
);
8995 END_PROFILE(Trans2_findnotifynext
);
8999 case TRANSACT2_MKDIR
:
9001 START_PROFILE(Trans2_mkdir
);
9002 call_trans2mkdir(conn
, req
,
9003 &state
->param
, state
->total_param
,
9004 &state
->data
, state
->total_data
,
9005 state
->max_data_return
);
9006 END_PROFILE(Trans2_mkdir
);
9010 case TRANSACT2_GET_DFS_REFERRAL
:
9012 START_PROFILE(Trans2_get_dfs_referral
);
9013 call_trans2getdfsreferral(conn
, req
,
9014 &state
->param
, state
->total_param
,
9015 &state
->data
, state
->total_data
,
9016 state
->max_data_return
);
9017 END_PROFILE(Trans2_get_dfs_referral
);
9021 case TRANSACT2_IOCTL
:
9023 START_PROFILE(Trans2_ioctl
);
9024 call_trans2ioctl(conn
, req
,
9025 &state
->param
, state
->total_param
,
9026 &state
->data
, state
->total_data
,
9027 state
->max_data_return
);
9028 END_PROFILE(Trans2_ioctl
);
9033 /* Error in request */
9034 DEBUG(2,("Unknown request %d in trans2 call\n", state
->call
));
9035 reply_nterror(req
, NT_STATUS_NOT_IMPLEMENTED
);
9039 /****************************************************************************
9040 Reply to a SMBtrans2.
9041 ****************************************************************************/
9043 void reply_trans2(struct smb_request
*req
)
9045 connection_struct
*conn
= req
->conn
;
9050 unsigned int tran_call
;
9051 struct trans_state
*state
;
9054 START_PROFILE(SMBtrans2
);
9056 if (req
->wct
< 14) {
9057 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
9058 END_PROFILE(SMBtrans2
);
9062 dsoff
= SVAL(req
->vwv
+12, 0);
9063 dscnt
= SVAL(req
->vwv
+11, 0);
9064 psoff
= SVAL(req
->vwv
+10, 0);
9065 pscnt
= SVAL(req
->vwv
+9, 0);
9066 tran_call
= SVAL(req
->vwv
+14, 0);
9068 result
= allow_new_trans(conn
->pending_trans
, req
->mid
);
9069 if (!NT_STATUS_IS_OK(result
)) {
9070 DEBUG(2, ("Got invalid trans2 request: %s\n",
9071 nt_errstr(result
)));
9072 reply_nterror(req
, result
);
9073 END_PROFILE(SMBtrans2
);
9078 switch (tran_call
) {
9079 /* List the allowed trans2 calls on IPC$ */
9080 case TRANSACT2_OPEN
:
9081 case TRANSACT2_GET_DFS_REFERRAL
:
9082 case TRANSACT2_QFILEINFO
:
9083 case TRANSACT2_QFSINFO
:
9084 case TRANSACT2_SETFSINFO
:
9087 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
9088 END_PROFILE(SMBtrans2
);
9093 if ((state
= talloc(conn
, struct trans_state
)) == NULL
) {
9094 DEBUG(0, ("talloc failed\n"));
9095 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
9096 END_PROFILE(SMBtrans2
);
9100 state
->cmd
= SMBtrans2
;
9102 state
->mid
= req
->mid
;
9103 state
->vuid
= req
->vuid
;
9104 state
->setup_count
= SVAL(req
->vwv
+13, 0);
9105 state
->setup
= NULL
;
9106 state
->total_param
= SVAL(req
->vwv
+0, 0);
9107 state
->param
= NULL
;
9108 state
->total_data
= SVAL(req
->vwv
+1, 0);
9110 state
->max_param_return
= SVAL(req
->vwv
+2, 0);
9111 state
->max_data_return
= SVAL(req
->vwv
+3, 0);
9112 state
->max_setup_return
= SVAL(req
->vwv
+4, 0);
9113 state
->close_on_completion
= BITSETW(req
->vwv
+5, 0);
9114 state
->one_way
= BITSETW(req
->vwv
+5, 1);
9116 state
->call
= tran_call
;
9118 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
9119 is so as a sanity check */
9120 if (state
->setup_count
!= 1) {
9122 * Need to have rc=0 for ioctl to get job id for OS/2.
9123 * Network printing will fail if function is not successful.
9124 * Similar function in reply.c will be used if protocol
9125 * is LANMAN1.0 instead of LM1.2X002.
9126 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
9127 * outbuf doesn't have to be set(only job id is used).
9129 if ( (state
->setup_count
== 4)
9130 && (tran_call
== TRANSACT2_IOCTL
)
9131 && (SVAL(req
->vwv
+16, 0) == LMCAT_SPL
)
9132 && (SVAL(req
->vwv
+17, 0) == LMFUNC_GETJOBID
)) {
9133 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
9135 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state
->setup_count
));
9136 DEBUG(2,("Transaction is %d\n",tran_call
));
9138 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
9139 END_PROFILE(SMBtrans2
);
9144 if ((dscnt
> state
->total_data
) || (pscnt
> state
->total_param
))
9147 if (state
->total_data
) {
9149 if (trans_oob(state
->total_data
, 0, dscnt
)
9150 || trans_oob(smb_len(req
->inbuf
), dsoff
, dscnt
)) {
9154 /* Can't use talloc here, the core routines do realloc on the
9155 * params and data. */
9156 state
->data
= (char *)SMB_MALLOC(state
->total_data
);
9157 if (state
->data
== NULL
) {
9158 DEBUG(0,("reply_trans2: data malloc fail for %u "
9159 "bytes !\n", (unsigned int)state
->total_data
));
9161 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
9162 END_PROFILE(SMBtrans2
);
9166 memcpy(state
->data
,smb_base(req
->inbuf
)+dsoff
,dscnt
);
9169 if (state
->total_param
) {
9171 if (trans_oob(state
->total_param
, 0, pscnt
)
9172 || trans_oob(smb_len(req
->inbuf
), psoff
, pscnt
)) {
9176 /* Can't use talloc here, the core routines do realloc on the
9177 * params and data. */
9178 state
->param
= (char *)SMB_MALLOC(state
->total_param
);
9179 if (state
->param
== NULL
) {
9180 DEBUG(0,("reply_trans: param malloc fail for %u "
9181 "bytes !\n", (unsigned int)state
->total_param
));
9182 SAFE_FREE(state
->data
);
9184 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
9185 END_PROFILE(SMBtrans2
);
9189 memcpy(state
->param
,smb_base(req
->inbuf
)+psoff
,pscnt
);
9192 state
->received_data
= dscnt
;
9193 state
->received_param
= pscnt
;
9195 if ((state
->received_param
== state
->total_param
) &&
9196 (state
->received_data
== state
->total_data
)) {
9198 handle_trans2(conn
, req
, state
);
9200 SAFE_FREE(state
->data
);
9201 SAFE_FREE(state
->param
);
9203 END_PROFILE(SMBtrans2
);
9207 DLIST_ADD(conn
->pending_trans
, state
);
9209 /* We need to send an interim response then receive the rest
9210 of the parameter/data bytes */
9211 reply_outbuf(req
, 0, 0);
9212 show_msg((char *)req
->outbuf
);
9213 END_PROFILE(SMBtrans2
);
9218 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
9219 SAFE_FREE(state
->data
);
9220 SAFE_FREE(state
->param
);
9222 END_PROFILE(SMBtrans2
);
9223 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
9227 /****************************************************************************
9228 Reply to a SMBtranss2
9229 ****************************************************************************/
9231 void reply_transs2(struct smb_request
*req
)
9233 connection_struct
*conn
= req
->conn
;
9234 unsigned int pcnt
,poff
,dcnt
,doff
,pdisp
,ddisp
;
9235 struct trans_state
*state
;
9237 START_PROFILE(SMBtranss2
);
9239 show_msg((const char *)req
->inbuf
);
9241 /* Windows clients expect all replies to
9242 a transact secondary (SMBtranss2 0x33)
9243 to have a command code of transact
9244 (SMBtrans2 0x32). See bug #8989
9245 and also [MS-CIFS] section 2.2.4.47.2
9248 req
->cmd
= SMBtrans2
;
9251 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
9252 END_PROFILE(SMBtranss2
);
9256 for (state
= conn
->pending_trans
; state
!= NULL
;
9257 state
= state
->next
) {
9258 if (state
->mid
== req
->mid
) {
9263 if ((state
== NULL
) || (state
->cmd
!= SMBtrans2
)) {
9264 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
9265 END_PROFILE(SMBtranss2
);
9269 /* Revise state->total_param and state->total_data in case they have
9270 changed downwards */
9272 if (SVAL(req
->vwv
+0, 0) < state
->total_param
)
9273 state
->total_param
= SVAL(req
->vwv
+0, 0);
9274 if (SVAL(req
->vwv
+1, 0) < state
->total_data
)
9275 state
->total_data
= SVAL(req
->vwv
+1, 0);
9277 pcnt
= SVAL(req
->vwv
+2, 0);
9278 poff
= SVAL(req
->vwv
+3, 0);
9279 pdisp
= SVAL(req
->vwv
+4, 0);
9281 dcnt
= SVAL(req
->vwv
+5, 0);
9282 doff
= SVAL(req
->vwv
+6, 0);
9283 ddisp
= SVAL(req
->vwv
+7, 0);
9285 state
->received_param
+= pcnt
;
9286 state
->received_data
+= dcnt
;
9288 if ((state
->received_data
> state
->total_data
) ||
9289 (state
->received_param
> state
->total_param
))
9293 if (trans_oob(state
->total_param
, pdisp
, pcnt
)
9294 || trans_oob(smb_len(req
->inbuf
), poff
, pcnt
)) {
9297 memcpy(state
->param
+pdisp
,smb_base(req
->inbuf
)+poff
,pcnt
);
9301 if (trans_oob(state
->total_data
, ddisp
, dcnt
)
9302 || trans_oob(smb_len(req
->inbuf
), doff
, dcnt
)) {
9305 memcpy(state
->data
+ddisp
, smb_base(req
->inbuf
)+doff
,dcnt
);
9308 if ((state
->received_param
< state
->total_param
) ||
9309 (state
->received_data
< state
->total_data
)) {
9310 END_PROFILE(SMBtranss2
);
9314 handle_trans2(conn
, req
, state
);
9316 DLIST_REMOVE(conn
->pending_trans
, state
);
9317 SAFE_FREE(state
->data
);
9318 SAFE_FREE(state
->param
);
9321 END_PROFILE(SMBtranss2
);
9326 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
9327 DLIST_REMOVE(conn
->pending_trans
, state
);
9328 SAFE_FREE(state
->data
);
9329 SAFE_FREE(state
->param
);
9331 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
9332 END_PROFILE(SMBtranss2
);