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 NTSTATUS
check_access_fsp(const struct files_struct
*fsp
,
60 if (!(fsp
->access_mask
& access_mask
)) {
61 return NT_STATUS_ACCESS_DENIED
;
66 /********************************************************************
67 The canonical "check access" based on object handle or path function.
68 ********************************************************************/
70 NTSTATUS
check_access(connection_struct
*conn
,
72 const struct smb_filename
*smb_fname
,
78 status
= check_access_fsp(fsp
, access_mask
);
80 status
= smbd_check_access_rights(conn
, smb_fname
,
87 /********************************************************************
88 Roundup a value to the nearest allocation roundup size boundary.
89 Only do this for Windows clients.
90 ********************************************************************/
92 uint64_t smb_roundup(connection_struct
*conn
, uint64_t val
)
94 uint64_t rval
= lp_allocation_roundup_size(SNUM(conn
));
96 /* Only roundup for Windows clients. */
97 enum remote_arch_types ra_type
= get_remote_arch();
98 if (rval
&& (ra_type
!= RA_SAMBA
) && (ra_type
!= RA_CIFSFS
)) {
99 val
= SMB_ROUNDUP(val
,rval
);
104 /********************************************************************
105 Create a 64 bit FileIndex. If the file is on the same device as
106 the root of the share, just return the 64-bit inode. If it isn't,
107 mangle as we used to do.
108 ********************************************************************/
110 uint64_t get_FileIndex(connection_struct
*conn
, const SMB_STRUCT_STAT
*psbuf
)
113 if (conn
->base_share_dev
== psbuf
->st_ex_dev
) {
114 return (uint64_t)psbuf
->st_ex_ino
;
116 file_index
= ((psbuf
->st_ex_ino
) & UINT32_MAX
); /* FileIndexLow */
117 file_index
|= ((uint64_t)((psbuf
->st_ex_dev
) & UINT32_MAX
)) << 32; /* FileIndexHigh */
121 /****************************************************************************
122 Utility functions for dealing with extended attributes.
123 ****************************************************************************/
125 /****************************************************************************
126 Refuse to allow clients to overwrite our private xattrs.
127 ****************************************************************************/
129 bool samba_private_attr_name(const char *unix_ea_name
)
131 static const char * const prohibited_ea_names
[] = {
132 SAMBA_POSIX_INHERITANCE_EA_NAME
,
133 SAMBA_XATTR_DOS_ATTRIB
,
141 for (i
= 0; prohibited_ea_names
[i
]; i
++) {
142 if (strequal( prohibited_ea_names
[i
], unix_ea_name
))
145 if (strncasecmp_m(unix_ea_name
, SAMBA_XATTR_DOSSTREAM_PREFIX
,
146 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX
)) == 0) {
152 /****************************************************************************
153 Get one EA value. Fill in a struct ea_struct.
154 ****************************************************************************/
156 NTSTATUS
get_ea_value(TALLOC_CTX
*mem_ctx
, connection_struct
*conn
,
157 files_struct
*fsp
, const char *fname
,
158 const char *ea_name
, struct ea_struct
*pea
)
160 /* Get the value of this xattr. Max size is 64k. */
161 size_t attr_size
= 256;
167 val
= talloc_realloc(mem_ctx
, val
, char, attr_size
);
169 return NT_STATUS_NO_MEMORY
;
172 if (fsp
&& fsp
->fh
->fd
!= -1) {
173 sizeret
= SMB_VFS_FGETXATTR(fsp
, ea_name
, val
, attr_size
);
175 sizeret
= SMB_VFS_GETXATTR(conn
, fname
, ea_name
, val
, attr_size
);
178 if (sizeret
== -1 && errno
== ERANGE
&& attr_size
!= 65536) {
184 return map_nt_error_from_unix(errno
);
187 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name
, (unsigned int)sizeret
));
188 dump_data(10, (uint8_t *)val
, sizeret
);
191 if (strnequal(ea_name
, "user.", 5)) {
192 pea
->name
= talloc_strdup(mem_ctx
, &ea_name
[5]);
194 pea
->name
= talloc_strdup(mem_ctx
, ea_name
);
196 if (pea
->name
== NULL
) {
198 return NT_STATUS_NO_MEMORY
;
200 pea
->value
.data
= (unsigned char *)val
;
201 pea
->value
.length
= (size_t)sizeret
;
205 NTSTATUS
get_ea_names_from_file(TALLOC_CTX
*mem_ctx
, connection_struct
*conn
,
206 files_struct
*fsp
, const char *fname
,
207 char ***pnames
, size_t *pnum_names
)
209 /* Get a list of all xattrs. Max namesize is 64k. */
210 size_t ea_namelist_size
= 1024;
211 char *ea_namelist
= NULL
;
216 ssize_t sizeret
= -1;
218 if (!lp_ea_support(SNUM(conn
))) {
227 * TALLOC the result early to get the talloc hierarchy right.
230 names
= talloc_array(mem_ctx
, char *, 1);
232 DEBUG(0, ("talloc failed\n"));
233 return NT_STATUS_NO_MEMORY
;
236 while (ea_namelist_size
<= 65536) {
238 ea_namelist
= talloc_realloc(
239 names
, ea_namelist
, char, ea_namelist_size
);
240 if (ea_namelist
== NULL
) {
241 DEBUG(0, ("talloc failed\n"));
243 return NT_STATUS_NO_MEMORY
;
246 if (fsp
&& fsp
->fh
->fd
!= -1) {
247 sizeret
= SMB_VFS_FLISTXATTR(fsp
, ea_namelist
,
250 sizeret
= SMB_VFS_LISTXATTR(conn
, fname
, ea_namelist
,
254 if ((sizeret
== -1) && (errno
== ERANGE
)) {
255 ea_namelist_size
*= 2;
264 return map_nt_error_from_unix(errno
);
267 DEBUG(10, ("%s: ea_namelist size = %u\n",
268 __func__
, (unsigned int)sizeret
));
280 * Ensure the result is 0-terminated
283 if (ea_namelist
[sizeret
-1] != '\0') {
285 return NT_STATUS_INTERNAL_ERROR
;
293 for (p
= ea_namelist
; p
- ea_namelist
< sizeret
; p
+= strlen(p
)+1) {
297 tmp
= talloc_realloc(mem_ctx
, names
, char *, num_names
);
299 DEBUG(0, ("talloc failed\n"));
301 return NT_STATUS_NO_MEMORY
;
307 for (p
= ea_namelist
; p
- ea_namelist
< sizeret
; p
+= strlen(p
)+1) {
308 names
[num_names
++] = p
;
316 *pnum_names
= num_names
;
320 /****************************************************************************
321 Return a linked list of the total EA's. Plus the total size
322 ****************************************************************************/
324 static NTSTATUS
get_ea_list_from_file_path(TALLOC_CTX
*mem_ctx
, connection_struct
*conn
, files_struct
*fsp
,
325 const char *fname
, size_t *pea_total_len
, struct ea_list
**ea_list
)
327 /* Get a list of all xattrs. Max namesize is 64k. */
330 struct ea_list
*ea_list_head
= NULL
;
336 status
= get_ea_names_from_file(talloc_tos(), conn
, fsp
, fname
,
339 if (!NT_STATUS_IS_OK(status
)) {
343 if (num_names
== 0) {
348 for (i
=0; i
<num_names
; i
++) {
349 struct ea_list
*listp
;
352 if (strnequal(names
[i
], "system.", 7)
353 || samba_private_attr_name(names
[i
]))
357 * Filter out any underlying POSIX EA names
358 * that a Windows client can't handle.
360 if (!lp_posix_pathnames() &&
361 is_invalid_windows_ea_name(names
[i
])) {
365 listp
= talloc(mem_ctx
, struct ea_list
);
367 return NT_STATUS_NO_MEMORY
;
370 status
= get_ea_value(listp
, conn
, fsp
,
374 if (!NT_STATUS_IS_OK(status
)) {
379 if (listp
->ea
.value
.length
== 0) {
381 * We can never return a zero length EA.
382 * Windows reports the EA's as corrupted.
388 push_ascii_fstring(dos_ea_name
, listp
->ea
.name
);
391 4 + strlen(dos_ea_name
) + 1 + listp
->ea
.value
.length
;
393 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
394 "= %u\n", (unsigned int)*pea_total_len
, dos_ea_name
,
395 (unsigned int)listp
->ea
.value
.length
));
397 DLIST_ADD_END(ea_list_head
, listp
, struct ea_list
*);
401 /* Add on 4 for total length. */
402 if (*pea_total_len
) {
406 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
407 (unsigned int)*pea_total_len
));
409 *ea_list
= ea_list_head
;
413 static NTSTATUS
get_ea_list_from_file(TALLOC_CTX
*mem_ctx
, connection_struct
*conn
, files_struct
*fsp
,
414 const struct smb_filename
*smb_fname
, size_t *pea_total_len
, struct ea_list
**ea_list
)
419 if (!lp_ea_support(SNUM(conn
))) {
423 if (is_ntfs_stream_smb_fname(smb_fname
)) {
424 return NT_STATUS_INVALID_PARAMETER
;
427 return get_ea_list_from_file_path(mem_ctx
, conn
, fsp
, smb_fname
->base_name
, pea_total_len
, ea_list
);
430 /****************************************************************************
431 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
433 ****************************************************************************/
435 static unsigned int fill_ea_buffer(TALLOC_CTX
*mem_ctx
, char *pdata
, unsigned int total_data_size
,
436 connection_struct
*conn
, struct ea_list
*ea_list
)
438 unsigned int ret_data_size
= 4;
441 SMB_ASSERT(total_data_size
>= 4);
443 if (!lp_ea_support(SNUM(conn
))) {
448 for (p
= pdata
+ 4; ea_list
; ea_list
= ea_list
->next
) {
451 push_ascii_fstring(dos_ea_name
, ea_list
->ea
.name
);
452 dos_namelen
= strlen(dos_ea_name
);
453 if (dos_namelen
> 255 || dos_namelen
== 0) {
456 if (ea_list
->ea
.value
.length
> 65535) {
459 if (4 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
> total_data_size
) {
463 /* We know we have room. */
464 SCVAL(p
,0,ea_list
->ea
.flags
);
465 SCVAL(p
,1,dos_namelen
);
466 SSVAL(p
,2,ea_list
->ea
.value
.length
);
467 strlcpy(p
+4, dos_ea_name
, dos_namelen
+1);
468 memcpy( p
+ 4 + dos_namelen
+ 1, ea_list
->ea
.value
.data
, ea_list
->ea
.value
.length
);
470 total_data_size
-= 4 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
;
471 p
+= 4 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
;
474 ret_data_size
= PTR_DIFF(p
, pdata
);
475 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size
));
476 SIVAL(pdata
,0,ret_data_size
);
477 return ret_data_size
;
480 static NTSTATUS
fill_ea_chained_buffer(TALLOC_CTX
*mem_ctx
,
482 unsigned int total_data_size
,
483 unsigned int *ret_data_size
,
484 connection_struct
*conn
,
485 struct ea_list
*ea_list
)
487 uint8_t *p
= (uint8_t *)pdata
;
488 uint8_t *last_start
= NULL
;
489 bool do_store_data
= (pdata
!= NULL
);
493 if (!lp_ea_support(SNUM(conn
))) {
494 return NT_STATUS_NO_EAS_ON_FILE
;
497 for (; ea_list
; ea_list
= ea_list
->next
) {
503 if (last_start
!= NULL
&& do_store_data
) {
504 SIVAL(last_start
, 0, PTR_DIFF(p
, last_start
));
508 push_ascii_fstring(dos_ea_name
, ea_list
->ea
.name
);
509 dos_namelen
= strlen(dos_ea_name
);
510 if (dos_namelen
> 255 || dos_namelen
== 0) {
511 return NT_STATUS_INTERNAL_ERROR
;
513 if (ea_list
->ea
.value
.length
> 65535) {
514 return NT_STATUS_INTERNAL_ERROR
;
517 this_size
= 0x08 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
;
520 pad
= (4 - (this_size
% 4)) % 4;
525 if (this_size
> total_data_size
) {
526 return NT_STATUS_INFO_LENGTH_MISMATCH
;
529 /* We know we have room. */
530 SIVAL(p
, 0x00, 0); /* next offset */
531 SCVAL(p
, 0x04, ea_list
->ea
.flags
);
532 SCVAL(p
, 0x05, dos_namelen
);
533 SSVAL(p
, 0x06, ea_list
->ea
.value
.length
);
534 strlcpy((char *)(p
+0x08), dos_ea_name
, dos_namelen
+1);
535 memcpy(p
+ 0x08 + dos_namelen
+ 1, ea_list
->ea
.value
.data
, ea_list
->ea
.value
.length
);
537 memset(p
+ 0x08 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
,
541 total_data_size
-= this_size
;
547 *ret_data_size
= PTR_DIFF(p
, pdata
);
548 DEBUG(10,("fill_ea_chained_buffer: data_size = %u\n", *ret_data_size
));
552 static unsigned int estimate_ea_size(connection_struct
*conn
, files_struct
*fsp
, const struct smb_filename
*smb_fname
)
554 size_t total_ea_len
= 0;
556 struct ea_list
*ea_list
= NULL
;
558 if (!lp_ea_support(SNUM(conn
))) {
561 mem_ctx
= talloc_stackframe();
563 /* If this is a stream fsp, then we need to instead find the
564 * estimated ea len from the main file, not the stream
565 * (streams cannot have EAs), but the estimate isn't just 0 in
567 if (is_ntfs_stream_smb_fname(smb_fname
)) {
570 (void)get_ea_list_from_file_path(mem_ctx
, conn
, fsp
, smb_fname
->base_name
, &total_ea_len
, &ea_list
);
571 if(conn
->sconn
->using_smb2
) {
573 unsigned int ret_data_size
;
575 * We're going to be using fill_ea_chained_buffer() to
576 * marshall EA's - this size is significantly larger
577 * than the SMB1 buffer. Re-calculate the size without
580 status
= fill_ea_chained_buffer(mem_ctx
,
586 if (!NT_STATUS_IS_OK(status
)) {
589 total_ea_len
= ret_data_size
;
591 TALLOC_FREE(mem_ctx
);
595 /****************************************************************************
596 Ensure the EA name is case insensitive by matching any existing EA name.
597 ****************************************************************************/
599 static void canonicalize_ea_name(connection_struct
*conn
, files_struct
*fsp
, const char *fname
, fstring unix_ea_name
)
602 TALLOC_CTX
*mem_ctx
= talloc_tos();
603 struct ea_list
*ea_list
;
604 NTSTATUS status
= get_ea_list_from_file_path(mem_ctx
, conn
, fsp
, fname
, &total_ea_len
, &ea_list
);
605 if (!NT_STATUS_IS_OK(status
)) {
609 for (; ea_list
; ea_list
= ea_list
->next
) {
610 if (strequal(&unix_ea_name
[5], ea_list
->ea
.name
)) {
611 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
612 &unix_ea_name
[5], ea_list
->ea
.name
));
613 strlcpy(&unix_ea_name
[5], ea_list
->ea
.name
, sizeof(fstring
)-5);
619 /****************************************************************************
620 Set or delete an extended attribute.
621 ****************************************************************************/
623 NTSTATUS
set_ea(connection_struct
*conn
, files_struct
*fsp
,
624 const struct smb_filename
*smb_fname
, struct ea_list
*ea_list
)
629 if (!lp_ea_support(SNUM(conn
))) {
630 return NT_STATUS_EAS_NOT_SUPPORTED
;
633 status
= check_access(conn
, fsp
, smb_fname
, FILE_WRITE_EA
);
634 if (!NT_STATUS_IS_OK(status
)) {
638 /* Setting EAs on streams isn't supported. */
639 if (is_ntfs_stream_smb_fname(smb_fname
)) {
640 return NT_STATUS_INVALID_PARAMETER
;
644 * Filter out invalid Windows EA names - before
645 * we set *any* of them.
648 if (ea_list_has_invalid_name(ea_list
)) {
649 return STATUS_INVALID_EA_NAME
;
652 fname
= smb_fname
->base_name
;
654 for (;ea_list
; ea_list
= ea_list
->next
) {
656 fstring unix_ea_name
;
658 fstrcpy(unix_ea_name
, "user."); /* All EA's must start with user. */
659 fstrcat(unix_ea_name
, ea_list
->ea
.name
);
661 canonicalize_ea_name(conn
, fsp
, fname
, unix_ea_name
);
663 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name
, (unsigned int)ea_list
->ea
.value
.length
));
665 if (samba_private_attr_name(unix_ea_name
)) {
666 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name
));
667 return NT_STATUS_ACCESS_DENIED
;
670 if (ea_list
->ea
.value
.length
== 0) {
671 /* Remove the attribute. */
672 if (fsp
&& (fsp
->fh
->fd
!= -1)) {
673 DEBUG(10,("set_ea: deleting ea name %s on "
674 "file %s by file descriptor.\n",
675 unix_ea_name
, fsp_str_dbg(fsp
)));
676 ret
= SMB_VFS_FREMOVEXATTR(fsp
, unix_ea_name
);
678 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
679 unix_ea_name
, fname
));
680 ret
= SMB_VFS_REMOVEXATTR(conn
, fname
, unix_ea_name
);
683 /* Removing a non existent attribute always succeeds. */
684 if (ret
== -1 && errno
== ENOATTR
) {
685 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
691 if (fsp
&& (fsp
->fh
->fd
!= -1)) {
692 DEBUG(10,("set_ea: setting ea name %s on file "
693 "%s by file descriptor.\n",
694 unix_ea_name
, fsp_str_dbg(fsp
)));
695 ret
= SMB_VFS_FSETXATTR(fsp
, unix_ea_name
,
696 ea_list
->ea
.value
.data
, ea_list
->ea
.value
.length
, 0);
698 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
699 unix_ea_name
, fname
));
700 ret
= SMB_VFS_SETXATTR(conn
, fname
, unix_ea_name
,
701 ea_list
->ea
.value
.data
, ea_list
->ea
.value
.length
, 0);
707 if (errno
== ENOTSUP
) {
708 return NT_STATUS_EAS_NOT_SUPPORTED
;
711 return map_nt_error_from_unix(errno
);
717 /****************************************************************************
718 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
719 ****************************************************************************/
721 static struct ea_list
*read_ea_name_list(TALLOC_CTX
*ctx
, const char *pdata
, size_t data_size
)
723 struct ea_list
*ea_list_head
= NULL
;
724 size_t converted_size
, offset
= 0;
726 while (offset
+ 2 < data_size
) {
727 struct ea_list
*eal
= talloc_zero(ctx
, struct ea_list
);
728 unsigned int namelen
= CVAL(pdata
,offset
);
730 offset
++; /* Go past the namelen byte. */
732 /* integer wrap paranioa. */
733 if ((offset
+ namelen
< offset
) || (offset
+ namelen
< namelen
) ||
734 (offset
> data_size
) || (namelen
> data_size
) ||
735 (offset
+ namelen
>= data_size
)) {
738 /* Ensure the name is null terminated. */
739 if (pdata
[offset
+ namelen
] != '\0') {
742 if (!pull_ascii_talloc(ctx
, &eal
->ea
.name
, &pdata
[offset
],
744 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
745 "failed: %s", strerror(errno
)));
751 offset
+= (namelen
+ 1); /* Go past the name + terminating zero. */
752 DLIST_ADD_END(ea_list_head
, eal
, struct ea_list
*);
753 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal
->ea
.name
));
759 /****************************************************************************
760 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
761 ****************************************************************************/
763 static struct ea_list
*read_ea_list(TALLOC_CTX
*ctx
, const char *pdata
, size_t data_size
)
765 struct ea_list
*ea_list_head
= NULL
;
767 size_t bytes_used
= 0;
769 while (offset
< data_size
) {
770 struct ea_list
*eal
= read_ea_list_entry(ctx
, pdata
+ offset
, data_size
- offset
, &bytes_used
);
776 DLIST_ADD_END(ea_list_head
, eal
, struct ea_list
*);
777 offset
+= bytes_used
;
783 /****************************************************************************
784 Count the total EA size needed.
785 ****************************************************************************/
787 static size_t ea_list_size(struct ea_list
*ealist
)
790 struct ea_list
*listp
;
793 for (listp
= ealist
; listp
; listp
= listp
->next
) {
794 push_ascii_fstring(dos_ea_name
, listp
->ea
.name
);
795 ret
+= 4 + strlen(dos_ea_name
) + 1 + listp
->ea
.value
.length
;
797 /* Add on 4 for total length. */
805 /****************************************************************************
806 Return a union of EA's from a file list and a list of names.
807 The TALLOC context for the two lists *MUST* be identical as we steal
808 memory from one list to add to another. JRA.
809 ****************************************************************************/
811 static struct ea_list
*ea_list_union(struct ea_list
*name_list
, struct ea_list
*file_list
, size_t *total_ea_len
)
813 struct ea_list
*nlistp
, *flistp
;
815 for (nlistp
= name_list
; nlistp
; nlistp
= nlistp
->next
) {
816 for (flistp
= file_list
; flistp
; flistp
= flistp
->next
) {
817 if (strequal(nlistp
->ea
.name
, flistp
->ea
.name
)) {
823 /* Copy the data from this entry. */
824 nlistp
->ea
.flags
= flistp
->ea
.flags
;
825 nlistp
->ea
.value
= flistp
->ea
.value
;
828 nlistp
->ea
.flags
= 0;
829 ZERO_STRUCT(nlistp
->ea
.value
);
833 *total_ea_len
= ea_list_size(name_list
);
837 /****************************************************************************
838 Send the required number of replies back.
839 We assume all fields other than the data fields are
840 set correctly for the type of call.
841 HACK ! Always assumes smb_setup field is zero.
842 ****************************************************************************/
844 void send_trans2_replies(connection_struct
*conn
,
845 struct smb_request
*req
,
853 /* As we are using a protocol > LANMAN1 then the max_send
854 variable must have been set in the sessetupX call.
855 This takes precedence over the max_xmit field in the
856 global struct. These different max_xmit variables should
857 be merged as this is now too confusing */
859 int data_to_send
= datasize
;
860 int params_to_send
= paramsize
;
862 const char *pp
= params
;
863 const char *pd
= pdata
;
864 int params_sent_thistime
, data_sent_thistime
, total_sent_thistime
;
865 int alignment_offset
= 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
866 int data_alignment_offset
= 0;
867 bool overflow
= False
;
868 struct smbXsrv_connection
*xconn
= req
->xconn
;
869 int max_send
= xconn
->smb1
.sessions
.max_send
;
871 /* Modify the data_to_send and datasize and set the error if
872 we're trying to send more than max_data_bytes. We still send
873 the part of the packet(s) that fit. Strange, but needed
876 if (max_data_bytes
> 0 && datasize
> max_data_bytes
) {
877 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
878 max_data_bytes
, datasize
));
879 datasize
= data_to_send
= max_data_bytes
;
883 /* If there genuinely are no parameters or data to send just send the empty packet */
885 if(params_to_send
== 0 && data_to_send
== 0) {
886 reply_outbuf(req
, 10, 0);
887 if (NT_STATUS_V(status
)) {
890 ntstatus_to_dos(status
, &eclass
, &ecode
);
891 error_packet_set((char *)req
->outbuf
,
892 eclass
, ecode
, status
,
895 show_msg((char *)req
->outbuf
);
896 if (!srv_send_smb(xconn
,
899 IS_CONN_ENCRYPTED(conn
),
901 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
903 TALLOC_FREE(req
->outbuf
);
907 /* When sending params and data ensure that both are nicely aligned */
908 /* Only do this alignment when there is also data to send - else
909 can cause NT redirector problems. */
911 if (((params_to_send
% 4) != 0) && (data_to_send
!= 0))
912 data_alignment_offset
= 4 - (params_to_send
% 4);
914 /* Space is bufsize minus Netbios over TCP header minus SMB header */
915 /* The alignment_offset is to align the param bytes on an even byte
916 boundary. NT 4.0 Beta needs this to work correctly. */
918 useable_space
= max_send
- (smb_size
921 + data_alignment_offset
);
923 if (useable_space
< 0) {
924 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
925 "= %d!!!", useable_space
));
926 exit_server_cleanly("send_trans2_replies: Not enough space");
929 while (params_to_send
|| data_to_send
) {
930 /* Calculate whether we will totally or partially fill this packet */
932 total_sent_thistime
= params_to_send
+ data_to_send
;
934 /* We can never send more than useable_space */
936 * Note that 'useable_space' does not include the alignment offsets,
937 * but we must include the alignment offsets in the calculation of
938 * the length of the data we send over the wire, as the alignment offsets
939 * are sent here. Fix from Marc_Jacobsen@hp.com.
942 total_sent_thistime
= MIN(total_sent_thistime
, useable_space
);
944 reply_outbuf(req
, 10, total_sent_thistime
+ alignment_offset
945 + data_alignment_offset
);
947 /* Set total params and data to be sent */
948 SSVAL(req
->outbuf
,smb_tprcnt
,paramsize
);
949 SSVAL(req
->outbuf
,smb_tdrcnt
,datasize
);
951 /* Calculate how many parameters and data we can fit into
952 * this packet. Parameters get precedence
955 params_sent_thistime
= MIN(params_to_send
,useable_space
);
956 data_sent_thistime
= useable_space
- params_sent_thistime
;
957 data_sent_thistime
= MIN(data_sent_thistime
,data_to_send
);
959 SSVAL(req
->outbuf
,smb_prcnt
, params_sent_thistime
);
961 /* smb_proff is the offset from the start of the SMB header to the
962 parameter bytes, however the first 4 bytes of outbuf are
963 the Netbios over TCP header. Thus use smb_base() to subtract
964 them from the calculation */
966 SSVAL(req
->outbuf
,smb_proff
,
967 ((smb_buf(req
->outbuf
)+alignment_offset
)
968 - smb_base(req
->outbuf
)));
970 if(params_sent_thistime
== 0)
971 SSVAL(req
->outbuf
,smb_prdisp
,0);
973 /* Absolute displacement of param bytes sent in this packet */
974 SSVAL(req
->outbuf
,smb_prdisp
,pp
- params
);
976 SSVAL(req
->outbuf
,smb_drcnt
, data_sent_thistime
);
977 if(data_sent_thistime
== 0) {
978 SSVAL(req
->outbuf
,smb_droff
,0);
979 SSVAL(req
->outbuf
,smb_drdisp
, 0);
981 /* The offset of the data bytes is the offset of the
982 parameter bytes plus the number of parameters being sent this time */
983 SSVAL(req
->outbuf
, smb_droff
,
984 ((smb_buf(req
->outbuf
)+alignment_offset
)
985 - smb_base(req
->outbuf
))
986 + params_sent_thistime
+ data_alignment_offset
);
987 SSVAL(req
->outbuf
,smb_drdisp
, pd
- pdata
);
990 /* Initialize the padding for alignment */
992 if (alignment_offset
!= 0) {
993 memset(smb_buf(req
->outbuf
), 0, alignment_offset
);
996 /* Copy the param bytes into the packet */
998 if(params_sent_thistime
) {
999 memcpy((smb_buf(req
->outbuf
)+alignment_offset
), pp
,
1000 params_sent_thistime
);
1003 /* Copy in the data bytes */
1004 if(data_sent_thistime
) {
1005 if (data_alignment_offset
!= 0) {
1006 memset((smb_buf(req
->outbuf
)+alignment_offset
+
1007 params_sent_thistime
), 0,
1008 data_alignment_offset
);
1010 memcpy(smb_buf(req
->outbuf
)+alignment_offset
1011 +params_sent_thistime
+data_alignment_offset
,
1012 pd
,data_sent_thistime
);
1015 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
1016 params_sent_thistime
, data_sent_thistime
, useable_space
));
1017 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
1018 params_to_send
, data_to_send
, paramsize
, datasize
));
1021 error_packet_set((char *)req
->outbuf
,
1022 ERRDOS
,ERRbufferoverflow
,
1023 STATUS_BUFFER_OVERFLOW
,
1025 } else if (NT_STATUS_V(status
)) {
1028 ntstatus_to_dos(status
, &eclass
, &ecode
);
1029 error_packet_set((char *)req
->outbuf
,
1030 eclass
, ecode
, status
,
1034 /* Send the packet */
1035 show_msg((char *)req
->outbuf
);
1036 if (!srv_send_smb(xconn
,
1037 (char *)req
->outbuf
,
1038 true, req
->seqnum
+1,
1039 IS_CONN_ENCRYPTED(conn
),
1041 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
1043 TALLOC_FREE(req
->outbuf
);
1045 pp
+= params_sent_thistime
;
1046 pd
+= data_sent_thistime
;
1048 params_to_send
-= params_sent_thistime
;
1049 data_to_send
-= data_sent_thistime
;
1052 if(params_to_send
< 0 || data_to_send
< 0) {
1053 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
1054 params_to_send
, data_to_send
));
1062 /****************************************************************************
1063 Reply to a TRANSACT2_OPEN.
1064 ****************************************************************************/
1066 static void call_trans2open(connection_struct
*conn
,
1067 struct smb_request
*req
,
1068 char **pparams
, int total_params
,
1069 char **ppdata
, int total_data
,
1070 unsigned int max_data_bytes
)
1072 struct smb_filename
*smb_fname
= NULL
;
1073 char *params
= *pparams
;
1074 char *pdata
= *ppdata
;
1077 bool oplock_request
;
1079 bool return_additional_info
;
1088 int fattr
=0,mtime
=0;
1089 SMB_INO_T inode
= 0;
1092 struct ea_list
*ea_list
= NULL
;
1095 uint32_t access_mask
;
1096 uint32_t share_mode
;
1097 uint32_t create_disposition
;
1098 uint32_t create_options
= 0;
1099 uint32_t private_flags
= 0;
1100 TALLOC_CTX
*ctx
= talloc_tos();
1103 * Ensure we have enough parameters to perform the operation.
1106 if (total_params
< 29) {
1107 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1111 flags
= SVAL(params
, 0);
1112 deny_mode
= SVAL(params
, 2);
1113 open_attr
= SVAL(params
,6);
1114 oplock_request
= (flags
& REQUEST_OPLOCK
) ? EXCLUSIVE_OPLOCK
: 0;
1115 if (oplock_request
) {
1116 oplock_request
|= (flags
& REQUEST_BATCH_OPLOCK
) ? BATCH_OPLOCK
: 0;
1120 return_additional_info
= BITSETW(params
,0);
1121 open_sattr
= SVAL(params
, 4);
1122 open_time
= make_unix_date3(params
+8);
1124 open_ofun
= SVAL(params
,12);
1125 open_size
= IVAL(params
,14);
1126 pname
= ¶ms
[28];
1129 reply_nterror(req
, NT_STATUS_NETWORK_ACCESS_DENIED
);
1133 srvstr_get_path(ctx
, params
, req
->flags2
, &fname
, pname
,
1134 total_params
- 28, STR_TERMINATE
,
1136 if (!NT_STATUS_IS_OK(status
)) {
1137 reply_nterror(req
, status
);
1141 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
1142 fname
, (unsigned int)deny_mode
, (unsigned int)open_attr
,
1143 (unsigned int)open_ofun
, open_size
));
1145 status
= filename_convert(ctx
,
1147 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
1152 if (!NT_STATUS_IS_OK(status
)) {
1153 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
1154 reply_botherror(req
,
1155 NT_STATUS_PATH_NOT_COVERED
,
1156 ERRSRV
, ERRbadpath
);
1159 reply_nterror(req
, status
);
1163 if (open_ofun
== 0) {
1164 reply_nterror(req
, NT_STATUS_OBJECT_NAME_COLLISION
);
1168 if (!map_open_params_to_ntcreate(smb_fname
->base_name
, deny_mode
,
1170 &access_mask
, &share_mode
,
1171 &create_disposition
,
1174 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
1178 /* Any data in this call is an EA list. */
1179 if (total_data
&& (total_data
!= 4)) {
1180 if (total_data
< 10) {
1181 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1185 if (IVAL(pdata
,0) > total_data
) {
1186 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
1187 IVAL(pdata
,0), (unsigned int)total_data
));
1188 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1192 ea_list
= read_ea_list(talloc_tos(), pdata
+ 4,
1195 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1199 if (!lp_ea_support(SNUM(conn
))) {
1200 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
1204 if (ea_list_has_invalid_name(ea_list
)) {
1206 *pparams
= (char *)SMB_REALLOC(*pparams
, param_len
);
1207 if(*pparams
== NULL
) {
1208 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1212 memset(params
, '\0', param_len
);
1213 send_trans2_replies(conn
, req
, STATUS_INVALID_EA_NAME
,
1214 params
, param_len
, NULL
, 0, max_data_bytes
);
1219 status
= SMB_VFS_CREATE_FILE(
1222 0, /* root_dir_fid */
1223 smb_fname
, /* fname */
1224 access_mask
, /* access_mask */
1225 share_mode
, /* share_access */
1226 create_disposition
, /* create_disposition*/
1227 create_options
, /* create_options */
1228 open_attr
, /* file_attributes */
1229 oplock_request
, /* oplock_request */
1231 open_size
, /* allocation_size */
1234 ea_list
, /* ea_list */
1236 &smb_action
, /* psbuf */
1237 NULL
, NULL
); /* create context */
1239 if (!NT_STATUS_IS_OK(status
)) {
1240 if (open_was_deferred(req
->xconn
, req
->mid
)) {
1241 /* We have re-scheduled this call. */
1244 reply_openerror(req
, status
);
1248 size
= get_file_size_stat(&smb_fname
->st
);
1249 fattr
= dos_mode(conn
, smb_fname
);
1250 mtime
= convert_timespec_to_time_t(smb_fname
->st
.st_ex_mtime
);
1251 inode
= smb_fname
->st
.st_ex_ino
;
1252 if (fattr
& FILE_ATTRIBUTE_DIRECTORY
) {
1253 close_file(req
, fsp
, ERROR_CLOSE
);
1254 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
1258 /* Realloc the size of parameters and data we will return */
1259 *pparams
= (char *)SMB_REALLOC(*pparams
, 30);
1260 if(*pparams
== NULL
) {
1261 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1266 SSVAL(params
,0,fsp
->fnum
);
1267 SSVAL(params
,2,fattr
);
1268 srv_put_dos_date2(params
,4, mtime
);
1269 SIVAL(params
,8, (uint32_t)size
);
1270 SSVAL(params
,12,deny_mode
);
1271 SSVAL(params
,14,0); /* open_type - file or directory. */
1272 SSVAL(params
,16,0); /* open_state - only valid for IPC device. */
1274 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
1275 smb_action
|= EXTENDED_OPLOCK_GRANTED
;
1278 SSVAL(params
,18,smb_action
);
1281 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1283 SIVAL(params
,20,inode
);
1284 SSVAL(params
,24,0); /* Padding. */
1286 uint32_t ea_size
= estimate_ea_size(conn
, fsp
,
1288 SIVAL(params
, 26, ea_size
);
1290 SIVAL(params
, 26, 0);
1293 /* Send the required number of replies */
1294 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 30, *ppdata
, 0, max_data_bytes
);
1296 TALLOC_FREE(smb_fname
);
1299 /*********************************************************
1300 Routine to check if a given string matches exactly.
1301 as a special case a mask of "." does NOT match. That
1302 is required for correct wildcard semantics
1303 Case can be significant or not.
1304 **********************************************************/
1306 static bool exact_match(bool has_wild
,
1307 bool case_sensitive
,
1311 if (mask
[0] == '.' && mask
[1] == 0) {
1319 if (case_sensitive
) {
1320 return strcmp(str
,mask
)==0;
1322 return strcasecmp_m(str
,mask
) == 0;
1326 /****************************************************************************
1327 Return the filetype for UNIX extensions.
1328 ****************************************************************************/
1330 static uint32_t unix_filetype(mode_t mode
)
1333 return UNIX_TYPE_FILE
;
1334 else if(S_ISDIR(mode
))
1335 return UNIX_TYPE_DIR
;
1337 else if(S_ISLNK(mode
))
1338 return UNIX_TYPE_SYMLINK
;
1341 else if(S_ISCHR(mode
))
1342 return UNIX_TYPE_CHARDEV
;
1345 else if(S_ISBLK(mode
))
1346 return UNIX_TYPE_BLKDEV
;
1349 else if(S_ISFIFO(mode
))
1350 return UNIX_TYPE_FIFO
;
1353 else if(S_ISSOCK(mode
))
1354 return UNIX_TYPE_SOCKET
;
1357 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode
));
1358 return UNIX_TYPE_UNKNOWN
;
1361 /****************************************************************************
1362 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1363 ****************************************************************************/
1365 enum perm_type
{ PERM_NEW_FILE
, PERM_NEW_DIR
, PERM_EXISTING_FILE
, PERM_EXISTING_DIR
};
1367 static NTSTATUS
unix_perms_from_wire( connection_struct
*conn
,
1368 const SMB_STRUCT_STAT
*psbuf
,
1370 enum perm_type ptype
,
1375 if (perms
== SMB_MODE_NO_CHANGE
) {
1376 if (!VALID_STAT(*psbuf
)) {
1377 return NT_STATUS_INVALID_PARAMETER
;
1379 *ret_perms
= psbuf
->st_ex_mode
;
1380 return NT_STATUS_OK
;
1384 ret
|= ((perms
& UNIX_X_OTH
) ? S_IXOTH
: 0);
1385 ret
|= ((perms
& UNIX_W_OTH
) ? S_IWOTH
: 0);
1386 ret
|= ((perms
& UNIX_R_OTH
) ? S_IROTH
: 0);
1387 ret
|= ((perms
& UNIX_X_GRP
) ? S_IXGRP
: 0);
1388 ret
|= ((perms
& UNIX_W_GRP
) ? S_IWGRP
: 0);
1389 ret
|= ((perms
& UNIX_R_GRP
) ? S_IRGRP
: 0);
1390 ret
|= ((perms
& UNIX_X_USR
) ? S_IXUSR
: 0);
1391 ret
|= ((perms
& UNIX_W_USR
) ? S_IWUSR
: 0);
1392 ret
|= ((perms
& UNIX_R_USR
) ? S_IRUSR
: 0);
1394 ret
|= ((perms
& UNIX_STICKY
) ? S_ISVTX
: 0);
1397 ret
|= ((perms
& UNIX_SET_GID
) ? S_ISGID
: 0);
1400 ret
|= ((perms
& UNIX_SET_UID
) ? S_ISUID
: 0);
1403 if (ptype
== PERM_NEW_FILE
) {
1405 * "create mask"/"force create mode" are
1406 * only applied to new files, not existing ones.
1408 ret
&= lp_create_mask(SNUM(conn
));
1409 /* Add in force bits */
1410 ret
|= lp_force_create_mode(SNUM(conn
));
1411 } else if (ptype
== PERM_NEW_DIR
) {
1413 * "directory mask"/"force directory mode" are
1414 * only applied to new directories, not existing ones.
1416 ret
&= lp_directory_mask(SNUM(conn
));
1417 /* Add in force bits */
1418 ret
|= lp_force_directory_mode(SNUM(conn
));
1422 return NT_STATUS_OK
;
1425 /****************************************************************************
1426 Needed to show the msdfs symlinks as directories. Modifies psbuf
1427 to be a directory if it's a msdfs link.
1428 ****************************************************************************/
1430 static bool check_msdfs_link(connection_struct
*conn
,
1431 const char *pathname
,
1432 SMB_STRUCT_STAT
*psbuf
)
1434 int saved_errno
= errno
;
1435 if(lp_host_msdfs() &&
1436 lp_msdfs_root(SNUM(conn
)) &&
1437 is_msdfs_link(conn
, pathname
, psbuf
)) {
1439 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1442 psbuf
->st_ex_mode
= (psbuf
->st_ex_mode
& 0xFFF) | S_IFDIR
;
1443 errno
= saved_errno
;
1446 errno
= saved_errno
;
1451 /****************************************************************************
1452 Get a level dependent lanman2 dir entry.
1453 ****************************************************************************/
1455 struct smbd_dirptr_lanman2_state
{
1456 connection_struct
*conn
;
1457 uint32_t info_level
;
1458 bool check_mangled_names
;
1460 bool got_exact_match
;
1463 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX
*ctx
,
1469 struct smbd_dirptr_lanman2_state
*state
=
1470 (struct smbd_dirptr_lanman2_state
*)private_data
;
1472 char mangled_name
[13]; /* mangled 8.3 name. */
1476 /* Mangle fname if it's an illegal name. */
1477 if (mangle_must_mangle(dname
, state
->conn
->params
)) {
1479 * Slow path - ensure we can push the original name as UCS2. If
1480 * not, then just don't return this name.
1484 size_t len
= (strlen(dname
) + 2) * 4; /* Allow enough space. */
1485 uint8_t *tmp
= talloc_array(talloc_tos(),
1489 status
= srvstr_push(NULL
,
1490 FLAGS2_UNICODE_STRINGS
,
1499 if (!NT_STATUS_IS_OK(status
)) {
1503 ok
= name_to_8_3(dname
, mangled_name
,
1504 true, state
->conn
->params
);
1508 fname
= mangled_name
;
1513 got_match
= exact_match(state
->has_wild
,
1514 state
->conn
->case_sensitive
,
1516 state
->got_exact_match
= got_match
;
1518 got_match
= mask_match(fname
, mask
,
1519 state
->conn
->case_sensitive
);
1522 if(!got_match
&& state
->check_mangled_names
&&
1523 !mangle_is_8_3(fname
, false, state
->conn
->params
)) {
1525 * It turns out that NT matches wildcards against
1526 * both long *and* short names. This may explain some
1527 * of the wildcard wierdness from old DOS clients
1528 * that some people have been seeing.... JRA.
1530 /* Force the mangling into 8.3. */
1531 ok
= name_to_8_3(fname
, mangled_name
,
1532 false, state
->conn
->params
);
1537 got_match
= exact_match(state
->has_wild
,
1538 state
->conn
->case_sensitive
,
1539 mangled_name
, mask
);
1540 state
->got_exact_match
= got_match
;
1542 got_match
= mask_match(mangled_name
, mask
,
1543 state
->conn
->case_sensitive
);
1551 *_fname
= talloc_strdup(ctx
, fname
);
1552 if (*_fname
== NULL
) {
1559 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX
*ctx
,
1561 struct smb_filename
*smb_fname
,
1564 struct smbd_dirptr_lanman2_state
*state
=
1565 (struct smbd_dirptr_lanman2_state
*)private_data
;
1566 bool ms_dfs_link
= false;
1569 if (INFO_LEVEL_IS_UNIX(state
->info_level
)) {
1570 if (SMB_VFS_LSTAT(state
->conn
, smb_fname
) != 0) {
1571 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1572 "Couldn't lstat [%s] (%s)\n",
1573 smb_fname_str_dbg(smb_fname
),
1577 } else if (!VALID_STAT(smb_fname
->st
) &&
1578 SMB_VFS_STAT(state
->conn
, smb_fname
) != 0) {
1579 /* Needed to show the msdfs symlinks as
1582 ms_dfs_link
= check_msdfs_link(state
->conn
,
1583 smb_fname
->base_name
,
1586 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1587 "Couldn't stat [%s] (%s)\n",
1588 smb_fname_str_dbg(smb_fname
),
1595 mode
= dos_mode_msdfs(state
->conn
, smb_fname
);
1597 mode
= dos_mode(state
->conn
, smb_fname
);
1604 static NTSTATUS
smbd_marshall_dir_entry(TALLOC_CTX
*ctx
,
1605 connection_struct
*conn
,
1607 uint32_t info_level
,
1608 struct ea_list
*name_list
,
1609 bool check_mangled_names
,
1610 bool requires_resume_key
,
1613 const struct smb_filename
*smb_fname
,
1614 int space_remaining
,
1620 uint64_t *last_entry_off
)
1622 char *p
, *q
, *pdata
= *ppdata
;
1624 uint64_t file_size
= 0;
1625 uint64_t allocation_size
= 0;
1626 uint64_t file_index
= 0;
1628 struct timespec mdate_ts
= {0};
1629 struct timespec adate_ts
= {0};
1630 struct timespec cdate_ts
= {0};
1631 struct timespec create_date_ts
= {0};
1632 time_t mdate
= (time_t)0, adate
= (time_t)0, create_date
= (time_t)0;
1634 char *last_entry_ptr
;
1639 struct readdir_attr_data
*readdir_attr_data
= NULL
;
1641 if (!(mode
& FILE_ATTRIBUTE_DIRECTORY
)) {
1642 file_size
= get_file_size_stat(&smb_fname
->st
);
1644 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
, NULL
, &smb_fname
->st
);
1646 status
= SMB_VFS_READDIR_ATTR(conn
, smb_fname
, ctx
, &readdir_attr_data
);
1647 if (!NT_STATUS_IS_OK(status
)) {
1648 if (!NT_STATUS_EQUAL(NT_STATUS_NOT_SUPPORTED
, status
)) {
1653 file_index
= get_FileIndex(conn
, &smb_fname
->st
);
1655 mdate_ts
= smb_fname
->st
.st_ex_mtime
;
1656 adate_ts
= smb_fname
->st
.st_ex_atime
;
1657 create_date_ts
= get_create_timespec(conn
, NULL
, smb_fname
);
1658 cdate_ts
= get_change_timespec(conn
, NULL
, smb_fname
);
1660 if (lp_dos_filetime_resolution(SNUM(conn
))) {
1661 dos_filetime_timespec(&create_date_ts
);
1662 dos_filetime_timespec(&mdate_ts
);
1663 dos_filetime_timespec(&adate_ts
);
1664 dos_filetime_timespec(&cdate_ts
);
1667 create_date
= convert_timespec_to_time_t(create_date_ts
);
1668 mdate
= convert_timespec_to_time_t(mdate_ts
);
1669 adate
= convert_timespec_to_time_t(adate_ts
);
1671 /* align the record */
1672 SMB_ASSERT(align
>= 1);
1674 off
= (int)PTR_DIFF(pdata
, base_data
);
1675 pad
= (off
+ (align
-1)) & ~(align
-1);
1678 if (pad
&& pad
> space_remaining
) {
1679 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1680 "for padding (wanted %u, had %d)\n",
1683 return STATUS_MORE_ENTRIES
; /* Not finished - just out of space */
1687 /* initialize padding to 0 */
1689 memset(pdata
, 0, pad
);
1691 space_remaining
-= pad
;
1693 DEBUG(10,("smbd_marshall_dir_entry: space_remaining = %d\n",
1703 switch (info_level
) {
1704 case SMB_FIND_INFO_STANDARD
:
1705 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1706 if(requires_resume_key
) {
1710 srv_put_dos_date2(p
,0,create_date
);
1711 srv_put_dos_date2(p
,4,adate
);
1712 srv_put_dos_date2(p
,8,mdate
);
1713 SIVAL(p
,12,(uint32_t)file_size
);
1714 SIVAL(p
,16,(uint32_t)allocation_size
);
1718 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1719 p
+= ucs2_align(base_data
, p
, 0);
1721 status
= srvstr_push(base_data
, flags2
, p
,
1722 fname
, PTR_DIFF(end_data
, p
),
1723 STR_TERMINATE
, &len
);
1724 if (!NT_STATUS_IS_OK(status
)) {
1727 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1729 SCVAL(nameptr
, -1, len
- 2);
1731 SCVAL(nameptr
, -1, 0);
1735 SCVAL(nameptr
, -1, len
- 1);
1737 SCVAL(nameptr
, -1, 0);
1743 case SMB_FIND_EA_SIZE
:
1744 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
1745 if (requires_resume_key
) {
1749 srv_put_dos_date2(p
,0,create_date
);
1750 srv_put_dos_date2(p
,4,adate
);
1751 srv_put_dos_date2(p
,8,mdate
);
1752 SIVAL(p
,12,(uint32_t)file_size
);
1753 SIVAL(p
,16,(uint32_t)allocation_size
);
1756 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
1758 SIVAL(p
,22,ea_size
); /* Extended attributes */
1762 status
= srvstr_push(base_data
, flags2
,
1763 p
, fname
, PTR_DIFF(end_data
, p
),
1764 STR_TERMINATE
| STR_NOALIGN
, &len
);
1765 if (!NT_STATUS_IS_OK(status
)) {
1768 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1781 SCVAL(nameptr
,0,len
);
1783 SCVAL(p
,0,0); p
+= 1; /* Extra zero byte ? - why.. */
1786 case SMB_FIND_EA_LIST
:
1788 struct ea_list
*file_list
= NULL
;
1791 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
1793 return NT_STATUS_INVALID_PARAMETER
;
1795 if (requires_resume_key
) {
1799 srv_put_dos_date2(p
,0,create_date
);
1800 srv_put_dos_date2(p
,4,adate
);
1801 srv_put_dos_date2(p
,8,mdate
);
1802 SIVAL(p
,12,(uint32_t)file_size
);
1803 SIVAL(p
,16,(uint32_t)allocation_size
);
1805 p
+= 22; /* p now points to the EA area. */
1807 status
= get_ea_list_from_file(ctx
, conn
, NULL
,
1809 &ea_len
, &file_list
);
1810 if (!NT_STATUS_IS_OK(status
)) {
1813 name_list
= ea_list_union(name_list
, file_list
, &ea_len
);
1815 /* We need to determine if this entry will fit in the space available. */
1816 /* Max string size is 255 bytes. */
1817 if (PTR_DIFF(p
+ 255 + ea_len
,pdata
) > space_remaining
) {
1818 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1819 "(wanted %u, had %d)\n",
1820 (unsigned int)PTR_DIFF(p
+ 255 + ea_len
,pdata
),
1822 return STATUS_MORE_ENTRIES
; /* Not finished - just out of space */
1825 /* Push the ea_data followed by the name. */
1826 p
+= fill_ea_buffer(ctx
, p
, space_remaining
, conn
, name_list
);
1828 status
= srvstr_push(base_data
, flags2
,
1829 p
+ 1, fname
, PTR_DIFF(end_data
, p
+1),
1830 STR_TERMINATE
| STR_NOALIGN
, &len
);
1831 if (!NT_STATUS_IS_OK(status
)) {
1834 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1847 SCVAL(nameptr
,0,len
);
1849 SCVAL(p
,0,0); p
+= 1; /* Extra zero byte ? - why.. */
1853 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
1854 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1855 was_8_3
= mangle_is_8_3(fname
, True
, conn
->params
);
1857 SIVAL(p
,0,reskey
); p
+= 4;
1858 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
1859 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
1860 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
1861 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
1862 SOFF_T(p
,0,file_size
); p
+= 8;
1863 SOFF_T(p
,0,allocation_size
); p
+= 8;
1864 SIVAL(p
,0,mode
); p
+= 4;
1865 q
= p
; p
+= 4; /* q is placeholder for name length. */
1866 if (mode
& FILE_ATTRIBUTE_REPARSE_POINT
) {
1867 SIVAL(p
, 0, IO_REPARSE_TAG_DFS
);
1869 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
1871 SIVAL(p
,0,ea_size
); /* Extended attributes */
1874 /* Clear the short name buffer. This is
1875 * IMPORTANT as not doing so will trigger
1876 * a Win2k client bug. JRA.
1878 if (!was_8_3
&& check_mangled_names
) {
1879 char mangled_name
[13]; /* mangled 8.3 name. */
1880 if (!name_to_8_3(fname
,mangled_name
,True
,
1882 /* Error - mangle failed ! */
1883 memset(mangled_name
,'\0',12);
1885 mangled_name
[12] = 0;
1886 status
= srvstr_push(base_data
, flags2
,
1887 p
+2, mangled_name
, 24,
1888 STR_UPPER
|STR_UNICODE
, &len
);
1889 if (!NT_STATUS_IS_OK(status
)) {
1893 memset(p
+ 2 + len
,'\0',24 - len
);
1900 status
= srvstr_push(base_data
, flags2
, p
,
1901 fname
, PTR_DIFF(end_data
, p
),
1902 STR_TERMINATE_ASCII
, &len
);
1903 if (!NT_STATUS_IS_OK(status
)) {
1909 len
= PTR_DIFF(p
, pdata
);
1910 pad
= (len
+ (align
-1)) & ~(align
-1);
1912 * offset to the next entry, the caller
1913 * will overwrite it for the last entry
1914 * that's why we always include the padding
1918 * set padding to zero
1921 memset(p
, 0, pad
- len
);
1928 case SMB_FIND_FILE_DIRECTORY_INFO
:
1929 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1931 SIVAL(p
,0,reskey
); p
+= 4;
1932 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
1933 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
1934 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
1935 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
1936 SOFF_T(p
,0,file_size
); p
+= 8;
1937 SOFF_T(p
,0,allocation_size
); p
+= 8;
1938 SIVAL(p
,0,mode
); p
+= 4;
1939 status
= srvstr_push(base_data
, flags2
,
1940 p
+ 4, fname
, PTR_DIFF(end_data
, p
+4),
1941 STR_TERMINATE_ASCII
, &len
);
1942 if (!NT_STATUS_IS_OK(status
)) {
1948 len
= PTR_DIFF(p
, pdata
);
1949 pad
= (len
+ (align
-1)) & ~(align
-1);
1951 * offset to the next entry, the caller
1952 * will overwrite it for the last entry
1953 * that's why we always include the padding
1957 * set padding to zero
1960 memset(p
, 0, pad
- len
);
1967 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
1968 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1970 SIVAL(p
,0,reskey
); p
+= 4;
1971 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
1972 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
1973 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
1974 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
1975 SOFF_T(p
,0,file_size
); p
+= 8;
1976 SOFF_T(p
,0,allocation_size
); p
+= 8;
1977 SIVAL(p
,0,mode
); p
+= 4;
1978 q
= p
; p
+= 4; /* q is placeholder for name length. */
1980 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
1982 SIVAL(p
,0,ea_size
); /* Extended attributes */
1985 status
= srvstr_push(base_data
, flags2
, p
,
1986 fname
, PTR_DIFF(end_data
, p
),
1987 STR_TERMINATE_ASCII
, &len
);
1988 if (!NT_STATUS_IS_OK(status
)) {
1994 len
= PTR_DIFF(p
, pdata
);
1995 pad
= (len
+ (align
-1)) & ~(align
-1);
1997 * offset to the next entry, the caller
1998 * will overwrite it for the last entry
1999 * that's why we always include the padding
2003 * set padding to zero
2006 memset(p
, 0, pad
- len
);
2013 case SMB_FIND_FILE_NAMES_INFO
:
2014 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
2016 SIVAL(p
,0,reskey
); p
+= 4;
2018 /* this must *not* be null terminated or w2k gets in a loop trying to set an
2019 acl on a dir (tridge) */
2020 status
= srvstr_push(base_data
, flags2
, p
,
2021 fname
, PTR_DIFF(end_data
, p
),
2022 STR_TERMINATE_ASCII
, &len
);
2023 if (!NT_STATUS_IS_OK(status
)) {
2029 len
= PTR_DIFF(p
, pdata
);
2030 pad
= (len
+ (align
-1)) & ~(align
-1);
2032 * offset to the next entry, the caller
2033 * will overwrite it for the last entry
2034 * that's why we always include the padding
2038 * set padding to zero
2041 memset(p
, 0, pad
- len
);
2048 case SMB_FIND_ID_FULL_DIRECTORY_INFO
:
2049 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
2051 SIVAL(p
,0,reskey
); p
+= 4;
2052 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
2053 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
2054 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
2055 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
2056 SOFF_T(p
,0,file_size
); p
+= 8;
2057 SOFF_T(p
,0,allocation_size
); p
+= 8;
2058 SIVAL(p
,0,mode
); p
+= 4;
2059 q
= p
; p
+= 4; /* q is placeholder for name length. */
2060 if (mode
& FILE_ATTRIBUTE_REPARSE_POINT
) {
2061 SIVAL(p
, 0, IO_REPARSE_TAG_DFS
);
2063 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
2065 SIVAL(p
,0,ea_size
); /* Extended attributes */
2068 SIVAL(p
,0,0); p
+= 4; /* Unknown - reserved ? */
2069 SBVAL(p
,0,file_index
); p
+= 8;
2070 status
= srvstr_push(base_data
, flags2
, p
,
2071 fname
, PTR_DIFF(end_data
, p
),
2072 STR_TERMINATE_ASCII
, &len
);
2073 if (!NT_STATUS_IS_OK(status
)) {
2079 len
= PTR_DIFF(p
, pdata
);
2080 pad
= (len
+ (align
-1)) & ~(align
-1);
2082 * offset to the next entry, the caller
2083 * will overwrite it for the last entry
2084 * that's why we always include the padding
2088 * set padding to zero
2091 memset(p
, 0, pad
- len
);
2098 case SMB_FIND_ID_BOTH_DIRECTORY_INFO
:
2099 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
2100 was_8_3
= mangle_is_8_3(fname
, True
, conn
->params
);
2102 SIVAL(p
,0,reskey
); p
+= 4;
2103 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
2104 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
2105 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
2106 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
2107 SOFF_T(p
,0,file_size
); p
+= 8;
2108 SOFF_T(p
,0,allocation_size
); p
+= 8;
2109 SIVAL(p
,0,mode
); p
+= 4;
2110 q
= p
; p
+= 4; /* q is placeholder for name length */
2111 if (mode
& FILE_ATTRIBUTE_REPARSE_POINT
) {
2112 SIVAL(p
, 0, IO_REPARSE_TAG_DFS
);
2113 } else if (readdir_attr_data
&&
2114 readdir_attr_data
->type
== RDATTR_AAPL
) {
2116 * OS X specific SMB2 extension negotiated via
2117 * AAPL create context: return max_access in
2120 SIVAL(p
, 0, readdir_attr_data
->attr_data
.aapl
.max_access
);
2122 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
2124 SIVAL(p
,0,ea_size
); /* Extended attributes */
2128 if (readdir_attr_data
&&
2129 readdir_attr_data
->type
== RDATTR_AAPL
) {
2131 * OS X specific SMB2 extension negotiated via
2132 * AAPL create context: return resource fork
2133 * length and compressed FinderInfo in
2136 * According to documentation short_name_len
2137 * should be 0, but on the wire behaviour
2138 * shows its set to 24 by clients.
2142 /* Resourefork length */
2143 SBVAL(p
, 2, readdir_attr_data
->attr_data
.aapl
.rfork_size
);
2145 /* Compressed FinderInfo */
2146 memcpy(p
+ 10, &readdir_attr_data
->attr_data
.aapl
.finder_info
, 16);
2147 } else if (!was_8_3
&& check_mangled_names
) {
2148 char mangled_name
[13]; /* mangled 8.3 name. */
2149 if (!name_to_8_3(fname
,mangled_name
,True
,
2151 /* Error - mangle failed ! */
2152 memset(mangled_name
,'\0',12);
2154 mangled_name
[12] = 0;
2155 status
= srvstr_push(base_data
, flags2
,
2156 p
+2, mangled_name
, 24,
2157 STR_UPPER
|STR_UNICODE
, &len
);
2158 if (!NT_STATUS_IS_OK(status
)) {
2163 memset(p
+ 2 + len
,'\0',24 - len
);
2167 /* Clear the short name buffer. This is
2168 * IMPORTANT as not doing so will trigger
2169 * a Win2k client bug. JRA.
2176 if (readdir_attr_data
&&
2177 readdir_attr_data
->type
== RDATTR_AAPL
) {
2179 * OS X specific SMB2 extension negotiated via
2180 * AAPL create context: return UNIX mode in
2183 uint16_t aapl_mode
= (uint16_t)readdir_attr_data
->attr_data
.aapl
.unix_mode
;
2184 SSVAL(p
, 0, aapl_mode
);
2190 SBVAL(p
,0,file_index
); p
+= 8;
2191 status
= srvstr_push(base_data
, flags2
, p
,
2192 fname
, PTR_DIFF(end_data
, p
),
2193 STR_TERMINATE_ASCII
, &len
);
2194 if (!NT_STATUS_IS_OK(status
)) {
2200 len
= PTR_DIFF(p
, pdata
);
2201 pad
= (len
+ (align
-1)) & ~(align
-1);
2203 * offset to the next entry, the caller
2204 * will overwrite it for the last entry
2205 * that's why we always include the padding
2209 * set padding to zero
2212 memset(p
, 0, pad
- len
);
2219 /* CIFS UNIX Extension. */
2221 case SMB_FIND_FILE_UNIX
:
2222 case SMB_FIND_FILE_UNIX_INFO2
:
2224 SIVAL(p
,0,reskey
); p
+= 4; /* Used for continuing search. */
2226 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
2228 if (info_level
== SMB_FIND_FILE_UNIX
) {
2229 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
2230 p
= store_file_unix_basic(conn
, p
,
2231 NULL
, &smb_fname
->st
);
2232 status
= srvstr_push(base_data
, flags2
, p
,
2233 fname
, PTR_DIFF(end_data
, p
),
2234 STR_TERMINATE
, &len
);
2235 if (!NT_STATUS_IS_OK(status
)) {
2239 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
2240 p
= store_file_unix_basic_info2(conn
, p
,
2241 NULL
, &smb_fname
->st
);
2244 status
= srvstr_push(base_data
, flags2
, p
, fname
,
2245 PTR_DIFF(end_data
, p
), 0, &len
);
2246 if (!NT_STATUS_IS_OK(status
)) {
2249 SIVAL(nameptr
, 0, len
);
2254 len
= PTR_DIFF(p
, pdata
);
2255 pad
= (len
+ (align
-1)) & ~(align
-1);
2257 * offset to the next entry, the caller
2258 * will overwrite it for the last entry
2259 * that's why we always include the padding
2263 * set padding to zero
2266 memset(p
, 0, pad
- len
);
2271 /* End of SMB_QUERY_FILE_UNIX_BASIC */
2276 return NT_STATUS_INVALID_LEVEL
;
2279 if (PTR_DIFF(p
,pdata
) > space_remaining
) {
2280 DEBUG(9,("smbd_marshall_dir_entry: out of space "
2281 "(wanted %u, had %d)\n",
2282 (unsigned int)PTR_DIFF(p
,pdata
),
2284 return STATUS_MORE_ENTRIES
; /* Not finished - just out of space */
2287 /* Setup the last entry pointer, as an offset from base_data */
2288 *last_entry_off
= PTR_DIFF(last_entry_ptr
,base_data
);
2289 /* Advance the data pointer to the next slot */
2292 return NT_STATUS_OK
;
2295 NTSTATUS
smbd_dirptr_lanman2_entry(TALLOC_CTX
*ctx
,
2296 connection_struct
*conn
,
2297 struct dptr_struct
*dirptr
,
2299 const char *path_mask
,
2302 int requires_resume_key
,
2310 int space_remaining
,
2311 bool *got_exact_match
,
2312 int *_last_entry_off
,
2313 struct ea_list
*name_list
)
2316 const char *mask
= NULL
;
2317 long prev_dirpos
= 0;
2320 struct smb_filename
*smb_fname
= NULL
;
2321 struct smbd_dirptr_lanman2_state state
;
2323 uint64_t last_entry_off
= 0;
2328 state
.info_level
= info_level
;
2329 state
.check_mangled_names
= lp_mangled_names(conn
->params
);
2330 state
.has_wild
= dptr_has_wild(dirptr
);
2331 state
.got_exact_match
= false;
2333 *got_exact_match
= false;
2335 p
= strrchr_m(path_mask
,'/');
2346 ok
= smbd_dirptr_get_entry(ctx
,
2352 smbd_dirptr_lanman2_match_fn
,
2353 smbd_dirptr_lanman2_mode_fn
,
2360 return NT_STATUS_END_OF_FILE
;
2363 *got_exact_match
= state
.got_exact_match
;
2365 status
= smbd_marshall_dir_entry(ctx
,
2370 state
.check_mangled_names
,
2371 requires_resume_key
,
2382 if (NT_STATUS_EQUAL(status
, NT_STATUS_ILLEGAL_CHARACTER
)) {
2383 DEBUG(1,("Conversion error: illegal character: %s\n",
2384 smb_fname_str_dbg(smb_fname
)));
2387 TALLOC_FREE(smb_fname
);
2388 if (NT_STATUS_EQUAL(status
, STATUS_MORE_ENTRIES
)) {
2389 dptr_SeekDir(dirptr
, prev_dirpos
);
2392 if (!NT_STATUS_IS_OK(status
)) {
2396 *_last_entry_off
= last_entry_off
;
2397 return NT_STATUS_OK
;
2400 static NTSTATUS
get_lanman2_dir_entry(TALLOC_CTX
*ctx
,
2401 connection_struct
*conn
,
2402 struct dptr_struct
*dirptr
,
2404 const char *path_mask
,
2407 bool requires_resume_key
,
2413 int space_remaining
,
2414 bool *got_exact_match
,
2415 int *last_entry_off
,
2416 struct ea_list
*name_list
)
2419 const bool do_pad
= true;
2421 if (info_level
>= 1 && info_level
<= 3) {
2422 /* No alignment on earlier info levels. */
2426 return smbd_dirptr_lanman2_entry(ctx
, conn
, dirptr
, flags2
,
2427 path_mask
, dirtype
, info_level
,
2428 requires_resume_key
, dont_descend
, ask_sharemode
,
2430 ppdata
, base_data
, end_data
,
2433 last_entry_off
, name_list
);
2436 /****************************************************************************
2437 Reply to a TRANS2_FINDFIRST.
2438 ****************************************************************************/
2440 static void call_trans2findfirst(connection_struct
*conn
,
2441 struct smb_request
*req
,
2442 char **pparams
, int total_params
,
2443 char **ppdata
, int total_data
,
2444 unsigned int max_data_bytes
)
2446 /* We must be careful here that we don't return more than the
2447 allowed number of data bytes. If this means returning fewer than
2448 maxentries then so be it. We assume that the redirector has
2449 enough room for the fixed number of parameter bytes it has
2451 struct smb_filename
*smb_dname
= NULL
;
2452 char *params
= *pparams
;
2453 char *pdata
= *ppdata
;
2457 uint16_t findfirst_flags
;
2458 bool close_after_first
;
2460 bool requires_resume_key
;
2462 char *directory
= NULL
;
2465 int last_entry_off
=0;
2469 bool finished
= False
;
2470 bool dont_descend
= False
;
2471 bool out_of_space
= False
;
2472 int space_remaining
;
2473 bool mask_contains_wcard
= False
;
2474 struct ea_list
*ea_list
= NULL
;
2475 NTSTATUS ntstatus
= NT_STATUS_OK
;
2476 bool ask_sharemode
= lp_parm_bool(SNUM(conn
), "smbd", "search ask sharemode", true);
2477 TALLOC_CTX
*ctx
= talloc_tos();
2478 struct dptr_struct
*dirptr
= NULL
;
2479 struct smbd_server_connection
*sconn
= req
->sconn
;
2480 uint32_t ucf_flags
= (UCF_SAVE_LCOMP
| UCF_ALWAYS_ALLOW_WCARD_LCOMP
);
2481 bool backup_priv
= false;
2482 bool as_root
= false;
2484 if (total_params
< 13) {
2485 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2489 dirtype
= SVAL(params
,0);
2490 maxentries
= SVAL(params
,2);
2491 findfirst_flags
= SVAL(params
,4);
2492 close_after_first
= (findfirst_flags
& FLAG_TRANS2_FIND_CLOSE
);
2493 close_if_end
= (findfirst_flags
& FLAG_TRANS2_FIND_CLOSE_IF_END
);
2494 requires_resume_key
= (findfirst_flags
& FLAG_TRANS2_FIND_REQUIRE_RESUME
);
2495 backup_priv
= ((findfirst_flags
& FLAG_TRANS2_FIND_BACKUP_INTENT
) &&
2496 security_token_has_privilege(get_current_nttok(conn
),
2499 info_level
= SVAL(params
,6);
2501 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2502 close_if_end = %d requires_resume_key = %d backup_priv = %d level = 0x%x, max_data_bytes = %d\n",
2503 (unsigned int)dirtype
, maxentries
, close_after_first
, close_if_end
, requires_resume_key
,
2505 info_level
, max_data_bytes
));
2508 /* W2K3 seems to treat zero as 1. */
2512 switch (info_level
) {
2513 case SMB_FIND_INFO_STANDARD
:
2514 case SMB_FIND_EA_SIZE
:
2515 case SMB_FIND_EA_LIST
:
2516 case SMB_FIND_FILE_DIRECTORY_INFO
:
2517 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
2518 case SMB_FIND_FILE_NAMES_INFO
:
2519 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
2520 case SMB_FIND_ID_FULL_DIRECTORY_INFO
:
2521 case SMB_FIND_ID_BOTH_DIRECTORY_INFO
:
2523 case SMB_FIND_FILE_UNIX
:
2524 case SMB_FIND_FILE_UNIX_INFO2
:
2525 /* Always use filesystem for UNIX mtime query. */
2526 ask_sharemode
= false;
2527 if (!lp_unix_extensions()) {
2528 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2531 ucf_flags
|= UCF_UNIX_NAME_LOOKUP
;
2534 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2538 srvstr_get_path_wcard(ctx
, params
, req
->flags2
, &directory
,
2539 params
+12, total_params
- 12,
2540 STR_TERMINATE
, &ntstatus
, &mask_contains_wcard
);
2541 if (!NT_STATUS_IS_OK(ntstatus
)) {
2542 reply_nterror(req
, ntstatus
);
2549 ntstatus
= filename_convert_with_privilege(ctx
,
2554 &mask_contains_wcard
,
2557 ntstatus
= filename_convert(ctx
, conn
,
2558 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
2561 &mask_contains_wcard
,
2565 if (!NT_STATUS_IS_OK(ntstatus
)) {
2566 if (NT_STATUS_EQUAL(ntstatus
,NT_STATUS_PATH_NOT_COVERED
)) {
2567 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
2568 ERRSRV
, ERRbadpath
);
2571 reply_nterror(req
, ntstatus
);
2575 mask
= smb_dname
->original_lcomp
;
2577 directory
= smb_dname
->base_name
;
2579 p
= strrchr_m(directory
,'/');
2581 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2582 if((directory
[0] == '.') && (directory
[1] == '\0')) {
2583 mask
= talloc_strdup(ctx
,"*");
2585 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2588 mask_contains_wcard
= True
;
2594 if (p
== NULL
|| p
== directory
) {
2595 /* Ensure we don't have a directory name of "". */
2596 directory
= talloc_strdup(talloc_tos(), ".");
2598 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2603 DEBUG(5,("dir=%s, mask = %s\n",directory
, mask
));
2605 if (info_level
== SMB_FIND_EA_LIST
) {
2608 if (total_data
< 4) {
2609 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2613 ea_size
= IVAL(pdata
,0);
2614 if (ea_size
!= total_data
) {
2615 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2616 total_data=%u (should be %u)\n", (unsigned int)total_data
, (unsigned int)IVAL(pdata
,0) ));
2617 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2621 if (!lp_ea_support(SNUM(conn
))) {
2622 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
2626 /* Pull out the list of names. */
2627 ea_list
= read_ea_name_list(ctx
, pdata
+ 4, ea_size
- 4);
2629 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2634 if (max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
< max_data_bytes
) {
2635 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2639 *ppdata
= (char *)SMB_REALLOC(
2640 *ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
2641 if(*ppdata
== NULL
) {
2642 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2646 data_end
= pdata
+ max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
- 1;
2648 * squash valgrind "writev(vector[...]) points to uninitialised byte(s)"
2651 memset(pdata
+ total_data
, 0, ((max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
) - total_data
));
2652 /* Realloc the params space */
2653 *pparams
= (char *)SMB_REALLOC(*pparams
, 10);
2654 if (*pparams
== NULL
) {
2655 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2660 /* Save the wildcard match and attribs we are using on this directory -
2661 needed as lanman2 assumes these are being saved between calls */
2663 ntstatus
= dptr_create(conn
,
2671 mask_contains_wcard
,
2675 if (!NT_STATUS_IS_OK(ntstatus
)) {
2676 reply_nterror(req
, ntstatus
);
2681 /* Remember this in case we have
2682 to do a findnext. */
2683 dptr_set_priv(dirptr
);
2686 dptr_num
= dptr_dnum(dirptr
);
2687 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num
, mask
, dirtype
));
2689 /* Initialize per TRANS2_FIND_FIRST operation data */
2690 dptr_init_search_op(dirptr
);
2692 /* We don't need to check for VOL here as this is returned by
2693 a different TRANS2 call. */
2695 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2696 directory
,lp_dont_descend(ctx
, SNUM(conn
))));
2697 if (in_list(directory
,lp_dont_descend(ctx
, SNUM(conn
)),conn
->case_sensitive
))
2698 dont_descend
= True
;
2701 space_remaining
= max_data_bytes
;
2702 out_of_space
= False
;
2704 for (i
=0;(i
<maxentries
) && !finished
&& !out_of_space
;i
++) {
2705 bool got_exact_match
= False
;
2707 /* this is a heuristic to avoid seeking the dirptr except when
2708 absolutely necessary. It allows for a filename of about 40 chars */
2709 if (space_remaining
< DIRLEN_GUESS
&& numentries
> 0) {
2710 out_of_space
= True
;
2713 ntstatus
= get_lanman2_dir_entry(ctx
,
2717 mask
,dirtype
,info_level
,
2718 requires_resume_key
,dont_descend
,
2723 &last_entry_off
, ea_list
);
2724 if (NT_STATUS_EQUAL(ntstatus
,
2725 NT_STATUS_ILLEGAL_CHARACTER
)) {
2727 * Bad character conversion on name. Ignore this
2732 if (NT_STATUS_EQUAL(ntstatus
, STATUS_MORE_ENTRIES
)) {
2733 out_of_space
= true;
2735 finished
= !NT_STATUS_IS_OK(ntstatus
);
2739 if (!finished
&& !out_of_space
)
2743 * As an optimisation if we know we aren't looking
2744 * for a wildcard name (ie. the name matches the wildcard exactly)
2745 * then we can finish on any (first) match.
2746 * This speeds up large directory searches. JRA.
2752 /* Ensure space_remaining never goes -ve. */
2753 if (PTR_DIFF(p
,pdata
) > max_data_bytes
) {
2754 space_remaining
= 0;
2755 out_of_space
= true;
2757 space_remaining
= max_data_bytes
- PTR_DIFF(p
,pdata
);
2761 /* Check if we can close the dirptr */
2762 if(close_after_first
|| (finished
&& close_if_end
)) {
2763 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num
));
2764 dptr_close(sconn
, &dptr_num
);
2768 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2769 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2770 * the protocol level is less than NT1. Tested with smbclient. JRA.
2771 * This should fix the OS/2 client bug #2335.
2774 if(numentries
== 0) {
2775 dptr_close(sconn
, &dptr_num
);
2776 if (get_Protocol() < PROTOCOL_NT1
) {
2777 reply_force_doserror(req
, ERRDOS
, ERRnofiles
);
2780 reply_botherror(req
, NT_STATUS_NO_SUCH_FILE
,
2781 ERRDOS
, ERRbadfile
);
2786 /* At this point pdata points to numentries directory entries. */
2788 /* Set up the return parameter block */
2789 SSVAL(params
,0,dptr_num
);
2790 SSVAL(params
,2,numentries
);
2791 SSVAL(params
,4,finished
);
2792 SSVAL(params
,6,0); /* Never an EA error */
2793 SSVAL(params
,8,last_entry_off
);
2795 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 10, pdata
, PTR_DIFF(p
,pdata
),
2798 if ((! *directory
) && dptr_path(sconn
, dptr_num
)) {
2799 directory
= talloc_strdup(talloc_tos(),dptr_path(sconn
, dptr_num
));
2801 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2805 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2806 smb_fn_name(req
->cmd
),
2807 mask
, directory
, dirtype
, numentries
) );
2810 * Force a name mangle here to ensure that the
2811 * mask as an 8.3 name is top of the mangled cache.
2812 * The reasons for this are subtle. Don't remove
2813 * this code unless you know what you are doing
2814 * (see PR#13758). JRA.
2817 if(!mangle_is_8_3_wildcards( mask
, False
, conn
->params
)) {
2818 char mangled_name
[13];
2819 name_to_8_3(mask
, mangled_name
, True
, conn
->params
);
2827 TALLOC_FREE(smb_dname
);
2831 /****************************************************************************
2832 Reply to a TRANS2_FINDNEXT.
2833 ****************************************************************************/
2835 static void call_trans2findnext(connection_struct
*conn
,
2836 struct smb_request
*req
,
2837 char **pparams
, int total_params
,
2838 char **ppdata
, int total_data
,
2839 unsigned int max_data_bytes
)
2841 /* We must be careful here that we don't return more than the
2842 allowed number of data bytes. If this means returning fewer than
2843 maxentries then so be it. We assume that the redirector has
2844 enough room for the fixed number of parameter bytes it has
2846 char *params
= *pparams
;
2847 char *pdata
= *ppdata
;
2851 uint16_t info_level
;
2852 uint32_t resume_key
;
2853 uint16_t findnext_flags
;
2854 bool close_after_request
;
2856 bool requires_resume_key
;
2858 bool mask_contains_wcard
= False
;
2859 char *resume_name
= NULL
;
2860 const char *mask
= NULL
;
2861 const char *directory
= NULL
;
2865 int i
, last_entry_off
=0;
2866 bool finished
= False
;
2867 bool dont_descend
= False
;
2868 bool out_of_space
= False
;
2869 int space_remaining
;
2870 struct ea_list
*ea_list
= NULL
;
2871 NTSTATUS ntstatus
= NT_STATUS_OK
;
2872 bool ask_sharemode
= lp_parm_bool(SNUM(conn
), "smbd", "search ask sharemode", true);
2873 TALLOC_CTX
*ctx
= talloc_tos();
2874 struct dptr_struct
*dirptr
;
2875 struct smbd_server_connection
*sconn
= req
->sconn
;
2876 bool backup_priv
= false;
2877 bool as_root
= false;
2879 if (total_params
< 13) {
2880 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2884 dptr_num
= SVAL(params
,0);
2885 maxentries
= SVAL(params
,2);
2886 info_level
= SVAL(params
,4);
2887 resume_key
= IVAL(params
,6);
2888 findnext_flags
= SVAL(params
,10);
2889 close_after_request
= (findnext_flags
& FLAG_TRANS2_FIND_CLOSE
);
2890 close_if_end
= (findnext_flags
& FLAG_TRANS2_FIND_CLOSE_IF_END
);
2891 requires_resume_key
= (findnext_flags
& FLAG_TRANS2_FIND_REQUIRE_RESUME
);
2892 continue_bit
= (findnext_flags
& FLAG_TRANS2_FIND_CONTINUE
);
2894 if (!continue_bit
) {
2895 /* We only need resume_name if continue_bit is zero. */
2896 srvstr_get_path_wcard(ctx
, params
, req
->flags2
, &resume_name
,
2898 total_params
- 12, STR_TERMINATE
, &ntstatus
,
2899 &mask_contains_wcard
);
2900 if (!NT_STATUS_IS_OK(ntstatus
)) {
2901 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2902 complain (it thinks we're asking for the directory above the shared
2903 path or an invalid name). Catch this as the resume name is only compared, never used in
2904 a file access. JRA. */
2905 srvstr_pull_talloc(ctx
, params
, req
->flags2
,
2906 &resume_name
, params
+12,
2910 if (!resume_name
|| !(ISDOT(resume_name
) || ISDOTDOT(resume_name
))) {
2911 reply_nterror(req
, ntstatus
);
2917 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2918 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2919 resume_key = %d resume name = %s continue=%d level = %d\n",
2920 dptr_num
, max_data_bytes
, maxentries
, close_after_request
, close_if_end
,
2921 requires_resume_key
, resume_key
,
2922 resume_name
? resume_name
: "(NULL)", continue_bit
, info_level
));
2925 /* W2K3 seems to treat zero as 1. */
2929 switch (info_level
) {
2930 case SMB_FIND_INFO_STANDARD
:
2931 case SMB_FIND_EA_SIZE
:
2932 case SMB_FIND_EA_LIST
:
2933 case SMB_FIND_FILE_DIRECTORY_INFO
:
2934 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
2935 case SMB_FIND_FILE_NAMES_INFO
:
2936 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
2937 case SMB_FIND_ID_FULL_DIRECTORY_INFO
:
2938 case SMB_FIND_ID_BOTH_DIRECTORY_INFO
:
2940 case SMB_FIND_FILE_UNIX
:
2941 case SMB_FIND_FILE_UNIX_INFO2
:
2942 /* Always use filesystem for UNIX mtime query. */
2943 ask_sharemode
= false;
2944 if (!lp_unix_extensions()) {
2945 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2950 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2954 if (info_level
== SMB_FIND_EA_LIST
) {
2957 if (total_data
< 4) {
2958 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2962 ea_size
= IVAL(pdata
,0);
2963 if (ea_size
!= total_data
) {
2964 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2965 total_data=%u (should be %u)\n", (unsigned int)total_data
, (unsigned int)IVAL(pdata
,0) ));
2966 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2970 if (!lp_ea_support(SNUM(conn
))) {
2971 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
2975 /* Pull out the list of names. */
2976 ea_list
= read_ea_name_list(ctx
, pdata
+ 4, ea_size
- 4);
2978 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2983 if (max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
< max_data_bytes
) {
2984 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2988 *ppdata
= (char *)SMB_REALLOC(
2989 *ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
2990 if(*ppdata
== NULL
) {
2991 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2996 data_end
= pdata
+ max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
- 1;
2999 * squash valgrind "writev(vector[...]) points to uninitialised byte(s)"
3002 memset(pdata
+ total_data
, 0, (max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
) - total_data
);
3003 /* Realloc the params space */
3004 *pparams
= (char *)SMB_REALLOC(*pparams
, 6*SIZEOFWORD
);
3005 if(*pparams
== NULL
) {
3006 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
3012 /* Check that the dptr is valid */
3013 if(!(dirptr
= dptr_fetch_lanman2(sconn
, dptr_num
))) {
3014 reply_nterror(req
, STATUS_NO_MORE_FILES
);
3018 directory
= dptr_path(sconn
, dptr_num
);
3020 /* Get the wildcard mask from the dptr */
3021 if((mask
= dptr_wcard(sconn
, dptr_num
))== NULL
) {
3022 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num
));
3023 reply_nterror(req
, STATUS_NO_MORE_FILES
);
3027 /* Get the attr mask from the dptr */
3028 dirtype
= dptr_attr(sconn
, dptr_num
);
3030 backup_priv
= dptr_get_priv(dirptr
);
3032 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld) "
3033 "backup_priv = %d\n",
3034 dptr_num
, mask
, dirtype
,
3036 dptr_TellDir(dirptr
),
3039 /* Initialize per TRANS2_FIND_NEXT operation data */
3040 dptr_init_search_op(dirptr
);
3042 /* We don't need to check for VOL here as this is returned by
3043 a different TRANS2 call. */
3045 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
3046 directory
,lp_dont_descend(ctx
, SNUM(conn
))));
3047 if (in_list(directory
,lp_dont_descend(ctx
, SNUM(conn
)),conn
->case_sensitive
))
3048 dont_descend
= True
;
3051 space_remaining
= max_data_bytes
;
3052 out_of_space
= False
;
3060 * Seek to the correct position. We no longer use the resume key but
3061 * depend on the last file name instead.
3064 if(!continue_bit
&& resume_name
&& *resume_name
) {
3067 long current_pos
= 0;
3069 * Remember, name_to_8_3 is called by
3070 * get_lanman2_dir_entry(), so the resume name
3071 * could be mangled. Ensure we check the unmangled name.
3074 if (mangle_is_mangled(resume_name
, conn
->params
)) {
3075 char *new_resume_name
= NULL
;
3076 mangle_lookup_name_from_8_3(ctx
,
3080 if (new_resume_name
) {
3081 resume_name
= new_resume_name
;
3086 * Fix for NT redirector problem triggered by resume key indexes
3087 * changing between directory scans. We now return a resume key of 0
3088 * and instead look for the filename to continue from (also given
3089 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
3090 * findfirst/findnext (as is usual) then the directory pointer
3091 * should already be at the correct place.
3094 finished
= !dptr_SearchDir(dirptr
, resume_name
, ¤t_pos
, &st
);
3095 } /* end if resume_name && !continue_bit */
3097 for (i
=0;(i
<(int)maxentries
) && !finished
&& !out_of_space
;i
++) {
3098 bool got_exact_match
= False
;
3100 /* this is a heuristic to avoid seeking the dirptr except when
3101 absolutely necessary. It allows for a filename of about 40 chars */
3102 if (space_remaining
< DIRLEN_GUESS
&& numentries
> 0) {
3103 out_of_space
= True
;
3106 ntstatus
= get_lanman2_dir_entry(ctx
,
3110 mask
,dirtype
,info_level
,
3111 requires_resume_key
,dont_descend
,
3116 &last_entry_off
, ea_list
);
3117 if (NT_STATUS_EQUAL(ntstatus
,
3118 NT_STATUS_ILLEGAL_CHARACTER
)) {
3120 * Bad character conversion on name. Ignore this
3125 if (NT_STATUS_EQUAL(ntstatus
, STATUS_MORE_ENTRIES
)) {
3126 out_of_space
= true;
3128 finished
= !NT_STATUS_IS_OK(ntstatus
);
3132 if (!finished
&& !out_of_space
)
3136 * As an optimisation if we know we aren't looking
3137 * for a wildcard name (ie. the name matches the wildcard exactly)
3138 * then we can finish on any (first) match.
3139 * This speeds up large directory searches. JRA.
3145 space_remaining
= max_data_bytes
- PTR_DIFF(p
,pdata
);
3148 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
3149 smb_fn_name(req
->cmd
),
3150 mask
, directory
, dirtype
, numentries
) );
3152 /* Check if we can close the dirptr */
3153 if(close_after_request
|| (finished
&& close_if_end
)) {
3154 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num
));
3155 dptr_close(sconn
, &dptr_num
); /* This frees up the saved mask */
3162 /* Set up the return parameter block */
3163 SSVAL(params
,0,numentries
);
3164 SSVAL(params
,2,finished
);
3165 SSVAL(params
,4,0); /* Never an EA error */
3166 SSVAL(params
,6,last_entry_off
);
3168 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 8, pdata
, PTR_DIFF(p
,pdata
),
3174 unsigned char *create_volume_objectid(connection_struct
*conn
, unsigned char objid
[16])
3176 E_md4hash(lp_servicename(talloc_tos(), SNUM(conn
)),objid
);
3180 static void samba_extended_info_version(struct smb_extended_info
*extended_info
)
3182 SMB_ASSERT(extended_info
!= NULL
);
3184 extended_info
->samba_magic
= SAMBA_EXTENDED_INFO_MAGIC
;
3185 extended_info
->samba_version
= ((SAMBA_VERSION_MAJOR
& 0xff) << 24)
3186 | ((SAMBA_VERSION_MINOR
& 0xff) << 16)
3187 | ((SAMBA_VERSION_RELEASE
& 0xff) << 8);
3188 #ifdef SAMBA_VERSION_REVISION
3189 extended_info
->samba_version
|= (tolower(*SAMBA_VERSION_REVISION
) - 'a' + 1) & 0xff;
3191 extended_info
->samba_subversion
= 0;
3192 #ifdef SAMBA_VERSION_RC_RELEASE
3193 extended_info
->samba_subversion
|= (SAMBA_VERSION_RC_RELEASE
& 0xff) << 24;
3195 #ifdef SAMBA_VERSION_PRE_RELEASE
3196 extended_info
->samba_subversion
|= (SAMBA_VERSION_PRE_RELEASE
& 0xff) << 16;
3199 #ifdef SAMBA_VERSION_VENDOR_PATCH
3200 extended_info
->samba_subversion
|= (SAMBA_VERSION_VENDOR_PATCH
& 0xffff);
3202 extended_info
->samba_gitcommitdate
= 0;
3203 #ifdef SAMBA_VERSION_COMMIT_TIME
3204 unix_to_nt_time(&extended_info
->samba_gitcommitdate
, SAMBA_VERSION_COMMIT_TIME
);
3207 memset(extended_info
->samba_version_string
, 0,
3208 sizeof(extended_info
->samba_version_string
));
3210 snprintf (extended_info
->samba_version_string
,
3211 sizeof(extended_info
->samba_version_string
),
3212 "%s", samba_version_string());
3215 NTSTATUS
smbd_do_qfsinfo(struct smbXsrv_connection
*xconn
,
3216 connection_struct
*conn
,
3217 TALLOC_CTX
*mem_ctx
,
3218 uint16_t info_level
,
3220 unsigned int max_data_bytes
,
3221 size_t *fixed_portion
,
3222 struct smb_filename
*fname
,
3226 char *pdata
, *end_data
;
3229 const char *vname
= volume_label(talloc_tos(), SNUM(conn
));
3230 int snum
= SNUM(conn
);
3231 const char *fstype
= lp_fstype(SNUM(conn
));
3232 const char *filename
= NULL
;
3233 const uint64_t bytes_per_sector
= 512;
3234 uint32_t additional_flags
= 0;
3235 struct smb_filename smb_fname
;
3237 NTSTATUS status
= NT_STATUS_OK
;
3240 if (fname
== NULL
|| fname
->base_name
== NULL
) {
3243 filename
= fname
->base_name
;
3247 if (info_level
!= SMB_QUERY_CIFS_UNIX_INFO
) {
3248 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
3249 "info level (0x%x) on IPC$.\n",
3250 (unsigned int)info_level
));
3251 return NT_STATUS_ACCESS_DENIED
;
3255 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level
));
3257 ZERO_STRUCT(smb_fname
);
3258 smb_fname
.base_name
= discard_const_p(char, filename
);
3260 if(SMB_VFS_STAT(conn
, &smb_fname
) != 0) {
3261 DEBUG(2,("stat of . failed (%s)\n", strerror(errno
)));
3262 return map_nt_error_from_unix(errno
);
3267 if (max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
< max_data_bytes
) {
3268 return NT_STATUS_INVALID_PARAMETER
;
3271 *ppdata
= (char *)SMB_REALLOC(
3272 *ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
3273 if (*ppdata
== NULL
) {
3274 return NT_STATUS_NO_MEMORY
;
3278 memset((char *)pdata
,'\0',max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
3279 end_data
= pdata
+ max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
- 1;
3283 switch (info_level
) {
3284 case SMB_INFO_ALLOCATION
:
3286 uint64_t dfree
,dsize
,bsize
,block_size
,sectors_per_unit
;
3288 df_ret
= get_dfree_info(conn
, filename
, &bsize
, &dfree
,
3290 if (df_ret
== (uint64_t)-1) {
3291 return map_nt_error_from_unix(errno
);
3294 block_size
= lp_block_size(snum
);
3295 if (bsize
< block_size
) {
3296 uint64_t factor
= block_size
/bsize
;
3301 if (bsize
> block_size
) {
3302 uint64_t factor
= bsize
/block_size
;
3307 sectors_per_unit
= bsize
/bytes_per_sector
;
3309 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
3310 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st
.st_ex_dev
, (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
3311 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
3313 SIVAL(pdata
,l1_idFileSystem
,st
.st_ex_dev
);
3314 SIVAL(pdata
,l1_cSectorUnit
,sectors_per_unit
);
3315 SIVAL(pdata
,l1_cUnit
,dsize
);
3316 SIVAL(pdata
,l1_cUnitAvail
,dfree
);
3317 SSVAL(pdata
,l1_cbSector
,bytes_per_sector
);
3321 case SMB_INFO_VOLUME
:
3322 /* Return volume name */
3324 * Add volume serial number - hash of a combination of
3325 * the called hostname and the service name.
3327 SIVAL(pdata
,0,str_checksum(lp_servicename(talloc_tos(), snum
)) ^ (str_checksum(get_local_machine_name())<<16) );
3329 * Win2k3 and previous mess this up by sending a name length
3330 * one byte short. I believe only older clients (OS/2 Win9x) use
3331 * this call so try fixing this by adding a terminating null to
3332 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
3334 status
= srvstr_push(
3336 pdata
+l2_vol_szVolLabel
, vname
,
3337 PTR_DIFF(end_data
, pdata
+l2_vol_szVolLabel
),
3338 STR_NOALIGN
|STR_TERMINATE
, &len
);
3339 if (!NT_STATUS_IS_OK(status
)) {
3342 SCVAL(pdata
,l2_vol_cch
,len
);
3343 data_len
= l2_vol_szVolLabel
+ len
;
3344 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %u, name = %s\n",
3345 (unsigned)convert_timespec_to_time_t(st
.st_ex_ctime
),
3346 (unsigned)len
, vname
));
3349 case SMB_QUERY_FS_ATTRIBUTE_INFO
:
3350 case SMB_FS_ATTRIBUTE_INFORMATION
:
3352 additional_flags
= 0;
3353 #if defined(HAVE_SYS_QUOTAS)
3354 additional_flags
|= FILE_VOLUME_QUOTAS
;
3357 if(lp_nt_acl_support(SNUM(conn
))) {
3358 additional_flags
|= FILE_PERSISTENT_ACLS
;
3361 /* Capabilities are filled in at connection time through STATVFS call */
3362 additional_flags
|= conn
->fs_capabilities
;
3363 additional_flags
|= lp_parm_int(conn
->params
->service
,
3364 "share", "fake_fscaps",
3367 SIVAL(pdata
,0,FILE_CASE_PRESERVED_NAMES
|FILE_CASE_SENSITIVE_SEARCH
|
3368 FILE_SUPPORTS_OBJECT_IDS
|FILE_UNICODE_ON_DISK
|
3369 additional_flags
); /* FS ATTRIBUTES */
3371 SIVAL(pdata
,4,255); /* Max filename component length */
3372 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
3373 and will think we can't do long filenames */
3374 status
= srvstr_push(pdata
, flags2
, pdata
+12, fstype
,
3375 PTR_DIFF(end_data
, pdata
+12),
3377 if (!NT_STATUS_IS_OK(status
)) {
3381 data_len
= 12 + len
;
3382 if (max_data_bytes
>= 16 && data_len
> max_data_bytes
) {
3383 /* the client only requested a portion of the
3385 data_len
= max_data_bytes
;
3386 status
= STATUS_BUFFER_OVERFLOW
;
3388 *fixed_portion
= 16;
3391 case SMB_QUERY_FS_LABEL_INFO
:
3392 case SMB_FS_LABEL_INFORMATION
:
3393 status
= srvstr_push(pdata
, flags2
, pdata
+4, vname
,
3394 PTR_DIFF(end_data
, pdata
+4), 0, &len
);
3395 if (!NT_STATUS_IS_OK(status
)) {
3402 case SMB_QUERY_FS_VOLUME_INFO
:
3403 case SMB_FS_VOLUME_INFORMATION
:
3406 * Add volume serial number - hash of a combination of
3407 * the called hostname and the service name.
3409 SIVAL(pdata
,8,str_checksum(lp_servicename(talloc_tos(), snum
)) ^
3410 (str_checksum(get_local_machine_name())<<16));
3412 /* Max label len is 32 characters. */
3413 status
= srvstr_push(pdata
, flags2
, pdata
+18, vname
,
3414 PTR_DIFF(end_data
, pdata
+18),
3416 if (!NT_STATUS_IS_OK(status
)) {
3419 SIVAL(pdata
,12,len
);
3422 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3423 (int)strlen(vname
),vname
,
3424 lp_servicename(talloc_tos(), snum
)));
3425 if (max_data_bytes
>= 24 && data_len
> max_data_bytes
) {
3426 /* the client only requested a portion of the
3428 data_len
= max_data_bytes
;
3429 status
= STATUS_BUFFER_OVERFLOW
;
3431 *fixed_portion
= 24;
3434 case SMB_QUERY_FS_SIZE_INFO
:
3435 case SMB_FS_SIZE_INFORMATION
:
3437 uint64_t dfree
,dsize
,bsize
,block_size
,sectors_per_unit
;
3439 df_ret
= get_dfree_info(conn
, filename
, &bsize
, &dfree
,
3441 if (df_ret
== (uint64_t)-1) {
3442 return map_nt_error_from_unix(errno
);
3444 block_size
= lp_block_size(snum
);
3445 if (bsize
< block_size
) {
3446 uint64_t factor
= block_size
/bsize
;
3451 if (bsize
> block_size
) {
3452 uint64_t factor
= bsize
/block_size
;
3457 sectors_per_unit
= bsize
/bytes_per_sector
;
3458 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3459 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
3460 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
3461 SBIG_UINT(pdata
,0,dsize
);
3462 SBIG_UINT(pdata
,8,dfree
);
3463 SIVAL(pdata
,16,sectors_per_unit
);
3464 SIVAL(pdata
,20,bytes_per_sector
);
3465 *fixed_portion
= 24;
3469 case SMB_FS_FULL_SIZE_INFORMATION
:
3471 uint64_t dfree
,dsize
,bsize
,block_size
,sectors_per_unit
;
3473 df_ret
= get_dfree_info(conn
, filename
, &bsize
, &dfree
,
3475 if (df_ret
== (uint64_t)-1) {
3476 return map_nt_error_from_unix(errno
);
3478 block_size
= lp_block_size(snum
);
3479 if (bsize
< block_size
) {
3480 uint64_t factor
= block_size
/bsize
;
3485 if (bsize
> block_size
) {
3486 uint64_t factor
= bsize
/block_size
;
3491 sectors_per_unit
= bsize
/bytes_per_sector
;
3492 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3493 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
3494 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
3495 SBIG_UINT(pdata
,0,dsize
); /* Total Allocation units. */
3496 SBIG_UINT(pdata
,8,dfree
); /* Caller available allocation units. */
3497 SBIG_UINT(pdata
,16,dfree
); /* Actual available allocation units. */
3498 SIVAL(pdata
,24,sectors_per_unit
); /* Sectors per allocation unit. */
3499 SIVAL(pdata
,28,bytes_per_sector
); /* Bytes per sector. */
3500 *fixed_portion
= 32;
3504 case SMB_QUERY_FS_DEVICE_INFO
:
3505 case SMB_FS_DEVICE_INFORMATION
:
3507 uint32_t characteristics
= FILE_DEVICE_IS_MOUNTED
;
3509 if (!CAN_WRITE(conn
)) {
3510 characteristics
|= FILE_READ_ONLY_DEVICE
;
3513 SIVAL(pdata
,0,FILE_DEVICE_DISK
); /* dev type */
3514 SIVAL(pdata
,4,characteristics
);
3519 #ifdef HAVE_SYS_QUOTAS
3520 case SMB_FS_QUOTA_INFORMATION
:
3522 * what we have to send --metze:
3524 * Unknown1: 24 NULL bytes
3525 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3526 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3527 * Quota Flags: 2 byte :
3528 * Unknown3: 6 NULL bytes
3532 * details for Quota Flags:
3534 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3535 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3536 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3537 * 0x0001 Enable Quotas: enable quota for this fs
3541 /* we need to fake up a fsp here,
3542 * because its not send in this call
3545 SMB_NTQUOTA_STRUCT quotas
;
3548 ZERO_STRUCT(quotas
);
3551 fsp
.fnum
= FNUM_FIELD_INVALID
;
3554 if (get_current_uid(conn
) != 0) {
3555 DEBUG(0,("get_user_quota: access_denied "
3556 "service [%s] user [%s]\n",
3557 lp_servicename(talloc_tos(), SNUM(conn
)),
3558 conn
->session_info
->unix_info
->unix_name
));
3559 return NT_STATUS_ACCESS_DENIED
;
3562 if (vfs_get_ntquota(&fsp
, SMB_USER_FS_QUOTA_TYPE
, NULL
, "as
)!=0) {
3563 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn
))));
3564 return map_nt_error_from_unix(errno
);
3569 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3570 lp_servicename(talloc_tos(), SNUM(conn
))));
3572 /* Unknown1 24 NULL bytes*/
3573 SBIG_UINT(pdata
,0,(uint64_t)0);
3574 SBIG_UINT(pdata
,8,(uint64_t)0);
3575 SBIG_UINT(pdata
,16,(uint64_t)0);
3577 /* Default Soft Quota 8 bytes */
3578 SBIG_UINT(pdata
,24,quotas
.softlim
);
3580 /* Default Hard Quota 8 bytes */
3581 SBIG_UINT(pdata
,32,quotas
.hardlim
);
3583 /* Quota flag 2 bytes */
3584 SSVAL(pdata
,40,quotas
.qflags
);
3586 /* Unknown3 6 NULL bytes */
3592 #endif /* HAVE_SYS_QUOTAS */
3593 case SMB_FS_OBJECTID_INFORMATION
:
3595 unsigned char objid
[16];
3596 struct smb_extended_info extended_info
;
3597 memcpy(pdata
,create_volume_objectid(conn
, objid
),16);
3598 samba_extended_info_version (&extended_info
);
3599 SIVAL(pdata
,16,extended_info
.samba_magic
);
3600 SIVAL(pdata
,20,extended_info
.samba_version
);
3601 SIVAL(pdata
,24,extended_info
.samba_subversion
);
3602 SBIG_UINT(pdata
,28,extended_info
.samba_gitcommitdate
);
3603 memcpy(pdata
+36,extended_info
.samba_version_string
,28);
3608 case SMB_FS_SECTOR_SIZE_INFORMATION
:
3612 * These values match a physical Windows Server 2012
3613 * share backed by NTFS atop spinning rust.
3615 DEBUG(5, ("SMB_FS_SECTOR_SIZE_INFORMATION:"));
3616 /* logical_bytes_per_sector */
3617 SIVAL(pdata
, 0, bytes_per_sector
);
3618 /* phys_bytes_per_sector_atomic */
3619 SIVAL(pdata
, 4, bytes_per_sector
);
3620 /* phys_bytes_per_sector_perf */
3621 SIVAL(pdata
, 8, bytes_per_sector
);
3622 /* fs_effective_phys_bytes_per_sector_atomic */
3623 SIVAL(pdata
, 12, bytes_per_sector
);
3625 SIVAL(pdata
, 16, SSINFO_FLAGS_ALIGNED_DEVICE
3626 | SSINFO_FLAGS_PARTITION_ALIGNED_ON_DEVICE
);
3627 /* byte_off_sector_align */
3628 SIVAL(pdata
, 20, 0);
3629 /* byte_off_partition_align */
3630 SIVAL(pdata
, 24, 0);
3631 *fixed_portion
= 28;
3637 * Query the version and capabilities of the CIFS UNIX extensions
3641 case SMB_QUERY_CIFS_UNIX_INFO
:
3643 bool large_write
= lp_min_receive_file_size() &&
3644 !srv_is_signing_active(xconn
);
3645 bool large_read
= !srv_is_signing_active(xconn
);
3646 int encrypt_caps
= 0;
3648 if (!lp_unix_extensions()) {
3649 return NT_STATUS_INVALID_LEVEL
;
3652 switch (conn
->encrypt_level
) {
3653 case SMB_SIGNING_OFF
:
3656 case SMB_SIGNING_DESIRED
:
3657 case SMB_SIGNING_IF_REQUIRED
:
3658 case SMB_SIGNING_DEFAULT
:
3659 encrypt_caps
= CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP
;
3661 case SMB_SIGNING_REQUIRED
:
3662 encrypt_caps
= CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP
|
3663 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP
;
3664 large_write
= false;
3670 SSVAL(pdata
,0,CIFS_UNIX_MAJOR_VERSION
);
3671 SSVAL(pdata
,2,CIFS_UNIX_MINOR_VERSION
);
3673 /* We have POSIX ACLs, pathname, encryption,
3674 * large read/write, and locking capability. */
3676 SBIG_UINT(pdata
,4,((uint64_t)(
3677 CIFS_UNIX_POSIX_ACLS_CAP
|
3678 CIFS_UNIX_POSIX_PATHNAMES_CAP
|
3679 CIFS_UNIX_FCNTL_LOCKS_CAP
|
3680 CIFS_UNIX_EXTATTR_CAP
|
3681 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP
|
3683 (large_read
? CIFS_UNIX_LARGE_READ_CAP
: 0) |
3685 CIFS_UNIX_LARGE_WRITE_CAP
: 0))));
3689 case SMB_QUERY_POSIX_FS_INFO
:
3692 vfs_statvfs_struct svfs
;
3694 if (!lp_unix_extensions()) {
3695 return NT_STATUS_INVALID_LEVEL
;
3698 rc
= SMB_VFS_STATVFS(conn
, filename
, &svfs
);
3702 SIVAL(pdata
,0,svfs
.OptimalTransferSize
);
3703 SIVAL(pdata
,4,svfs
.BlockSize
);
3704 SBIG_UINT(pdata
,8,svfs
.TotalBlocks
);
3705 SBIG_UINT(pdata
,16,svfs
.BlocksAvail
);
3706 SBIG_UINT(pdata
,24,svfs
.UserBlocksAvail
);
3707 SBIG_UINT(pdata
,32,svfs
.TotalFileNodes
);
3708 SBIG_UINT(pdata
,40,svfs
.FreeFileNodes
);
3709 SBIG_UINT(pdata
,48,svfs
.FsIdentifier
);
3710 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3712 } else if (rc
== EOPNOTSUPP
) {
3713 return NT_STATUS_INVALID_LEVEL
;
3714 #endif /* EOPNOTSUPP */
3716 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn
))));
3717 return NT_STATUS_DOS(ERRSRV
, ERRerror
);
3722 case SMB_QUERY_POSIX_WHOAMI
:
3728 if (!lp_unix_extensions()) {
3729 return NT_STATUS_INVALID_LEVEL
;
3732 if (max_data_bytes
< 40) {
3733 return NT_STATUS_BUFFER_TOO_SMALL
;
3736 if (security_session_user_level(conn
->session_info
, NULL
) < SECURITY_USER
) {
3737 flags
|= SMB_WHOAMI_GUEST
;
3740 /* NOTE: 8 bytes for UID/GID, irrespective of native
3741 * platform size. This matches
3742 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3744 data_len
= 4 /* flags */
3751 + 4 /* pad/reserved */
3752 + (conn
->session_info
->unix_token
->ngroups
* 8)
3754 + (conn
->session_info
->security_token
->num_sids
*
3758 SIVAL(pdata
, 0, flags
);
3759 SIVAL(pdata
, 4, SMB_WHOAMI_MASK
);
3761 (uint64_t)conn
->session_info
->unix_token
->uid
);
3762 SBIG_UINT(pdata
, 16,
3763 (uint64_t)conn
->session_info
->unix_token
->gid
);
3766 if (data_len
>= max_data_bytes
) {
3767 /* Potential overflow, skip the GIDs and SIDs. */
3769 SIVAL(pdata
, 24, 0); /* num_groups */
3770 SIVAL(pdata
, 28, 0); /* num_sids */
3771 SIVAL(pdata
, 32, 0); /* num_sid_bytes */
3772 SIVAL(pdata
, 36, 0); /* reserved */
3778 SIVAL(pdata
, 24, conn
->session_info
->unix_token
->ngroups
);
3779 SIVAL(pdata
, 28, conn
->session_info
->security_token
->num_sids
);
3781 /* We walk the SID list twice, but this call is fairly
3782 * infrequent, and I don't expect that it's performance
3783 * sensitive -- jpeach
3785 for (i
= 0, sid_bytes
= 0;
3786 i
< conn
->session_info
->security_token
->num_sids
; ++i
) {
3787 sid_bytes
+= ndr_size_dom_sid(
3788 &conn
->session_info
->security_token
->sids
[i
],
3792 /* SID list byte count */
3793 SIVAL(pdata
, 32, sid_bytes
);
3795 /* 4 bytes pad/reserved - must be zero */
3796 SIVAL(pdata
, 36, 0);
3800 for (i
= 0; i
< conn
->session_info
->unix_token
->ngroups
; ++i
) {
3801 SBIG_UINT(pdata
, data_len
,
3802 (uint64_t)conn
->session_info
->unix_token
->groups
[i
]);
3808 i
< conn
->session_info
->security_token
->num_sids
; ++i
) {
3809 int sid_len
= ndr_size_dom_sid(
3810 &conn
->session_info
->security_token
->sids
[i
],
3813 sid_linearize((uint8_t *)(pdata
+ data_len
),
3815 &conn
->session_info
->security_token
->sids
[i
]);
3816 data_len
+= sid_len
;
3822 case SMB_MAC_QUERY_FS_INFO
:
3824 * Thursby MAC extension... ONLY on NTFS filesystems
3825 * once we do streams then we don't need this
3827 if (strequal(lp_fstype(SNUM(conn
)),"NTFS")) {
3829 SIVAL(pdata
,84,0x100); /* Don't support mac... */
3834 return NT_STATUS_INVALID_LEVEL
;
3837 *ret_data_len
= data_len
;
3841 /****************************************************************************
3842 Reply to a TRANS2_QFSINFO (query filesystem info).
3843 ****************************************************************************/
3845 static void call_trans2qfsinfo(connection_struct
*conn
,
3846 struct smb_request
*req
,
3847 char **pparams
, int total_params
,
3848 char **ppdata
, int total_data
,
3849 unsigned int max_data_bytes
)
3851 char *params
= *pparams
;
3852 uint16_t info_level
;
3854 size_t fixed_portion
;
3857 if (total_params
< 2) {
3858 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3862 info_level
= SVAL(params
,0);
3864 if (ENCRYPTION_REQUIRED(conn
) && !req
->encrypted
) {
3865 if (info_level
!= SMB_QUERY_CIFS_UNIX_INFO
) {
3866 DEBUG(0,("call_trans2qfsinfo: encryption required "
3867 "and info level 0x%x sent.\n",
3868 (unsigned int)info_level
));
3869 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3874 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level
));
3876 status
= smbd_do_qfsinfo(req
->xconn
, conn
, req
,
3883 if (!NT_STATUS_IS_OK(status
)) {
3884 reply_nterror(req
, status
);
3888 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 0, *ppdata
, data_len
,
3891 DEBUG( 4, ( "%s info_level = %d\n",
3892 smb_fn_name(req
->cmd
), info_level
) );
3897 /****************************************************************************
3898 Reply to a TRANS2_SETFSINFO (set filesystem info).
3899 ****************************************************************************/
3901 static void call_trans2setfsinfo(connection_struct
*conn
,
3902 struct smb_request
*req
,
3903 char **pparams
, int total_params
,
3904 char **ppdata
, int total_data
,
3905 unsigned int max_data_bytes
)
3907 struct smbXsrv_connection
*xconn
= req
->xconn
;
3908 char *pdata
= *ppdata
;
3909 char *params
= *pparams
;
3910 uint16_t info_level
;
3912 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",
3913 lp_servicename(talloc_tos(), SNUM(conn
))));
3916 if (total_params
< 4) {
3917 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3919 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3923 info_level
= SVAL(params
,2);
3926 if (info_level
!= SMB_REQUEST_TRANSPORT_ENCRYPTION
&&
3927 info_level
!= SMB_SET_CIFS_UNIX_INFO
) {
3928 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3929 "info level (0x%x) on IPC$.\n",
3930 (unsigned int)info_level
));
3931 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3936 if (ENCRYPTION_REQUIRED(conn
) && !req
->encrypted
) {
3937 if (info_level
!= SMB_REQUEST_TRANSPORT_ENCRYPTION
) {
3938 DEBUG(0,("call_trans2setfsinfo: encryption required "
3939 "and info level 0x%x sent.\n",
3940 (unsigned int)info_level
));
3941 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3946 switch(info_level
) {
3947 case SMB_SET_CIFS_UNIX_INFO
:
3948 if (!lp_unix_extensions()) {
3949 DEBUG(2,("call_trans2setfsinfo: "
3950 "SMB_SET_CIFS_UNIX_INFO is invalid with "
3951 "unix extensions off\n"));
3953 NT_STATUS_INVALID_LEVEL
);
3957 /* There should be 12 bytes of capabilities set. */
3958 if (total_data
< 12) {
3961 NT_STATUS_INVALID_PARAMETER
);
3964 xconn
->smb1
.unix_info
.client_major
= SVAL(pdata
,0);
3965 xconn
->smb1
.unix_info
.client_minor
= SVAL(pdata
,2);
3966 xconn
->smb1
.unix_info
.client_cap_low
= IVAL(pdata
,4);
3967 xconn
->smb1
.unix_info
.client_cap_high
= IVAL(pdata
,8);
3968 /* Just print these values for now. */
3969 DEBUG(10, ("call_trans2setfsinfo: set unix_info info. "
3970 "major = %u, minor = %u cap_low = 0x%x, "
3972 (unsigned int)xconn
->
3973 smb1
.unix_info
.client_major
,
3974 (unsigned int)xconn
->
3975 smb1
.unix_info
.client_minor
,
3976 (unsigned int)xconn
->
3977 smb1
.unix_info
.client_cap_low
,
3978 (unsigned int)xconn
->
3979 smb1
.unix_info
.client_cap_high
));
3981 /* Here is where we must switch to posix pathname processing... */
3982 if (xconn
->smb1
.unix_info
.client_cap_low
& CIFS_UNIX_POSIX_PATHNAMES_CAP
) {
3983 lp_set_posix_pathnames();
3984 mangle_change_to_posix();
3987 if ((xconn
->smb1
.unix_info
.client_cap_low
& CIFS_UNIX_FCNTL_LOCKS_CAP
) &&
3988 !(xconn
->smb1
.unix_info
.client_cap_low
& CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP
)) {
3989 /* Client that knows how to do posix locks,
3990 * but not posix open/mkdir operations. Set a
3991 * default type for read/write checks. */
3993 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK
);
3998 case SMB_REQUEST_TRANSPORT_ENCRYPTION
:
4001 size_t param_len
= 0;
4002 size_t data_len
= total_data
;
4004 if (!lp_unix_extensions()) {
4007 NT_STATUS_INVALID_LEVEL
);
4011 if (lp_smb_encrypt(SNUM(conn
)) == SMB_SIGNING_OFF
) {
4014 NT_STATUS_NOT_SUPPORTED
);
4018 if (xconn
->smb1
.echo_handler
.trusted_fde
) {
4019 DEBUG( 2,("call_trans2setfsinfo: "
4020 "request transport encryption disabled"
4021 "with 'fork echo handler = yes'\n"));
4024 NT_STATUS_NOT_SUPPORTED
);
4028 DEBUG( 4,("call_trans2setfsinfo: "
4029 "request transport encryption.\n"));
4031 status
= srv_request_encryption_setup(conn
,
4032 (unsigned char **)ppdata
,
4034 (unsigned char **)pparams
,
4037 if (!NT_STATUS_EQUAL(status
, NT_STATUS_MORE_PROCESSING_REQUIRED
) &&
4038 !NT_STATUS_IS_OK(status
)) {
4039 reply_nterror(req
, status
);
4043 send_trans2_replies(conn
, req
,
4051 if (NT_STATUS_IS_OK(status
)) {
4052 /* Server-side transport
4053 * encryption is now *on*. */
4054 status
= srv_encryption_start(conn
);
4055 if (!NT_STATUS_IS_OK(status
)) {
4056 char *reason
= talloc_asprintf(talloc_tos(),
4057 "Failure in setting "
4058 "up encrypted transport: %s",
4060 exit_server_cleanly(reason
);
4066 case SMB_FS_QUOTA_INFORMATION
:
4068 files_struct
*fsp
= NULL
;
4069 SMB_NTQUOTA_STRUCT quotas
;
4071 ZERO_STRUCT(quotas
);
4074 if ((get_current_uid(conn
) != 0) || !CAN_WRITE(conn
)) {
4075 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
4076 lp_servicename(talloc_tos(), SNUM(conn
)),
4077 conn
->session_info
->unix_info
->unix_name
));
4078 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
4082 /* note: normally there're 48 bytes,
4083 * but we didn't use the last 6 bytes for now
4086 fsp
= file_fsp(req
, SVAL(params
,0));
4088 if (!check_fsp_ntquota_handle(conn
, req
,
4090 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
4092 req
, NT_STATUS_INVALID_HANDLE
);
4096 if (total_data
< 42) {
4097 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
4101 NT_STATUS_INVALID_PARAMETER
);
4105 /* unknown_1 24 NULL bytes in pdata*/
4107 /* the soft quotas 8 bytes (uint64_t)*/
4108 quotas
.softlim
= BVAL(pdata
,24);
4110 /* the hard quotas 8 bytes (uint64_t)*/
4111 quotas
.hardlim
= BVAL(pdata
,32);
4113 /* quota_flags 2 bytes **/
4114 quotas
.qflags
= SVAL(pdata
,40);
4116 /* unknown_2 6 NULL bytes follow*/
4118 /* now set the quotas */
4119 if (vfs_set_ntquota(fsp
, SMB_USER_FS_QUOTA_TYPE
, NULL
, "as
)!=0) {
4120 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn
))));
4121 reply_nterror(req
, map_nt_error_from_unix(errno
));
4128 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
4130 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
4136 * sending this reply works fine,
4137 * but I'm not sure it's the same
4138 * like windows do...
4141 reply_outbuf(req
, 10, 0);
4144 #if defined(HAVE_POSIX_ACLS)
4145 /****************************************************************************
4146 Utility function to count the number of entries in a POSIX acl.
4147 ****************************************************************************/
4149 static unsigned int count_acl_entries(connection_struct
*conn
, SMB_ACL_T posix_acl
)
4151 unsigned int ace_count
= 0;
4152 int entry_id
= SMB_ACL_FIRST_ENTRY
;
4153 SMB_ACL_ENTRY_T entry
;
4155 while ( posix_acl
&& (sys_acl_get_entry(posix_acl
, entry_id
, &entry
) == 1)) {
4157 if (entry_id
== SMB_ACL_FIRST_ENTRY
) {
4158 entry_id
= SMB_ACL_NEXT_ENTRY
;
4165 /****************************************************************************
4166 Utility function to marshall a POSIX acl into wire format.
4167 ****************************************************************************/
4169 static bool marshall_posix_acl(connection_struct
*conn
, char *pdata
, SMB_STRUCT_STAT
*pst
, SMB_ACL_T posix_acl
)
4171 int entry_id
= SMB_ACL_FIRST_ENTRY
;
4172 SMB_ACL_ENTRY_T entry
;
4174 while ( posix_acl
&& (sys_acl_get_entry(posix_acl
, entry_id
, &entry
) == 1)) {
4175 SMB_ACL_TAG_T tagtype
;
4176 SMB_ACL_PERMSET_T permset
;
4177 unsigned char perms
= 0;
4178 unsigned int own_grp
;
4181 if (entry_id
== SMB_ACL_FIRST_ENTRY
) {
4182 entry_id
= SMB_ACL_NEXT_ENTRY
;
4185 if (sys_acl_get_tag_type(entry
, &tagtype
) == -1) {
4186 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
4190 if (sys_acl_get_permset(entry
, &permset
) == -1) {
4191 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
4195 perms
|= (sys_acl_get_perm(permset
, SMB_ACL_READ
) ? SMB_POSIX_ACL_READ
: 0);
4196 perms
|= (sys_acl_get_perm(permset
, SMB_ACL_WRITE
) ? SMB_POSIX_ACL_WRITE
: 0);
4197 perms
|= (sys_acl_get_perm(permset
, SMB_ACL_EXECUTE
) ? SMB_POSIX_ACL_EXECUTE
: 0);
4199 SCVAL(pdata
,1,perms
);
4202 case SMB_ACL_USER_OBJ
:
4203 SCVAL(pdata
,0,SMB_POSIX_ACL_USER_OBJ
);
4204 own_grp
= (unsigned int)pst
->st_ex_uid
;
4205 SIVAL(pdata
,2,own_grp
);
4210 uid_t
*puid
= (uid_t
*)sys_acl_get_qualifier(entry
);
4212 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
4215 own_grp
= (unsigned int)*puid
;
4216 SCVAL(pdata
,0,SMB_POSIX_ACL_USER
);
4217 SIVAL(pdata
,2,own_grp
);
4221 case SMB_ACL_GROUP_OBJ
:
4222 SCVAL(pdata
,0,SMB_POSIX_ACL_GROUP_OBJ
);
4223 own_grp
= (unsigned int)pst
->st_ex_gid
;
4224 SIVAL(pdata
,2,own_grp
);
4229 gid_t
*pgid
= (gid_t
*)sys_acl_get_qualifier(entry
);
4231 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
4234 own_grp
= (unsigned int)*pgid
;
4235 SCVAL(pdata
,0,SMB_POSIX_ACL_GROUP
);
4236 SIVAL(pdata
,2,own_grp
);
4241 SCVAL(pdata
,0,SMB_POSIX_ACL_MASK
);
4242 SIVAL(pdata
,2,0xFFFFFFFF);
4243 SIVAL(pdata
,6,0xFFFFFFFF);
4246 SCVAL(pdata
,0,SMB_POSIX_ACL_OTHER
);
4247 SIVAL(pdata
,2,0xFFFFFFFF);
4248 SIVAL(pdata
,6,0xFFFFFFFF);
4251 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
4254 pdata
+= SMB_POSIX_ACL_ENTRY_SIZE
;
4261 /****************************************************************************
4262 Store the FILE_UNIX_BASIC info.
4263 ****************************************************************************/
4265 static char *store_file_unix_basic(connection_struct
*conn
,
4268 const SMB_STRUCT_STAT
*psbuf
)
4270 uint64_t file_index
= get_FileIndex(conn
, psbuf
);
4273 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
4274 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf
->st_ex_mode
));
4276 SOFF_T(pdata
,0,get_file_size_stat(psbuf
)); /* File size 64 Bit */
4279 SOFF_T(pdata
,0,SMB_VFS_GET_ALLOC_SIZE(conn
,fsp
,psbuf
)); /* Number of bytes used on disk - 64 Bit */
4282 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER
, pdata
, psbuf
->st_ex_ctime
); /* Change Time 64 Bit */
4283 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER
,pdata
+8, psbuf
->st_ex_atime
); /* Last access time 64 Bit */
4284 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER
, pdata
+16, psbuf
->st_ex_mtime
); /* Last modification time 64 Bit */
4287 SIVAL(pdata
,0,psbuf
->st_ex_uid
); /* user id for the owner */
4291 SIVAL(pdata
,0,psbuf
->st_ex_gid
); /* group id of owner */
4295 SIVAL(pdata
,0,unix_filetype(psbuf
->st_ex_mode
));
4298 if (S_ISBLK(psbuf
->st_ex_mode
) || S_ISCHR(psbuf
->st_ex_mode
)) {
4299 devno
= psbuf
->st_ex_rdev
;
4301 devno
= psbuf
->st_ex_dev
;
4304 SIVAL(pdata
,0,unix_dev_major(devno
)); /* Major device number if type is device */
4308 SIVAL(pdata
,0,unix_dev_minor(devno
)); /* Minor device number if type is device */
4312 SINO_T_VAL(pdata
,0,(SMB_INO_T
)file_index
); /* inode number */
4315 SIVAL(pdata
,0, unix_perms_to_wire(psbuf
->st_ex_mode
)); /* Standard UNIX file permissions */
4319 SIVAL(pdata
,0,psbuf
->st_ex_nlink
); /* number of hard links */
4326 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
4327 * the chflags(2) (or equivalent) flags.
4329 * XXX: this really should be behind the VFS interface. To do this, we would
4330 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
4331 * Each VFS module could then implement its own mapping as appropriate for the
4332 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
4334 static const struct {unsigned stat_fflag
; unsigned smb_fflag
;}
4338 { UF_NODUMP
, EXT_DO_NOT_BACKUP
},
4342 { UF_IMMUTABLE
, EXT_IMMUTABLE
},
4346 { UF_APPEND
, EXT_OPEN_APPEND_ONLY
},
4350 { UF_HIDDEN
, EXT_HIDDEN
},
4353 /* Do not remove. We need to guarantee that this array has at least one
4354 * entry to build on HP-UX.
4360 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT
*psbuf
,
4361 uint32_t *smb_fflags
, uint32_t *smb_fmask
)
4365 for (i
= 0; i
< ARRAY_SIZE(info2_flags_map
); ++i
) {
4366 *smb_fmask
|= info2_flags_map
[i
].smb_fflag
;
4367 if (psbuf
->st_ex_flags
& info2_flags_map
[i
].stat_fflag
) {
4368 *smb_fflags
|= info2_flags_map
[i
].smb_fflag
;
4373 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT
*psbuf
,
4374 const uint32_t smb_fflags
,
4375 const uint32_t smb_fmask
,
4378 uint32_t max_fmask
= 0;
4381 *stat_fflags
= psbuf
->st_ex_flags
;
4383 /* For each flags requested in smb_fmask, check the state of the
4384 * corresponding flag in smb_fflags and set or clear the matching
4388 for (i
= 0; i
< ARRAY_SIZE(info2_flags_map
); ++i
) {
4389 max_fmask
|= info2_flags_map
[i
].smb_fflag
;
4390 if (smb_fmask
& info2_flags_map
[i
].smb_fflag
) {
4391 if (smb_fflags
& info2_flags_map
[i
].smb_fflag
) {
4392 *stat_fflags
|= info2_flags_map
[i
].stat_fflag
;
4394 *stat_fflags
&= ~info2_flags_map
[i
].stat_fflag
;
4399 /* If smb_fmask is asking to set any bits that are not supported by
4400 * our flag mappings, we should fail.
4402 if ((smb_fmask
& max_fmask
) != smb_fmask
) {
4410 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
4411 * of file flags and birth (create) time.
4413 static char *store_file_unix_basic_info2(connection_struct
*conn
,
4416 const SMB_STRUCT_STAT
*psbuf
)
4418 uint32_t file_flags
= 0;
4419 uint32_t flags_mask
= 0;
4421 pdata
= store_file_unix_basic(conn
, pdata
, fsp
, psbuf
);
4423 /* Create (birth) time 64 bit */
4424 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER
,pdata
, psbuf
->st_ex_btime
);
4427 map_info2_flags_from_sbuf(psbuf
, &file_flags
, &flags_mask
);
4428 SIVAL(pdata
, 0, file_flags
); /* flags */
4429 SIVAL(pdata
, 4, flags_mask
); /* mask */
4435 static NTSTATUS
marshall_stream_info(unsigned int num_streams
,
4436 const struct stream_struct
*streams
,
4438 unsigned int max_data_bytes
,
4439 unsigned int *data_size
)
4442 unsigned int ofs
= 0;
4444 if (max_data_bytes
< 32) {
4445 return NT_STATUS_INFO_LENGTH_MISMATCH
;
4448 for (i
= 0; i
< num_streams
; i
++) {
4449 unsigned int next_offset
;
4451 smb_ucs2_t
*namebuf
;
4453 if (!push_ucs2_talloc(talloc_tos(), &namebuf
,
4454 streams
[i
].name
, &namelen
) ||
4457 return NT_STATUS_INVALID_PARAMETER
;
4461 * name_buf is now null-terminated, we need to marshall as not
4468 * We cannot overflow ...
4470 if ((ofs
+ 24 + namelen
) > max_data_bytes
) {
4471 DEBUG(10, ("refusing to overflow reply at stream %u\n",
4473 TALLOC_FREE(namebuf
);
4474 return STATUS_BUFFER_OVERFLOW
;
4477 SIVAL(data
, ofs
+4, namelen
);
4478 SOFF_T(data
, ofs
+8, streams
[i
].size
);
4479 SOFF_T(data
, ofs
+16, streams
[i
].alloc_size
);
4480 memcpy(data
+ofs
+24, namebuf
, namelen
);
4481 TALLOC_FREE(namebuf
);
4483 next_offset
= ofs
+ 24 + namelen
;
4485 if (i
== num_streams
-1) {
4486 SIVAL(data
, ofs
, 0);
4489 unsigned int align
= ndr_align_size(next_offset
, 8);
4491 if ((next_offset
+ align
) > max_data_bytes
) {
4492 DEBUG(10, ("refusing to overflow align "
4493 "reply at stream %u\n",
4495 TALLOC_FREE(namebuf
);
4496 return STATUS_BUFFER_OVERFLOW
;
4499 memset(data
+next_offset
, 0, align
);
4500 next_offset
+= align
;
4502 SIVAL(data
, ofs
, next_offset
- ofs
);
4509 DEBUG(10, ("max_data: %u, data_size: %u\n", max_data_bytes
, ofs
));
4513 return NT_STATUS_OK
;
4516 /****************************************************************************
4517 Reply to a TRANSACT2_QFILEINFO on a PIPE !
4518 ****************************************************************************/
4520 static void call_trans2qpipeinfo(connection_struct
*conn
,
4521 struct smb_request
*req
,
4522 unsigned int tran_call
,
4523 char **pparams
, int total_params
,
4524 char **ppdata
, int total_data
,
4525 unsigned int max_data_bytes
)
4527 char *params
= *pparams
;
4528 char *pdata
= *ppdata
;
4529 unsigned int data_size
= 0;
4530 unsigned int param_size
= 2;
4531 uint16_t info_level
;
4535 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4539 if (total_params
< 4) {
4540 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4544 fsp
= file_fsp(req
, SVAL(params
,0));
4545 if (!fsp_is_np(fsp
)) {
4546 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
4550 info_level
= SVAL(params
,2);
4552 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
4553 if (*pparams
== NULL
) {
4554 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
4559 if (max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
< max_data_bytes
) {
4560 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4563 data_size
= max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
;
4564 *ppdata
= (char *)SMB_REALLOC(*ppdata
, data_size
);
4565 if (*ppdata
== NULL
) {
4566 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
4571 switch (info_level
) {
4572 case SMB_FILE_STANDARD_INFORMATION
:
4574 SOFF_T(pdata
,0,4096LL);
4581 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
4585 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, param_size
, *ppdata
, data_size
,
4591 NTSTATUS
smbd_do_qfilepathinfo(connection_struct
*conn
,
4592 TALLOC_CTX
*mem_ctx
,
4593 uint16_t info_level
,
4595 struct smb_filename
*smb_fname
,
4596 bool delete_pending
,
4597 struct timespec write_time_ts
,
4598 struct ea_list
*ea_list
,
4599 int lock_data_count
,
4602 unsigned int max_data_bytes
,
4603 size_t *fixed_portion
,
4605 unsigned int *pdata_size
)
4607 char *pdata
= *ppdata
;
4608 char *dstart
, *dend
;
4609 unsigned int data_size
;
4610 struct timespec create_time_ts
, mtime_ts
, atime_ts
, ctime_ts
;
4611 time_t create_time
, mtime
, atime
, c_time
;
4612 SMB_STRUCT_STAT
*psbuf
= &smb_fname
->st
;
4619 uint64_t file_size
= 0;
4621 uint64_t allocation_size
= 0;
4622 uint64_t file_index
= 0;
4623 uint32_t access_mask
= 0;
4626 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
4627 return NT_STATUS_INVALID_LEVEL
;
4630 DEBUG(5,("smbd_do_qfilepathinfo: %s (%s) level=%d max_data=%u\n",
4631 smb_fname_str_dbg(smb_fname
),
4633 info_level
, max_data_bytes
));
4635 mode
= dos_mode(conn
, smb_fname
);
4636 nlink
= psbuf
->st_ex_nlink
;
4638 if (nlink
&& (mode
&FILE_ATTRIBUTE_DIRECTORY
)) {
4642 if ((nlink
> 0) && delete_pending
) {
4646 if (max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
< max_data_bytes
) {
4647 return NT_STATUS_INVALID_PARAMETER
;
4650 data_size
= max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
;
4651 *ppdata
= (char *)SMB_REALLOC(*ppdata
, data_size
);
4652 if (*ppdata
== NULL
) {
4653 return NT_STATUS_NO_MEMORY
;
4657 dend
= dstart
+ data_size
- 1;
4659 if (!null_timespec(write_time_ts
) && !INFO_LEVEL_IS_UNIX(info_level
)) {
4660 update_stat_ex_mtime(psbuf
, write_time_ts
);
4663 create_time_ts
= get_create_timespec(conn
, fsp
, smb_fname
);
4664 mtime_ts
= psbuf
->st_ex_mtime
;
4665 atime_ts
= psbuf
->st_ex_atime
;
4666 ctime_ts
= get_change_timespec(conn
, fsp
, smb_fname
);
4668 if (lp_dos_filetime_resolution(SNUM(conn
))) {
4669 dos_filetime_timespec(&create_time_ts
);
4670 dos_filetime_timespec(&mtime_ts
);
4671 dos_filetime_timespec(&atime_ts
);
4672 dos_filetime_timespec(&ctime_ts
);
4675 create_time
= convert_timespec_to_time_t(create_time_ts
);
4676 mtime
= convert_timespec_to_time_t(mtime_ts
);
4677 atime
= convert_timespec_to_time_t(atime_ts
);
4678 c_time
= convert_timespec_to_time_t(ctime_ts
);
4680 p
= strrchr_m(smb_fname
->base_name
,'/');
4682 base_name
= smb_fname
->base_name
;
4686 /* NT expects the name to be in an exact form of the *full*
4687 filename. See the trans2 torture test */
4688 if (ISDOT(base_name
)) {
4689 dos_fname
= talloc_strdup(mem_ctx
, "\\");
4691 return NT_STATUS_NO_MEMORY
;
4694 dos_fname
= talloc_asprintf(mem_ctx
,
4696 smb_fname
->base_name
);
4698 return NT_STATUS_NO_MEMORY
;
4700 if (is_ntfs_stream_smb_fname(smb_fname
)) {
4701 dos_fname
= talloc_asprintf(dos_fname
, "%s",
4702 smb_fname
->stream_name
);
4704 return NT_STATUS_NO_MEMORY
;
4708 string_replace(dos_fname
, '/', '\\');
4711 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
, fsp
, psbuf
);
4714 /* Do we have this path open ? */
4716 struct file_id fileid
= vfs_file_id_from_sbuf(conn
, psbuf
);
4717 fsp1
= file_find_di_first(conn
->sconn
, fileid
);
4718 if (fsp1
&& fsp1
->initial_allocation_size
) {
4719 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
, fsp1
, psbuf
);
4723 if (!(mode
& FILE_ATTRIBUTE_DIRECTORY
)) {
4724 file_size
= get_file_size_stat(psbuf
);
4728 pos
= fsp
->fh
->position_information
;
4732 access_mask
= fsp
->access_mask
;
4734 /* GENERIC_EXECUTE mapping from Windows */
4735 access_mask
= 0x12019F;
4738 /* This should be an index number - looks like
4741 I think this causes us to fail the IFSKIT
4742 BasicFileInformationTest. -tpot */
4743 file_index
= get_FileIndex(conn
, psbuf
);
4747 switch (info_level
) {
4748 case SMB_INFO_STANDARD
:
4749 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4751 srv_put_dos_date2(pdata
,l1_fdateCreation
,create_time
);
4752 srv_put_dos_date2(pdata
,l1_fdateLastAccess
,atime
);
4753 srv_put_dos_date2(pdata
,l1_fdateLastWrite
,mtime
); /* write time */
4754 SIVAL(pdata
,l1_cbFile
,(uint32_t)file_size
);
4755 SIVAL(pdata
,l1_cbFileAlloc
,(uint32_t)allocation_size
);
4756 SSVAL(pdata
,l1_attrFile
,mode
);
4759 case SMB_INFO_QUERY_EA_SIZE
:
4761 unsigned int ea_size
=
4762 estimate_ea_size(conn
, fsp
,
4764 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4766 srv_put_dos_date2(pdata
,0,create_time
);
4767 srv_put_dos_date2(pdata
,4,atime
);
4768 srv_put_dos_date2(pdata
,8,mtime
); /* write time */
4769 SIVAL(pdata
,12,(uint32_t)file_size
);
4770 SIVAL(pdata
,16,(uint32_t)allocation_size
);
4771 SSVAL(pdata
,20,mode
);
4772 SIVAL(pdata
,22,ea_size
);
4776 case SMB_INFO_IS_NAME_VALID
:
4777 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4779 /* os/2 needs this ? really ?*/
4780 return NT_STATUS_DOS(ERRDOS
, ERRbadfunc
);
4782 /* This is only reached for qpathinfo */
4786 case SMB_INFO_QUERY_EAS_FROM_LIST
:
4788 size_t total_ea_len
= 0;
4789 struct ea_list
*ea_file_list
= NULL
;
4790 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4793 get_ea_list_from_file(mem_ctx
, conn
, fsp
,
4795 &total_ea_len
, &ea_file_list
);
4796 if (!NT_STATUS_IS_OK(status
)) {
4800 ea_list
= ea_list_union(ea_list
, ea_file_list
, &total_ea_len
);
4802 if (!ea_list
|| (total_ea_len
> data_size
)) {
4804 SIVAL(pdata
,0,4); /* EA List Length must be set to 4 if no EA's. */
4808 data_size
= fill_ea_buffer(mem_ctx
, pdata
, data_size
, conn
, ea_list
);
4812 case SMB_INFO_QUERY_ALL_EAS
:
4814 /* We have data_size bytes to put EA's into. */
4815 size_t total_ea_len
= 0;
4816 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4818 status
= get_ea_list_from_file(mem_ctx
, conn
, fsp
,
4820 &total_ea_len
, &ea_list
);
4821 if (!NT_STATUS_IS_OK(status
)) {
4825 if (!ea_list
|| (total_ea_len
> data_size
)) {
4827 SIVAL(pdata
,0,4); /* EA List Length must be set to 4 if no EA's. */
4831 data_size
= fill_ea_buffer(mem_ctx
, pdata
, data_size
, conn
, ea_list
);
4835 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
4837 /* This is FileFullEaInformation - 0xF which maps to
4838 * 1015 (decimal) in smbd_do_setfilepathinfo. */
4840 /* We have data_size bytes to put EA's into. */
4841 size_t total_ea_len
= 0;
4842 struct ea_list
*ea_file_list
= NULL
;
4844 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
4846 /*TODO: add filtering and index handling */
4849 get_ea_list_from_file(mem_ctx
, conn
, fsp
,
4851 &total_ea_len
, &ea_file_list
);
4852 if (!NT_STATUS_IS_OK(status
)) {
4855 if (!ea_file_list
) {
4856 return NT_STATUS_NO_EAS_ON_FILE
;
4859 status
= fill_ea_chained_buffer(mem_ctx
,
4863 conn
, ea_file_list
);
4864 if (!NT_STATUS_IS_OK(status
)) {
4870 case SMB_FILE_BASIC_INFORMATION
:
4871 case SMB_QUERY_FILE_BASIC_INFO
:
4873 if (info_level
== SMB_QUERY_FILE_BASIC_INFO
) {
4874 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4875 data_size
= 36; /* w95 returns 40 bytes not 36 - why ?. */
4877 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4881 put_long_date_timespec(conn
->ts_res
,pdata
,create_time_ts
);
4882 put_long_date_timespec(conn
->ts_res
,pdata
+8,atime_ts
);
4883 put_long_date_timespec(conn
->ts_res
,pdata
+16,mtime_ts
); /* write time */
4884 put_long_date_timespec(conn
->ts_res
,pdata
+24,ctime_ts
); /* change time */
4885 SIVAL(pdata
,32,mode
);
4887 DEBUG(5,("SMB_QFBI - "));
4888 DEBUG(5,("create: %s ", ctime(&create_time
)));
4889 DEBUG(5,("access: %s ", ctime(&atime
)));
4890 DEBUG(5,("write: %s ", ctime(&mtime
)));
4891 DEBUG(5,("change: %s ", ctime(&c_time
)));
4892 DEBUG(5,("mode: %x\n", mode
));
4893 *fixed_portion
= data_size
;
4896 case SMB_FILE_STANDARD_INFORMATION
:
4897 case SMB_QUERY_FILE_STANDARD_INFO
:
4899 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4901 SOFF_T(pdata
,0,allocation_size
);
4902 SOFF_T(pdata
,8,file_size
);
4903 SIVAL(pdata
,16,nlink
);
4904 SCVAL(pdata
,20,delete_pending
?1:0);
4905 SCVAL(pdata
,21,(mode
&FILE_ATTRIBUTE_DIRECTORY
)?1:0);
4906 SSVAL(pdata
,22,0); /* Padding. */
4907 *fixed_portion
= 24;
4910 case SMB_FILE_EA_INFORMATION
:
4911 case SMB_QUERY_FILE_EA_INFO
:
4913 unsigned int ea_size
=
4914 estimate_ea_size(conn
, fsp
, smb_fname
);
4915 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4918 SIVAL(pdata
,0,ea_size
);
4922 /* Get the 8.3 name - used if NT SMB was negotiated. */
4923 case SMB_QUERY_FILE_ALT_NAME_INFO
:
4924 case SMB_FILE_ALTERNATE_NAME_INFORMATION
:
4926 char mangled_name
[13];
4927 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4928 if (!name_to_8_3(base_name
,mangled_name
,
4929 True
,conn
->params
)) {
4930 return NT_STATUS_NO_MEMORY
;
4932 status
= srvstr_push(dstart
, flags2
,
4933 pdata
+4, mangled_name
,
4934 PTR_DIFF(dend
, pdata
+4),
4936 if (!NT_STATUS_IS_OK(status
)) {
4939 data_size
= 4 + len
;
4945 case SMB_QUERY_FILE_NAME_INFO
:
4948 this must be *exactly* right for ACLs on mapped drives to work
4950 status
= srvstr_push(dstart
, flags2
,
4952 PTR_DIFF(dend
, pdata
+4),
4954 if (!NT_STATUS_IS_OK(status
)) {
4957 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4958 data_size
= 4 + len
;
4963 case SMB_FILE_ALLOCATION_INFORMATION
:
4964 case SMB_QUERY_FILE_ALLOCATION_INFO
:
4965 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4967 SOFF_T(pdata
,0,allocation_size
);
4970 case SMB_FILE_END_OF_FILE_INFORMATION
:
4971 case SMB_QUERY_FILE_END_OF_FILEINFO
:
4972 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4974 SOFF_T(pdata
,0,file_size
);
4977 case SMB_QUERY_FILE_ALL_INFO
:
4978 case SMB_FILE_ALL_INFORMATION
:
4980 unsigned int ea_size
=
4981 estimate_ea_size(conn
, fsp
, smb_fname
);
4982 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4983 put_long_date_timespec(conn
->ts_res
,pdata
,create_time_ts
);
4984 put_long_date_timespec(conn
->ts_res
,pdata
+8,atime_ts
);
4985 put_long_date_timespec(conn
->ts_res
,pdata
+16,mtime_ts
); /* write time */
4986 put_long_date_timespec(conn
->ts_res
,pdata
+24,ctime_ts
); /* change time */
4987 SIVAL(pdata
,32,mode
);
4988 SIVAL(pdata
,36,0); /* padding. */
4990 SOFF_T(pdata
,0,allocation_size
);
4991 SOFF_T(pdata
,8,file_size
);
4992 SIVAL(pdata
,16,nlink
);
4993 SCVAL(pdata
,20,delete_pending
);
4994 SCVAL(pdata
,21,(mode
&FILE_ATTRIBUTE_DIRECTORY
)?1:0);
4997 SIVAL(pdata
,0,ea_size
);
4998 pdata
+= 4; /* EA info */
4999 status
= srvstr_push(dstart
, flags2
,
5001 PTR_DIFF(dend
, pdata
+4),
5003 if (!NT_STATUS_IS_OK(status
)) {
5008 data_size
= PTR_DIFF(pdata
,(*ppdata
));
5009 *fixed_portion
= 10;
5013 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
5015 unsigned int ea_size
=
5016 estimate_ea_size(conn
, fsp
, smb_fname
);
5017 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
5018 put_long_date_timespec(conn
->ts_res
,pdata
+0x00,create_time_ts
);
5019 put_long_date_timespec(conn
->ts_res
,pdata
+0x08,atime_ts
);
5020 put_long_date_timespec(conn
->ts_res
,pdata
+0x10,mtime_ts
); /* write time */
5021 put_long_date_timespec(conn
->ts_res
,pdata
+0x18,ctime_ts
); /* change time */
5022 SIVAL(pdata
, 0x20, mode
);
5023 SIVAL(pdata
, 0x24, 0); /* padding. */
5024 SBVAL(pdata
, 0x28, allocation_size
);
5025 SBVAL(pdata
, 0x30, file_size
);
5026 SIVAL(pdata
, 0x38, nlink
);
5027 SCVAL(pdata
, 0x3C, delete_pending
);
5028 SCVAL(pdata
, 0x3D, (mode
&FILE_ATTRIBUTE_DIRECTORY
)?1:0);
5029 SSVAL(pdata
, 0x3E, 0); /* padding */
5030 SBVAL(pdata
, 0x40, file_index
);
5031 SIVAL(pdata
, 0x48, ea_size
);
5032 SIVAL(pdata
, 0x4C, access_mask
);
5033 SBVAL(pdata
, 0x50, pos
);
5034 SIVAL(pdata
, 0x58, mode
); /*TODO: mode != mode fix this!!! */
5035 SIVAL(pdata
, 0x5C, 0); /* No alignment needed. */
5039 status
= srvstr_push(dstart
, flags2
,
5041 PTR_DIFF(dend
, pdata
+4),
5043 if (!NT_STATUS_IS_OK(status
)) {
5048 data_size
= PTR_DIFF(pdata
,(*ppdata
));
5049 *fixed_portion
= 104;
5052 case SMB_FILE_INTERNAL_INFORMATION
:
5054 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
5055 SBVAL(pdata
, 0, file_index
);
5060 case SMB_FILE_ACCESS_INFORMATION
:
5061 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
5062 SIVAL(pdata
, 0, access_mask
);
5067 case SMB_FILE_NAME_INFORMATION
:
5068 /* Pathname with leading '\'. */
5071 byte_len
= dos_PutUniCode(pdata
+4,dos_fname
,(size_t)max_data_bytes
,False
);
5072 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
5073 SIVAL(pdata
,0,byte_len
);
5074 data_size
= 4 + byte_len
;
5078 case SMB_FILE_DISPOSITION_INFORMATION
:
5079 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
5081 SCVAL(pdata
,0,delete_pending
);
5085 case SMB_FILE_POSITION_INFORMATION
:
5086 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
5088 SOFF_T(pdata
,0,pos
);
5092 case SMB_FILE_MODE_INFORMATION
:
5093 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
5094 SIVAL(pdata
,0,mode
);
5099 case SMB_FILE_ALIGNMENT_INFORMATION
:
5100 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
5101 SIVAL(pdata
,0,0); /* No alignment needed. */
5107 * NT4 server just returns "invalid query" to this - if we try
5108 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
5111 /* The first statement above is false - verified using Thursby
5112 * client against NT4 -- gcolley.
5114 case SMB_QUERY_FILE_STREAM_INFO
:
5115 case SMB_FILE_STREAM_INFORMATION
: {
5116 unsigned int num_streams
= 0;
5117 struct stream_struct
*streams
= NULL
;
5119 DEBUG(10,("smbd_do_qfilepathinfo: "
5120 "SMB_FILE_STREAM_INFORMATION\n"));
5122 if (is_ntfs_stream_smb_fname(smb_fname
)) {
5123 return NT_STATUS_INVALID_PARAMETER
;
5126 status
= vfs_streaminfo(conn
, fsp
, smb_fname
->base_name
,
5127 talloc_tos(), &num_streams
, &streams
);
5129 if (!NT_STATUS_IS_OK(status
)) {
5130 DEBUG(10, ("could not get stream info: %s\n",
5131 nt_errstr(status
)));
5135 status
= marshall_stream_info(num_streams
, streams
,
5136 pdata
, max_data_bytes
,
5139 if (!NT_STATUS_IS_OK(status
)) {
5140 DEBUG(10, ("marshall_stream_info failed: %s\n",
5141 nt_errstr(status
)));
5142 TALLOC_FREE(streams
);
5146 TALLOC_FREE(streams
);
5148 *fixed_portion
= 32;
5152 case SMB_QUERY_COMPRESSION_INFO
:
5153 case SMB_FILE_COMPRESSION_INFORMATION
:
5154 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
5155 SOFF_T(pdata
,0,file_size
);
5156 SIVAL(pdata
,8,0); /* ??? */
5157 SIVAL(pdata
,12,0); /* ??? */
5159 *fixed_portion
= 16;
5162 case SMB_FILE_NETWORK_OPEN_INFORMATION
:
5163 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
5164 put_long_date_timespec(conn
->ts_res
,pdata
,create_time_ts
);
5165 put_long_date_timespec(conn
->ts_res
,pdata
+8,atime_ts
);
5166 put_long_date_timespec(conn
->ts_res
,pdata
+16,mtime_ts
); /* write time */
5167 put_long_date_timespec(conn
->ts_res
,pdata
+24,ctime_ts
); /* change time */
5168 SOFF_T(pdata
,32,allocation_size
);
5169 SOFF_T(pdata
,40,file_size
);
5170 SIVAL(pdata
,48,mode
);
5171 SIVAL(pdata
,52,0); /* ??? */
5173 *fixed_portion
= 56;
5176 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION
:
5177 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
5178 SIVAL(pdata
,0,mode
);
5185 * CIFS UNIX Extensions.
5188 case SMB_QUERY_FILE_UNIX_BASIC
:
5190 pdata
= store_file_unix_basic(conn
, pdata
, fsp
, psbuf
);
5191 data_size
= PTR_DIFF(pdata
,(*ppdata
));
5193 DEBUG(4,("smbd_do_qfilepathinfo: "
5194 "SMB_QUERY_FILE_UNIX_BASIC\n"));
5195 dump_data(4, (uint8_t *)(*ppdata
), data_size
);
5199 case SMB_QUERY_FILE_UNIX_INFO2
:
5201 pdata
= store_file_unix_basic_info2(conn
, pdata
, fsp
, psbuf
);
5202 data_size
= PTR_DIFF(pdata
,(*ppdata
));
5206 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
5208 for (i
=0; i
<100; i
++)
5209 DEBUG(4,("%d=%x, ",i
, (*ppdata
)[i
]));
5215 case SMB_QUERY_FILE_UNIX_LINK
:
5218 char *buffer
= talloc_array(mem_ctx
, char, PATH_MAX
+1);
5221 return NT_STATUS_NO_MEMORY
;
5224 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
5226 if(!S_ISLNK(psbuf
->st_ex_mode
)) {
5227 return NT_STATUS_DOS(ERRSRV
, ERRbadlink
);
5230 return NT_STATUS_DOS(ERRDOS
, ERRbadlink
);
5232 link_len
= SMB_VFS_READLINK(conn
,
5233 smb_fname
->base_name
,
5235 if (link_len
== -1) {
5236 return map_nt_error_from_unix(errno
);
5238 buffer
[link_len
] = 0;
5239 status
= srvstr_push(dstart
, flags2
,
5241 PTR_DIFF(dend
, pdata
),
5242 STR_TERMINATE
, &len
);
5243 if (!NT_STATUS_IS_OK(status
)) {
5247 data_size
= PTR_DIFF(pdata
,(*ppdata
));
5252 #if defined(HAVE_POSIX_ACLS)
5253 case SMB_QUERY_POSIX_ACL
:
5255 SMB_ACL_T file_acl
= NULL
;
5256 SMB_ACL_T def_acl
= NULL
;
5257 uint16_t num_file_acls
= 0;
5258 uint16_t num_def_acls
= 0;
5260 if (fsp
&& fsp
->fh
->fd
!= -1) {
5261 file_acl
= SMB_VFS_SYS_ACL_GET_FD(fsp
,
5265 SMB_VFS_SYS_ACL_GET_FILE(conn
,
5266 smb_fname
->base_name
,
5267 SMB_ACL_TYPE_ACCESS
,
5271 if (file_acl
== NULL
&& no_acl_syscall_error(errno
)) {
5272 DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
5273 "not implemented on "
5274 "filesystem containing %s\n",
5275 smb_fname
->base_name
));
5276 return NT_STATUS_NOT_IMPLEMENTED
;
5279 if (S_ISDIR(psbuf
->st_ex_mode
)) {
5280 if (fsp
&& fsp
->is_directory
) {
5282 SMB_VFS_SYS_ACL_GET_FILE(
5284 fsp
->fsp_name
->base_name
,
5285 SMB_ACL_TYPE_DEFAULT
,
5289 SMB_VFS_SYS_ACL_GET_FILE(
5291 smb_fname
->base_name
,
5292 SMB_ACL_TYPE_DEFAULT
,
5295 def_acl
= free_empty_sys_acl(conn
, def_acl
);
5298 num_file_acls
= count_acl_entries(conn
, file_acl
);
5299 num_def_acls
= count_acl_entries(conn
, def_acl
);
5301 if ( data_size
< (num_file_acls
+ num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
+ SMB_POSIX_ACL_HEADER_SIZE
) {
5302 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
5304 (unsigned int)((num_file_acls
+ num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
+
5305 SMB_POSIX_ACL_HEADER_SIZE
) ));
5307 TALLOC_FREE(file_acl
);
5310 TALLOC_FREE(def_acl
);
5312 return NT_STATUS_BUFFER_TOO_SMALL
;
5315 SSVAL(pdata
,0,SMB_POSIX_ACL_VERSION
);
5316 SSVAL(pdata
,2,num_file_acls
);
5317 SSVAL(pdata
,4,num_def_acls
);
5318 if (!marshall_posix_acl(conn
, pdata
+ SMB_POSIX_ACL_HEADER_SIZE
, psbuf
, file_acl
)) {
5320 TALLOC_FREE(file_acl
);
5323 TALLOC_FREE(def_acl
);
5325 return NT_STATUS_INTERNAL_ERROR
;
5327 if (!marshall_posix_acl(conn
, pdata
+ SMB_POSIX_ACL_HEADER_SIZE
+ (num_file_acls
*SMB_POSIX_ACL_ENTRY_SIZE
), psbuf
, def_acl
)) {
5329 TALLOC_FREE(file_acl
);
5332 TALLOC_FREE(def_acl
);
5334 return NT_STATUS_INTERNAL_ERROR
;
5338 TALLOC_FREE(file_acl
);
5341 TALLOC_FREE(def_acl
);
5343 data_size
= (num_file_acls
+ num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
+ SMB_POSIX_ACL_HEADER_SIZE
;
5349 case SMB_QUERY_POSIX_LOCK
:
5354 enum brl_type lock_type
;
5356 /* We need an open file with a real fd for this. */
5357 if (!fsp
|| fsp
->fh
->fd
== -1) {
5358 return NT_STATUS_INVALID_LEVEL
;
5361 if (lock_data_count
!= POSIX_LOCK_DATA_SIZE
) {
5362 return NT_STATUS_INVALID_PARAMETER
;
5365 switch (SVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
)) {
5366 case POSIX_LOCK_TYPE_READ
:
5367 lock_type
= READ_LOCK
;
5369 case POSIX_LOCK_TYPE_WRITE
:
5370 lock_type
= WRITE_LOCK
;
5372 case POSIX_LOCK_TYPE_UNLOCK
:
5374 /* There's no point in asking for an unlock... */
5375 return NT_STATUS_INVALID_PARAMETER
;
5378 smblctx
= (uint64_t)IVAL(pdata
, POSIX_LOCK_PID_OFFSET
);
5379 offset
= BVAL(pdata
,POSIX_LOCK_START_OFFSET
);
5380 count
= BVAL(pdata
,POSIX_LOCK_LEN_OFFSET
);
5382 status
= query_lock(fsp
,
5389 if (ERROR_WAS_LOCK_DENIED(status
)) {
5390 /* Here we need to report who has it locked... */
5391 data_size
= POSIX_LOCK_DATA_SIZE
;
5393 SSVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
, lock_type
);
5394 SSVAL(pdata
, POSIX_LOCK_FLAGS_OFFSET
, 0);
5395 SIVAL(pdata
, POSIX_LOCK_PID_OFFSET
, (uint32_t)smblctx
);
5396 SBVAL(pdata
, POSIX_LOCK_START_OFFSET
, offset
);
5397 SBVAL(pdata
, POSIX_LOCK_LEN_OFFSET
, count
);
5399 } else if (NT_STATUS_IS_OK(status
)) {
5400 /* For success we just return a copy of what we sent
5401 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
5402 data_size
= POSIX_LOCK_DATA_SIZE
;
5403 memcpy(pdata
, lock_data
, POSIX_LOCK_DATA_SIZE
);
5404 SSVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
, POSIX_LOCK_TYPE_UNLOCK
);
5412 return NT_STATUS_INVALID_LEVEL
;
5415 *pdata_size
= data_size
;
5416 return NT_STATUS_OK
;
5419 /****************************************************************************
5420 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
5421 file name or file id).
5422 ****************************************************************************/
5424 static void call_trans2qfilepathinfo(connection_struct
*conn
,
5425 struct smb_request
*req
,
5426 unsigned int tran_call
,
5427 char **pparams
, int total_params
,
5428 char **ppdata
, int total_data
,
5429 unsigned int max_data_bytes
)
5431 char *params
= *pparams
;
5432 char *pdata
= *ppdata
;
5433 uint16_t info_level
;
5434 unsigned int data_size
= 0;
5435 unsigned int param_size
= 2;
5436 struct smb_filename
*smb_fname
= NULL
;
5437 bool delete_pending
= False
;
5438 struct timespec write_time_ts
;
5439 files_struct
*fsp
= NULL
;
5440 struct file_id fileid
;
5441 struct ea_list
*ea_list
= NULL
;
5442 int lock_data_count
= 0;
5443 char *lock_data
= NULL
;
5444 size_t fixed_portion
;
5445 NTSTATUS status
= NT_STATUS_OK
;
5448 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5452 ZERO_STRUCT(write_time_ts
);
5454 if (tran_call
== TRANSACT2_QFILEINFO
) {
5455 if (total_params
< 4) {
5456 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5461 call_trans2qpipeinfo(conn
, req
, tran_call
,
5462 pparams
, total_params
,
5468 fsp
= file_fsp(req
, SVAL(params
,0));
5469 info_level
= SVAL(params
,2);
5471 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level
));
5473 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
5474 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
5478 /* Initial check for valid fsp ptr. */
5479 if (!check_fsp_open(conn
, req
, fsp
)) {
5483 smb_fname
= cp_smb_filename(talloc_tos(), fsp
->fsp_name
);
5484 if (smb_fname
== NULL
) {
5485 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5489 if(fsp
->fake_file_handle
) {
5491 * This is actually for the QUOTA_FAKE_FILE --metze
5494 /* We know this name is ok, it's already passed the checks. */
5496 } else if(fsp
->fh
->fd
== -1) {
5498 * This is actually a QFILEINFO on a directory
5499 * handle (returned from an NT SMB). NT5.0 seems
5500 * to do this call. JRA.
5503 if (INFO_LEVEL_IS_UNIX(info_level
)) {
5504 /* Always do lstat for UNIX calls. */
5505 if (SMB_VFS_LSTAT(conn
, smb_fname
)) {
5506 DEBUG(3,("call_trans2qfilepathinfo: "
5507 "SMB_VFS_LSTAT of %s failed "
5509 smb_fname_str_dbg(smb_fname
),
5512 map_nt_error_from_unix(errno
));
5515 } else if (SMB_VFS_STAT(conn
, smb_fname
)) {
5516 DEBUG(3,("call_trans2qfilepathinfo: "
5517 "SMB_VFS_STAT of %s failed (%s)\n",
5518 smb_fname_str_dbg(smb_fname
),
5521 map_nt_error_from_unix(errno
));
5525 fileid
= vfs_file_id_from_sbuf(conn
, &smb_fname
->st
);
5526 get_file_infos(fileid
, fsp
->name_hash
, &delete_pending
, &write_time_ts
);
5529 * Original code - this is an open file.
5531 if (SMB_VFS_FSTAT(fsp
, &smb_fname
->st
) != 0) {
5532 DEBUG(3, ("fstat of %s failed (%s)\n",
5533 fsp_fnum_dbg(fsp
), strerror(errno
)));
5535 map_nt_error_from_unix(errno
));
5538 fileid
= vfs_file_id_from_sbuf(conn
, &smb_fname
->st
);
5539 get_file_infos(fileid
, fsp
->name_hash
, &delete_pending
, &write_time_ts
);
5545 uint32_t ucf_flags
= 0;
5548 if (total_params
< 7) {
5549 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5553 info_level
= SVAL(params
,0);
5555 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level
));
5557 if (INFO_LEVEL_IS_UNIX(info_level
)) {
5558 if (!lp_unix_extensions()) {
5559 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
5562 if (info_level
== SMB_QUERY_FILE_UNIX_BASIC
||
5563 info_level
== SMB_QUERY_FILE_UNIX_INFO2
||
5564 info_level
== SMB_QUERY_FILE_UNIX_LINK
) {
5565 ucf_flags
|= UCF_UNIX_NAME_LOOKUP
;
5569 srvstr_get_path(req
, params
, req
->flags2
, &fname
, ¶ms
[6],
5571 STR_TERMINATE
, &status
);
5572 if (!NT_STATUS_IS_OK(status
)) {
5573 reply_nterror(req
, status
);
5577 status
= filename_convert(req
,
5579 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
5584 if (!NT_STATUS_IS_OK(status
)) {
5585 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
5586 reply_botherror(req
,
5587 NT_STATUS_PATH_NOT_COVERED
,
5588 ERRSRV
, ERRbadpath
);
5591 reply_nterror(req
, status
);
5595 /* If this is a stream, check if there is a delete_pending. */
5596 if ((conn
->fs_capabilities
& FILE_NAMED_STREAMS
)
5597 && is_ntfs_stream_smb_fname(smb_fname
)) {
5598 struct smb_filename
*smb_fname_base
;
5600 /* Create an smb_filename with stream_name == NULL. */
5601 smb_fname_base
= synthetic_smb_fname(
5602 talloc_tos(), smb_fname
->base_name
,
5604 if (smb_fname_base
== NULL
) {
5605 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5609 if (INFO_LEVEL_IS_UNIX(info_level
)) {
5610 /* Always do lstat for UNIX calls. */
5611 if (SMB_VFS_LSTAT(conn
, smb_fname_base
) != 0) {
5612 DEBUG(3,("call_trans2qfilepathinfo: "
5613 "SMB_VFS_LSTAT of %s failed "
5615 smb_fname_str_dbg(smb_fname_base
),
5617 TALLOC_FREE(smb_fname_base
);
5619 map_nt_error_from_unix(errno
));
5623 if (SMB_VFS_STAT(conn
, smb_fname_base
) != 0) {
5624 DEBUG(3,("call_trans2qfilepathinfo: "
5625 "fileinfo of %s failed "
5627 smb_fname_str_dbg(smb_fname_base
),
5629 TALLOC_FREE(smb_fname_base
);
5631 map_nt_error_from_unix(errno
));
5636 status
= file_name_hash(conn
,
5637 smb_fname_str_dbg(smb_fname_base
),
5639 if (!NT_STATUS_IS_OK(status
)) {
5640 TALLOC_FREE(smb_fname_base
);
5641 reply_nterror(req
, status
);
5645 fileid
= vfs_file_id_from_sbuf(conn
,
5646 &smb_fname_base
->st
);
5647 TALLOC_FREE(smb_fname_base
);
5648 get_file_infos(fileid
, name_hash
, &delete_pending
, NULL
);
5649 if (delete_pending
) {
5650 reply_nterror(req
, NT_STATUS_DELETE_PENDING
);
5655 if (INFO_LEVEL_IS_UNIX(info_level
)) {
5656 /* Always do lstat for UNIX calls. */
5657 if (SMB_VFS_LSTAT(conn
, smb_fname
)) {
5658 DEBUG(3,("call_trans2qfilepathinfo: "
5659 "SMB_VFS_LSTAT of %s failed (%s)\n",
5660 smb_fname_str_dbg(smb_fname
),
5663 map_nt_error_from_unix(errno
));
5668 if (SMB_VFS_STAT(conn
, smb_fname
) != 0) {
5669 DEBUG(3,("call_trans2qfilepathinfo: "
5670 "SMB_VFS_STAT of %s failed (%s)\n",
5671 smb_fname_str_dbg(smb_fname
),
5674 map_nt_error_from_unix(errno
));
5679 status
= file_name_hash(conn
,
5680 smb_fname_str_dbg(smb_fname
),
5682 if (!NT_STATUS_IS_OK(status
)) {
5683 reply_nterror(req
, status
);
5687 fileid
= vfs_file_id_from_sbuf(conn
, &smb_fname
->st
);
5688 get_file_infos(fileid
, name_hash
, &delete_pending
, &write_time_ts
);
5689 if (delete_pending
) {
5690 reply_nterror(req
, NT_STATUS_DELETE_PENDING
);
5695 DEBUG(3,("call_trans2qfilepathinfo %s (%s) level=%d call=%d "
5696 "total_data=%d\n", smb_fname_str_dbg(smb_fname
),
5698 info_level
,tran_call
,total_data
));
5700 /* Pull out any data sent here before we realloc. */
5701 switch (info_level
) {
5702 case SMB_INFO_QUERY_EAS_FROM_LIST
:
5704 /* Pull any EA list from the data portion. */
5707 if (total_data
< 4) {
5709 req
, NT_STATUS_INVALID_PARAMETER
);
5712 ea_size
= IVAL(pdata
,0);
5714 if (total_data
> 0 && ea_size
!= total_data
) {
5715 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5716 total_data=%u (should be %u)\n", (unsigned int)total_data
, (unsigned int)IVAL(pdata
,0) ));
5718 req
, NT_STATUS_INVALID_PARAMETER
);
5722 if (!lp_ea_support(SNUM(conn
))) {
5723 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
5727 /* Pull out the list of names. */
5728 ea_list
= read_ea_name_list(req
, pdata
+ 4, ea_size
- 4);
5731 req
, NT_STATUS_INVALID_PARAMETER
);
5737 case SMB_QUERY_POSIX_LOCK
:
5739 if (fsp
== NULL
|| fsp
->fh
->fd
== -1) {
5740 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
5744 if (total_data
!= POSIX_LOCK_DATA_SIZE
) {
5746 req
, NT_STATUS_INVALID_PARAMETER
);
5750 /* Copy the lock range data. */
5751 lock_data
= (char *)talloc_memdup(
5752 req
, pdata
, total_data
);
5754 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5757 lock_data_count
= total_data
;
5763 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
5764 if (*pparams
== NULL
) {
5765 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5772 * draft-leach-cifs-v1-spec-02.txt
5773 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
5776 * The requested information is placed in the Data portion of the
5777 * transaction response. For the information levels greater than 0x100,
5778 * the transaction response has 1 parameter word which should be
5779 * ignored by the client.
5781 * However Windows only follows this rule for the IS_NAME_VALID call.
5783 switch (info_level
) {
5784 case SMB_INFO_IS_NAME_VALID
:
5789 if ((info_level
& 0xFF00) == 0xFF00) {
5791 * We use levels that start with 0xFF00
5792 * internally to represent SMB2 specific levels
5794 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
5798 status
= smbd_do_qfilepathinfo(conn
, req
, info_level
,
5800 delete_pending
, write_time_ts
,
5802 lock_data_count
, lock_data
,
5803 req
->flags2
, max_data_bytes
,
5805 ppdata
, &data_size
);
5806 if (!NT_STATUS_IS_OK(status
)) {
5807 reply_nterror(req
, status
);
5810 if (fixed_portion
> max_data_bytes
) {
5811 reply_nterror(req
, NT_STATUS_INFO_LENGTH_MISMATCH
);
5815 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, param_size
, *ppdata
, data_size
,
5821 /****************************************************************************
5822 Set a hard link (called by UNIX extensions and by NT rename with HARD link
5824 ****************************************************************************/
5826 NTSTATUS
hardlink_internals(TALLOC_CTX
*ctx
,
5827 connection_struct
*conn
,
5828 struct smb_request
*req
,
5829 bool overwrite_if_exists
,
5830 const struct smb_filename
*smb_fname_old
,
5831 struct smb_filename
*smb_fname_new
)
5833 NTSTATUS status
= NT_STATUS_OK
;
5835 /* source must already exist. */
5836 if (!VALID_STAT(smb_fname_old
->st
)) {
5837 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5840 if (VALID_STAT(smb_fname_new
->st
)) {
5841 if (overwrite_if_exists
) {
5842 if (S_ISDIR(smb_fname_new
->st
.st_ex_mode
)) {
5843 return NT_STATUS_FILE_IS_A_DIRECTORY
;
5845 status
= unlink_internals(conn
,
5847 FILE_ATTRIBUTE_NORMAL
,
5850 if (!NT_STATUS_IS_OK(status
)) {
5854 /* Disallow if newname already exists. */
5855 return NT_STATUS_OBJECT_NAME_COLLISION
;
5859 /* No links from a directory. */
5860 if (S_ISDIR(smb_fname_old
->st
.st_ex_mode
)) {
5861 return NT_STATUS_FILE_IS_A_DIRECTORY
;
5864 /* Setting a hardlink to/from a stream isn't currently supported. */
5865 if (is_ntfs_stream_smb_fname(smb_fname_old
) ||
5866 is_ntfs_stream_smb_fname(smb_fname_new
)) {
5867 return NT_STATUS_INVALID_PARAMETER
;
5870 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
5871 smb_fname_old
->base_name
, smb_fname_new
->base_name
));
5873 if (SMB_VFS_LINK(conn
, smb_fname_old
->base_name
,
5874 smb_fname_new
->base_name
) != 0) {
5875 status
= map_nt_error_from_unix(errno
);
5876 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
5877 nt_errstr(status
), smb_fname_old
->base_name
,
5878 smb_fname_new
->base_name
));
5883 /****************************************************************************
5884 Deal with setting the time from any of the setfilepathinfo functions.
5885 NOTE !!!! The check for FILE_WRITE_ATTRIBUTES access must be done *before*
5886 calling this function.
5887 ****************************************************************************/
5889 NTSTATUS
smb_set_file_time(connection_struct
*conn
,
5891 const struct smb_filename
*smb_fname
,
5892 struct smb_file_time
*ft
,
5893 bool setting_write_time
)
5895 struct smb_filename smb_fname_base
;
5897 FILE_NOTIFY_CHANGE_LAST_ACCESS
5898 |FILE_NOTIFY_CHANGE_LAST_WRITE
5899 |FILE_NOTIFY_CHANGE_CREATION
;
5901 if (!VALID_STAT(smb_fname
->st
)) {
5902 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5905 /* get some defaults (no modifications) if any info is zero or -1. */
5906 if (null_timespec(ft
->create_time
)) {
5907 action
&= ~FILE_NOTIFY_CHANGE_CREATION
;
5910 if (null_timespec(ft
->atime
)) {
5911 action
&= ~FILE_NOTIFY_CHANGE_LAST_ACCESS
;
5914 if (null_timespec(ft
->mtime
)) {
5915 action
&= ~FILE_NOTIFY_CHANGE_LAST_WRITE
;
5918 if (!setting_write_time
) {
5919 /* ft->mtime comes from change time, not write time. */
5920 action
&= ~FILE_NOTIFY_CHANGE_LAST_WRITE
;
5923 /* Ensure the resolution is the correct for
5924 * what we can store on this filesystem. */
5926 round_timespec(conn
->ts_res
, &ft
->create_time
);
5927 round_timespec(conn
->ts_res
, &ft
->ctime
);
5928 round_timespec(conn
->ts_res
, &ft
->atime
);
5929 round_timespec(conn
->ts_res
, &ft
->mtime
);
5931 DEBUG(5,("smb_set_filetime: actime: %s\n ",
5932 time_to_asc(convert_timespec_to_time_t(ft
->atime
))));
5933 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
5934 time_to_asc(convert_timespec_to_time_t(ft
->mtime
))));
5935 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
5936 time_to_asc(convert_timespec_to_time_t(ft
->ctime
))));
5937 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
5938 time_to_asc(convert_timespec_to_time_t(ft
->create_time
))));
5940 if (setting_write_time
) {
5942 * This was a Windows setfileinfo on an open file.
5943 * NT does this a lot. We also need to
5944 * set the time here, as it can be read by
5945 * FindFirst/FindNext and with the patch for bug #2045
5946 * in smbd/fileio.c it ensures that this timestamp is
5947 * kept sticky even after a write. We save the request
5948 * away and will set it on file close and after a write. JRA.
5951 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
5952 time_to_asc(convert_timespec_to_time_t(ft
->mtime
))));
5955 if (fsp
->base_fsp
) {
5956 set_sticky_write_time_fsp(fsp
->base_fsp
,
5959 set_sticky_write_time_fsp(fsp
, ft
->mtime
);
5962 set_sticky_write_time_path(
5963 vfs_file_id_from_sbuf(conn
, &smb_fname
->st
),
5968 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5970 /* Always call ntimes on the base, even if a stream was passed in. */
5971 smb_fname_base
= *smb_fname
;
5972 smb_fname_base
.stream_name
= NULL
;
5974 if(file_ntimes(conn
, &smb_fname_base
, ft
)!=0) {
5975 return map_nt_error_from_unix(errno
);
5978 notify_fname(conn
, NOTIFY_ACTION_MODIFIED
, action
,
5979 smb_fname
->base_name
);
5980 return NT_STATUS_OK
;
5983 /****************************************************************************
5984 Deal with setting the dosmode from any of the setfilepathinfo functions.
5985 NB. The check for FILE_WRITE_ATTRIBUTES access on this path must have been
5986 done before calling this function.
5987 ****************************************************************************/
5989 static NTSTATUS
smb_set_file_dosmode(connection_struct
*conn
,
5990 const struct smb_filename
*smb_fname
,
5993 struct smb_filename
*smb_fname_base
;
5996 if (!VALID_STAT(smb_fname
->st
)) {
5997 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
6000 /* Always operate on the base_name, even if a stream was passed in. */
6001 smb_fname_base
= synthetic_smb_fname(
6002 talloc_tos(), smb_fname
->base_name
, NULL
, &smb_fname
->st
);
6003 if (smb_fname_base
== NULL
) {
6004 return NT_STATUS_NO_MEMORY
;
6008 if (S_ISDIR(smb_fname_base
->st
.st_ex_mode
)) {
6009 dosmode
|= FILE_ATTRIBUTE_DIRECTORY
;
6011 dosmode
&= ~FILE_ATTRIBUTE_DIRECTORY
;
6015 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode
));
6017 /* check the mode isn't different, before changing it */
6018 if ((dosmode
!= 0) && (dosmode
!= dos_mode(conn
, smb_fname_base
))) {
6019 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
6020 "0x%x\n", smb_fname_str_dbg(smb_fname_base
),
6021 (unsigned int)dosmode
));
6023 if(file_set_dosmode(conn
, smb_fname_base
, dosmode
, NULL
,
6025 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
6027 smb_fname_str_dbg(smb_fname_base
),
6029 status
= map_nt_error_from_unix(errno
);
6033 status
= NT_STATUS_OK
;
6035 TALLOC_FREE(smb_fname_base
);
6039 /****************************************************************************
6040 Deal with setting the size from any of the setfilepathinfo functions.
6041 ****************************************************************************/
6043 static NTSTATUS
smb_set_file_size(connection_struct
*conn
,
6044 struct smb_request
*req
,
6046 const struct smb_filename
*smb_fname
,
6047 const SMB_STRUCT_STAT
*psbuf
,
6049 bool fail_after_createfile
)
6051 NTSTATUS status
= NT_STATUS_OK
;
6052 struct smb_filename
*smb_fname_tmp
= NULL
;
6053 files_struct
*new_fsp
= NULL
;
6055 if (!VALID_STAT(*psbuf
)) {
6056 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
6059 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size
));
6061 if (size
== get_file_size_stat(psbuf
)) {
6062 return NT_STATUS_OK
;
6065 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
6066 smb_fname_str_dbg(smb_fname
), (double)size
));
6068 if (fsp
&& fsp
->fh
->fd
!= -1) {
6069 /* Handle based call. */
6070 if (!(fsp
->access_mask
& FILE_WRITE_DATA
)) {
6071 return NT_STATUS_ACCESS_DENIED
;
6074 if (vfs_set_filelen(fsp
, size
) == -1) {
6075 return map_nt_error_from_unix(errno
);
6077 trigger_write_time_update_immediate(fsp
);
6078 return NT_STATUS_OK
;
6081 smb_fname_tmp
= cp_smb_filename(talloc_tos(), smb_fname
);
6082 if (smb_fname_tmp
== NULL
) {
6083 return NT_STATUS_NO_MEMORY
;
6086 smb_fname_tmp
->st
= *psbuf
;
6088 status
= SMB_VFS_CREATE_FILE(
6091 0, /* root_dir_fid */
6092 smb_fname_tmp
, /* fname */
6093 FILE_WRITE_DATA
, /* access_mask */
6094 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
6096 FILE_OPEN
, /* create_disposition*/
6097 0, /* create_options */
6098 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
6099 0, /* oplock_request */
6101 0, /* allocation_size */
6102 0, /* private_flags */
6105 &new_fsp
, /* result */
6107 NULL
, NULL
); /* create context */
6109 TALLOC_FREE(smb_fname_tmp
);
6111 if (!NT_STATUS_IS_OK(status
)) {
6112 /* NB. We check for open_was_deferred in the caller. */
6116 /* See RAW-SFILEINFO-END-OF-FILE */
6117 if (fail_after_createfile
) {
6118 close_file(req
, new_fsp
,NORMAL_CLOSE
);
6119 return NT_STATUS_INVALID_LEVEL
;
6122 if (vfs_set_filelen(new_fsp
, size
) == -1) {
6123 status
= map_nt_error_from_unix(errno
);
6124 close_file(req
, new_fsp
,NORMAL_CLOSE
);
6128 trigger_write_time_update_immediate(new_fsp
);
6129 close_file(req
, new_fsp
,NORMAL_CLOSE
);
6130 return NT_STATUS_OK
;
6133 /****************************************************************************
6134 Deal with SMB_INFO_SET_EA.
6135 ****************************************************************************/
6137 static NTSTATUS
smb_info_set_ea(connection_struct
*conn
,
6141 const struct smb_filename
*smb_fname
)
6143 struct ea_list
*ea_list
= NULL
;
6144 TALLOC_CTX
*ctx
= NULL
;
6145 NTSTATUS status
= NT_STATUS_OK
;
6147 if (total_data
< 10) {
6149 /* OS/2 workplace shell seems to send SET_EA requests of "null"
6150 length. They seem to have no effect. Bug #3212. JRA */
6152 if ((total_data
== 4) && (IVAL(pdata
,0) == 4)) {
6153 /* We're done. We only get EA info in this call. */
6154 return NT_STATUS_OK
;
6157 return NT_STATUS_INVALID_PARAMETER
;
6160 if (IVAL(pdata
,0) > total_data
) {
6161 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
6162 IVAL(pdata
,0), (unsigned int)total_data
));
6163 return NT_STATUS_INVALID_PARAMETER
;
6167 ea_list
= read_ea_list(ctx
, pdata
+ 4, total_data
- 4);
6169 return NT_STATUS_INVALID_PARAMETER
;
6172 status
= set_ea(conn
, fsp
, smb_fname
, ea_list
);
6177 /****************************************************************************
6178 Deal with SMB_FILE_FULL_EA_INFORMATION set.
6179 ****************************************************************************/
6181 static NTSTATUS
smb_set_file_full_ea_info(connection_struct
*conn
,
6186 struct ea_list
*ea_list
= NULL
;
6190 return NT_STATUS_INVALID_HANDLE
;
6193 if (!lp_ea_support(SNUM(conn
))) {
6194 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
6195 "EA's not supported.\n",
6196 (unsigned int)total_data
));
6197 return NT_STATUS_EAS_NOT_SUPPORTED
;
6200 if (total_data
< 10) {
6201 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
6203 (unsigned int)total_data
));
6204 return NT_STATUS_INVALID_PARAMETER
;
6207 ea_list
= read_nttrans_ea_list(talloc_tos(),
6212 return NT_STATUS_INVALID_PARAMETER
;
6215 status
= set_ea(conn
, fsp
, fsp
->fsp_name
, ea_list
);
6217 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
6218 smb_fname_str_dbg(fsp
->fsp_name
),
6219 nt_errstr(status
) ));
6225 /****************************************************************************
6226 Deal with SMB_SET_FILE_DISPOSITION_INFO.
6227 ****************************************************************************/
6229 static NTSTATUS
smb_set_file_disposition_info(connection_struct
*conn
,
6233 struct smb_filename
*smb_fname
)
6235 NTSTATUS status
= NT_STATUS_OK
;
6236 bool delete_on_close
;
6237 uint32_t dosmode
= 0;
6239 if (total_data
< 1) {
6240 return NT_STATUS_INVALID_PARAMETER
;
6244 return NT_STATUS_INVALID_HANDLE
;
6247 delete_on_close
= (CVAL(pdata
,0) ? True
: False
);
6248 dosmode
= dos_mode(conn
, smb_fname
);
6250 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
6251 "delete_on_close = %u\n",
6252 smb_fname_str_dbg(smb_fname
),
6253 (unsigned int)dosmode
,
6254 (unsigned int)delete_on_close
));
6256 if (delete_on_close
) {
6257 status
= can_set_delete_on_close(fsp
, dosmode
);
6258 if (!NT_STATUS_IS_OK(status
)) {
6263 /* The set is across all open files on this dev/inode pair. */
6264 if (!set_delete_on_close(fsp
, delete_on_close
,
6265 conn
->session_info
->security_token
,
6266 conn
->session_info
->unix_token
)) {
6267 return NT_STATUS_ACCESS_DENIED
;
6269 return NT_STATUS_OK
;
6272 /****************************************************************************
6273 Deal with SMB_FILE_POSITION_INFORMATION.
6274 ****************************************************************************/
6276 static NTSTATUS
smb_file_position_information(connection_struct
*conn
,
6281 uint64_t position_information
;
6283 if (total_data
< 8) {
6284 return NT_STATUS_INVALID_PARAMETER
;
6288 /* Ignore on pathname based set. */
6289 return NT_STATUS_OK
;
6292 position_information
= (uint64_t)IVAL(pdata
,0);
6293 position_information
|= (((uint64_t)IVAL(pdata
,4)) << 32);
6295 DEBUG(10,("smb_file_position_information: Set file position "
6296 "information for file %s to %.0f\n", fsp_str_dbg(fsp
),
6297 (double)position_information
));
6298 fsp
->fh
->position_information
= position_information
;
6299 return NT_STATUS_OK
;
6302 /****************************************************************************
6303 Deal with SMB_FILE_MODE_INFORMATION.
6304 ****************************************************************************/
6306 static NTSTATUS
smb_file_mode_information(connection_struct
*conn
,
6312 if (total_data
< 4) {
6313 return NT_STATUS_INVALID_PARAMETER
;
6315 mode
= IVAL(pdata
,0);
6316 if (mode
!= 0 && mode
!= 2 && mode
!= 4 && mode
!= 6) {
6317 return NT_STATUS_INVALID_PARAMETER
;
6319 return NT_STATUS_OK
;
6322 /****************************************************************************
6323 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
6324 ****************************************************************************/
6326 static NTSTATUS
smb_set_file_unix_link(connection_struct
*conn
,
6327 struct smb_request
*req
,
6330 const struct smb_filename
*smb_fname
)
6332 char *link_target
= NULL
;
6333 const char *newname
= smb_fname
->base_name
;
6334 TALLOC_CTX
*ctx
= talloc_tos();
6336 /* Set a symbolic link. */
6337 /* Don't allow this if follow links is false. */
6339 if (total_data
== 0) {
6340 return NT_STATUS_INVALID_PARAMETER
;
6343 if (!lp_follow_symlinks(SNUM(conn
))) {
6344 return NT_STATUS_ACCESS_DENIED
;
6347 srvstr_pull_talloc(ctx
, pdata
, req
->flags2
, &link_target
, pdata
,
6348 total_data
, STR_TERMINATE
);
6351 return NT_STATUS_INVALID_PARAMETER
;
6354 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
6355 newname
, link_target
));
6357 if (SMB_VFS_SYMLINK(conn
,link_target
,newname
) != 0) {
6358 return map_nt_error_from_unix(errno
);
6361 return NT_STATUS_OK
;
6364 /****************************************************************************
6365 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
6366 ****************************************************************************/
6368 static NTSTATUS
smb_set_file_unix_hlink(connection_struct
*conn
,
6369 struct smb_request
*req
,
6370 const char *pdata
, int total_data
,
6371 struct smb_filename
*smb_fname_new
)
6373 char *oldname
= NULL
;
6374 struct smb_filename
*smb_fname_old
= NULL
;
6375 TALLOC_CTX
*ctx
= talloc_tos();
6376 NTSTATUS status
= NT_STATUS_OK
;
6378 /* Set a hard link. */
6379 if (total_data
== 0) {
6380 return NT_STATUS_INVALID_PARAMETER
;
6383 srvstr_get_path(ctx
, pdata
, req
->flags2
, &oldname
, pdata
,
6384 total_data
, STR_TERMINATE
, &status
);
6385 if (!NT_STATUS_IS_OK(status
)) {
6389 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
6390 smb_fname_str_dbg(smb_fname_new
), oldname
));
6392 status
= filename_convert(ctx
,
6394 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6399 if (!NT_STATUS_IS_OK(status
)) {
6403 return hardlink_internals(ctx
, conn
, req
, false,
6404 smb_fname_old
, smb_fname_new
);
6407 /****************************************************************************
6408 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
6409 ****************************************************************************/
6411 static NTSTATUS
smb2_file_rename_information(connection_struct
*conn
,
6412 struct smb_request
*req
,
6416 struct smb_filename
*smb_fname_src
)
6420 char *newname
= NULL
;
6421 struct smb_filename
*smb_fname_dst
= NULL
;
6422 NTSTATUS status
= NT_STATUS_OK
;
6423 TALLOC_CTX
*ctx
= talloc_tos();
6426 return NT_STATUS_INVALID_HANDLE
;
6429 if (total_data
< 20) {
6430 return NT_STATUS_INVALID_PARAMETER
;
6433 overwrite
= (CVAL(pdata
,0) ? True
: False
);
6434 len
= IVAL(pdata
,16);
6436 if (len
> (total_data
- 20) || (len
== 0)) {
6437 return NT_STATUS_INVALID_PARAMETER
;
6440 srvstr_get_path(ctx
, pdata
, req
->flags2
, &newname
,
6441 &pdata
[20], len
, STR_TERMINATE
,
6443 if (!NT_STATUS_IS_OK(status
)) {
6447 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
6450 status
= filename_convert(ctx
,
6452 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6457 if (!NT_STATUS_IS_OK(status
)) {
6461 if (fsp
->base_fsp
) {
6462 /* newname must be a stream name. */
6463 if (newname
[0] != ':') {
6464 return NT_STATUS_NOT_SUPPORTED
;
6467 /* Create an smb_fname to call rename_internals_fsp() with. */
6468 smb_fname_dst
= synthetic_smb_fname(
6469 talloc_tos(), fsp
->base_fsp
->fsp_name
->base_name
,
6471 if (smb_fname_dst
== NULL
) {
6472 status
= NT_STATUS_NO_MEMORY
;
6477 * Set the original last component, since
6478 * rename_internals_fsp() requires it.
6480 smb_fname_dst
->original_lcomp
= talloc_strdup(smb_fname_dst
,
6482 if (smb_fname_dst
->original_lcomp
== NULL
) {
6483 status
= NT_STATUS_NO_MEMORY
;
6489 DEBUG(10,("smb2_file_rename_information: "
6490 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
6491 fsp_fnum_dbg(fsp
), fsp_str_dbg(fsp
),
6492 smb_fname_str_dbg(smb_fname_dst
)));
6493 status
= rename_internals_fsp(conn
, fsp
, smb_fname_dst
,
6494 (FILE_ATTRIBUTE_HIDDEN
|FILE_ATTRIBUTE_SYSTEM
),
6498 TALLOC_FREE(smb_fname_dst
);
6502 static NTSTATUS
smb_file_link_information(connection_struct
*conn
,
6503 struct smb_request
*req
,
6507 struct smb_filename
*smb_fname_src
)
6511 char *newname
= NULL
;
6512 struct smb_filename
*smb_fname_dst
= NULL
;
6513 NTSTATUS status
= NT_STATUS_OK
;
6514 TALLOC_CTX
*ctx
= talloc_tos();
6517 return NT_STATUS_INVALID_HANDLE
;
6520 if (total_data
< 20) {
6521 return NT_STATUS_INVALID_PARAMETER
;
6524 overwrite
= (CVAL(pdata
,0) ? true : false);
6525 len
= IVAL(pdata
,16);
6527 if (len
> (total_data
- 20) || (len
== 0)) {
6528 return NT_STATUS_INVALID_PARAMETER
;
6531 srvstr_get_path(ctx
, pdata
, req
->flags2
, &newname
,
6532 &pdata
[20], len
, STR_TERMINATE
,
6534 if (!NT_STATUS_IS_OK(status
)) {
6538 DEBUG(10,("smb_file_link_information: got name |%s|\n",
6541 status
= filename_convert(ctx
,
6543 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6548 if (!NT_STATUS_IS_OK(status
)) {
6552 if (fsp
->base_fsp
) {
6553 /* No stream names. */
6554 return NT_STATUS_NOT_SUPPORTED
;
6557 DEBUG(10,("smb_file_link_information: "
6558 "SMB_FILE_LINK_INFORMATION (%s) %s -> %s\n",
6559 fsp_fnum_dbg(fsp
), fsp_str_dbg(fsp
),
6560 smb_fname_str_dbg(smb_fname_dst
)));
6561 status
= hardlink_internals(ctx
,
6568 TALLOC_FREE(smb_fname_dst
);
6572 /****************************************************************************
6573 Deal with SMB_FILE_RENAME_INFORMATION.
6574 ****************************************************************************/
6576 static NTSTATUS
smb_file_rename_information(connection_struct
*conn
,
6577 struct smb_request
*req
,
6581 struct smb_filename
*smb_fname_src
)
6586 char *newname
= NULL
;
6587 struct smb_filename
*smb_fname_dst
= NULL
;
6588 bool dest_has_wcard
= False
;
6589 NTSTATUS status
= NT_STATUS_OK
;
6591 TALLOC_CTX
*ctx
= talloc_tos();
6593 if (total_data
< 13) {
6594 return NT_STATUS_INVALID_PARAMETER
;
6597 overwrite
= (CVAL(pdata
,0) ? True
: False
);
6598 root_fid
= IVAL(pdata
,4);
6599 len
= IVAL(pdata
,8);
6601 if (len
> (total_data
- 12) || (len
== 0) || (root_fid
!= 0)) {
6602 return NT_STATUS_INVALID_PARAMETER
;
6605 srvstr_get_path_wcard(ctx
, pdata
, req
->flags2
, &newname
, &pdata
[12],
6608 if (!NT_STATUS_IS_OK(status
)) {
6612 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
6615 status
= resolve_dfspath_wcard(ctx
, conn
,
6616 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6619 !conn
->sconn
->using_smb2
,
6622 if (!NT_STATUS_IS_OK(status
)) {
6626 /* Check the new name has no '/' characters. */
6627 if (strchr_m(newname
, '/')) {
6628 return NT_STATUS_NOT_SUPPORTED
;
6631 if (fsp
&& fsp
->base_fsp
) {
6632 /* newname must be a stream name. */
6633 if (newname
[0] != ':') {
6634 return NT_STATUS_NOT_SUPPORTED
;
6637 /* Create an smb_fname to call rename_internals_fsp() with. */
6638 smb_fname_dst
= synthetic_smb_fname(
6639 talloc_tos(), fsp
->base_fsp
->fsp_name
->base_name
,
6641 if (smb_fname_dst
== NULL
) {
6642 status
= NT_STATUS_NO_MEMORY
;
6647 * Set the original last component, since
6648 * rename_internals_fsp() requires it.
6650 smb_fname_dst
->original_lcomp
= talloc_strdup(smb_fname_dst
,
6652 if (smb_fname_dst
->original_lcomp
== NULL
) {
6653 status
= NT_STATUS_NO_MEMORY
;
6659 * Build up an smb_fname_dst based on the filename passed in.
6660 * We basically just strip off the last component, and put on
6661 * the newname instead.
6663 char *base_name
= NULL
;
6665 /* newname must *not* be a stream name. */
6666 if (newname
[0] == ':') {
6667 return NT_STATUS_NOT_SUPPORTED
;
6671 * Strip off the last component (filename) of the path passed
6674 base_name
= talloc_strdup(ctx
, smb_fname_src
->base_name
);
6676 return NT_STATUS_NO_MEMORY
;
6678 p
= strrchr_m(base_name
, '/');
6682 base_name
= talloc_strdup(ctx
, "");
6684 return NT_STATUS_NO_MEMORY
;
6687 /* Append the new name. */
6688 base_name
= talloc_asprintf_append(base_name
,
6692 return NT_STATUS_NO_MEMORY
;
6695 status
= unix_convert(ctx
, conn
, base_name
, &smb_fname_dst
,
6698 UCF_ALWAYS_ALLOW_WCARD_LCOMP
:
6701 /* If an error we expect this to be
6702 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
6704 if (!NT_STATUS_IS_OK(status
)) {
6705 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND
,
6709 /* Create an smb_fname to call rename_internals_fsp() */
6710 smb_fname_dst
= synthetic_smb_fname(
6711 ctx
, base_name
, NULL
, NULL
);
6712 if (smb_fname_dst
== NULL
) {
6713 status
= NT_STATUS_NO_MEMORY
;
6720 DEBUG(10,("smb_file_rename_information: "
6721 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
6722 fsp_fnum_dbg(fsp
), fsp_str_dbg(fsp
),
6723 smb_fname_str_dbg(smb_fname_dst
)));
6724 status
= rename_internals_fsp(conn
, fsp
, smb_fname_dst
, 0,
6727 DEBUG(10,("smb_file_rename_information: "
6728 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
6729 smb_fname_str_dbg(smb_fname_src
),
6730 smb_fname_str_dbg(smb_fname_dst
)));
6731 status
= rename_internals(ctx
, conn
, req
, smb_fname_src
,
6732 smb_fname_dst
, 0, overwrite
, false,
6734 FILE_WRITE_ATTRIBUTES
);
6737 TALLOC_FREE(smb_fname_dst
);
6741 /****************************************************************************
6742 Deal with SMB_SET_POSIX_ACL.
6743 ****************************************************************************/
6745 #if defined(HAVE_POSIX_ACLS)
6746 static NTSTATUS
smb_set_posix_acl(connection_struct
*conn
,
6750 const struct smb_filename
*smb_fname
)
6752 uint16_t posix_acl_version
;
6753 uint16_t num_file_acls
;
6754 uint16_t num_def_acls
;
6755 bool valid_file_acls
= True
;
6756 bool valid_def_acls
= True
;
6758 if (total_data
< SMB_POSIX_ACL_HEADER_SIZE
) {
6759 return NT_STATUS_INVALID_PARAMETER
;
6761 posix_acl_version
= SVAL(pdata
,0);
6762 num_file_acls
= SVAL(pdata
,2);
6763 num_def_acls
= SVAL(pdata
,4);
6765 if (num_file_acls
== SMB_POSIX_IGNORE_ACE_ENTRIES
) {
6766 valid_file_acls
= False
;
6770 if (num_def_acls
== SMB_POSIX_IGNORE_ACE_ENTRIES
) {
6771 valid_def_acls
= False
;
6775 if (posix_acl_version
!= SMB_POSIX_ACL_VERSION
) {
6776 return NT_STATUS_INVALID_PARAMETER
;
6779 if (total_data
< SMB_POSIX_ACL_HEADER_SIZE
+
6780 (num_file_acls
+num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
) {
6781 return NT_STATUS_INVALID_PARAMETER
;
6784 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
6785 smb_fname
? smb_fname_str_dbg(smb_fname
) : fsp_str_dbg(fsp
),
6786 (unsigned int)num_file_acls
,
6787 (unsigned int)num_def_acls
));
6789 if (valid_file_acls
&& !set_unix_posix_acl(conn
, fsp
,
6790 smb_fname
->base_name
, num_file_acls
,
6791 pdata
+ SMB_POSIX_ACL_HEADER_SIZE
)) {
6792 return map_nt_error_from_unix(errno
);
6795 if (valid_def_acls
&& !set_unix_posix_default_acl(conn
,
6796 smb_fname
->base_name
, &smb_fname
->st
, num_def_acls
,
6797 pdata
+ SMB_POSIX_ACL_HEADER_SIZE
+
6798 (num_file_acls
*SMB_POSIX_ACL_ENTRY_SIZE
))) {
6799 return map_nt_error_from_unix(errno
);
6801 return NT_STATUS_OK
;
6805 /****************************************************************************
6806 Deal with SMB_SET_POSIX_LOCK.
6807 ****************************************************************************/
6809 static NTSTATUS
smb_set_posix_lock(connection_struct
*conn
,
6810 struct smb_request
*req
,
6818 bool blocking_lock
= False
;
6819 enum brl_type lock_type
;
6821 NTSTATUS status
= NT_STATUS_OK
;
6823 if (fsp
== NULL
|| fsp
->fh
->fd
== -1) {
6824 return NT_STATUS_INVALID_HANDLE
;
6827 if (total_data
!= POSIX_LOCK_DATA_SIZE
) {
6828 return NT_STATUS_INVALID_PARAMETER
;
6831 switch (SVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
)) {
6832 case POSIX_LOCK_TYPE_READ
:
6833 lock_type
= READ_LOCK
;
6835 case POSIX_LOCK_TYPE_WRITE
:
6836 /* Return the right POSIX-mappable error code for files opened read-only. */
6837 if (!fsp
->can_write
) {
6838 return NT_STATUS_INVALID_HANDLE
;
6840 lock_type
= WRITE_LOCK
;
6842 case POSIX_LOCK_TYPE_UNLOCK
:
6843 lock_type
= UNLOCK_LOCK
;
6846 return NT_STATUS_INVALID_PARAMETER
;
6849 if (SVAL(pdata
,POSIX_LOCK_FLAGS_OFFSET
) == POSIX_LOCK_FLAG_NOWAIT
) {
6850 blocking_lock
= False
;
6851 } else if (SVAL(pdata
,POSIX_LOCK_FLAGS_OFFSET
) == POSIX_LOCK_FLAG_WAIT
) {
6852 blocking_lock
= True
;
6854 return NT_STATUS_INVALID_PARAMETER
;
6857 if (!lp_blocking_locks(SNUM(conn
))) {
6858 blocking_lock
= False
;
6861 smblctx
= (uint64_t)IVAL(pdata
, POSIX_LOCK_PID_OFFSET
);
6862 offset
= (((uint64_t) IVAL(pdata
,(POSIX_LOCK_START_OFFSET
+4))) << 32) |
6863 ((uint64_t) IVAL(pdata
,POSIX_LOCK_START_OFFSET
));
6864 count
= (((uint64_t) IVAL(pdata
,(POSIX_LOCK_LEN_OFFSET
+4))) << 32) |
6865 ((uint64_t) IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
));
6867 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
6868 "smblctx = %llu, count = %.0f, offset = %.0f\n",
6870 (unsigned int)lock_type
,
6871 (unsigned long long)smblctx
,
6875 if (lock_type
== UNLOCK_LOCK
) {
6876 status
= do_unlock(req
->sconn
->msg_ctx
,
6883 uint64_t block_smblctx
;
6885 struct byte_range_lock
*br_lck
= do_lock(req
->sconn
->msg_ctx
,
6896 if (br_lck
&& blocking_lock
&& ERROR_WAS_LOCK_DENIED(status
)) {
6898 * A blocking lock was requested. Package up
6899 * this smb into a queued request and push it
6900 * onto the blocking lock queue.
6902 if(push_blocking_lock_request(br_lck
,
6905 -1, /* infinite timeout. */
6913 TALLOC_FREE(br_lck
);
6917 TALLOC_FREE(br_lck
);
6923 /****************************************************************************
6924 Deal with SMB_SET_FILE_BASIC_INFO.
6925 ****************************************************************************/
6927 static NTSTATUS
smb_set_file_basic_info(connection_struct
*conn
,
6931 const struct smb_filename
*smb_fname
)
6933 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
6934 struct smb_file_time ft
;
6935 uint32_t dosmode
= 0;
6936 NTSTATUS status
= NT_STATUS_OK
;
6940 if (total_data
< 36) {
6941 return NT_STATUS_INVALID_PARAMETER
;
6944 status
= check_access(conn
, fsp
, smb_fname
, FILE_WRITE_ATTRIBUTES
);
6945 if (!NT_STATUS_IS_OK(status
)) {
6949 /* Set the attributes */
6950 dosmode
= IVAL(pdata
,32);
6951 status
= smb_set_file_dosmode(conn
, smb_fname
, dosmode
);
6952 if (!NT_STATUS_IS_OK(status
)) {
6957 ft
.create_time
= interpret_long_date(pdata
);
6960 ft
.atime
= interpret_long_date(pdata
+8);
6963 ft
.mtime
= interpret_long_date(pdata
+16);
6966 ft
.ctime
= interpret_long_date(pdata
+24);
6968 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
6969 smb_fname_str_dbg(smb_fname
)));
6971 return smb_set_file_time(conn
, fsp
, smb_fname
, &ft
,
6975 /****************************************************************************
6976 Deal with SMB_INFO_STANDARD.
6977 ****************************************************************************/
6979 static NTSTATUS
smb_set_info_standard(connection_struct
*conn
,
6983 const struct smb_filename
*smb_fname
)
6986 struct smb_file_time ft
;
6990 if (total_data
< 12) {
6991 return NT_STATUS_INVALID_PARAMETER
;
6995 ft
.create_time
= convert_time_t_to_timespec(srv_make_unix_date2(pdata
));
6997 ft
.atime
= convert_time_t_to_timespec(srv_make_unix_date2(pdata
+4));
6999 ft
.mtime
= convert_time_t_to_timespec(srv_make_unix_date2(pdata
+8));
7001 DEBUG(10,("smb_set_info_standard: file %s\n",
7002 smb_fname_str_dbg(smb_fname
)));
7004 status
= check_access(conn
, fsp
, smb_fname
, FILE_WRITE_ATTRIBUTES
);
7005 if (!NT_STATUS_IS_OK(status
)) {
7009 return smb_set_file_time(conn
,
7016 /****************************************************************************
7017 Deal with SMB_SET_FILE_ALLOCATION_INFO.
7018 ****************************************************************************/
7020 static NTSTATUS
smb_set_file_allocation_info(connection_struct
*conn
,
7021 struct smb_request
*req
,
7025 struct smb_filename
*smb_fname
)
7027 uint64_t allocation_size
= 0;
7028 NTSTATUS status
= NT_STATUS_OK
;
7029 files_struct
*new_fsp
= NULL
;
7031 if (!VALID_STAT(smb_fname
->st
)) {
7032 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
7035 if (total_data
< 8) {
7036 return NT_STATUS_INVALID_PARAMETER
;
7039 allocation_size
= (uint64_t)IVAL(pdata
,0);
7040 allocation_size
|= (((uint64_t)IVAL(pdata
,4)) << 32);
7041 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
7042 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname
),
7043 (double)allocation_size
));
7045 if (allocation_size
) {
7046 allocation_size
= smb_roundup(conn
, allocation_size
);
7049 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
7050 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname
),
7051 (double)allocation_size
));
7053 if (fsp
&& fsp
->fh
->fd
!= -1) {
7054 /* Open file handle. */
7055 if (!(fsp
->access_mask
& FILE_WRITE_DATA
)) {
7056 return NT_STATUS_ACCESS_DENIED
;
7059 /* Only change if needed. */
7060 if (allocation_size
!= get_file_size_stat(&smb_fname
->st
)) {
7061 if (vfs_allocate_file_space(fsp
, allocation_size
) == -1) {
7062 return map_nt_error_from_unix(errno
);
7065 /* But always update the time. */
7067 * This is equivalent to a write. Ensure it's seen immediately
7068 * if there are no pending writes.
7070 trigger_write_time_update_immediate(fsp
);
7071 return NT_STATUS_OK
;
7074 /* Pathname or stat or directory file. */
7075 status
= SMB_VFS_CREATE_FILE(
7078 0, /* root_dir_fid */
7079 smb_fname
, /* fname */
7080 FILE_WRITE_DATA
, /* access_mask */
7081 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
7083 FILE_OPEN
, /* create_disposition*/
7084 0, /* create_options */
7085 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
7086 0, /* oplock_request */
7088 0, /* allocation_size */
7089 0, /* private_flags */
7092 &new_fsp
, /* result */
7094 NULL
, NULL
); /* create context */
7096 if (!NT_STATUS_IS_OK(status
)) {
7097 /* NB. We check for open_was_deferred in the caller. */
7101 /* Only change if needed. */
7102 if (allocation_size
!= get_file_size_stat(&smb_fname
->st
)) {
7103 if (vfs_allocate_file_space(new_fsp
, allocation_size
) == -1) {
7104 status
= map_nt_error_from_unix(errno
);
7105 close_file(req
, new_fsp
, NORMAL_CLOSE
);
7110 /* Changing the allocation size should set the last mod time. */
7112 * This is equivalent to a write. Ensure it's seen immediately
7113 * if there are no pending writes.
7115 trigger_write_time_update_immediate(new_fsp
);
7116 close_file(req
, new_fsp
, NORMAL_CLOSE
);
7117 return NT_STATUS_OK
;
7120 /****************************************************************************
7121 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
7122 ****************************************************************************/
7124 static NTSTATUS
smb_set_file_end_of_file_info(connection_struct
*conn
,
7125 struct smb_request
*req
,
7129 const struct smb_filename
*smb_fname
,
7130 bool fail_after_createfile
)
7134 if (total_data
< 8) {
7135 return NT_STATUS_INVALID_PARAMETER
;
7138 size
= IVAL(pdata
,0);
7139 size
|= (((off_t
)IVAL(pdata
,4)) << 32);
7140 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
7141 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname
),
7144 return smb_set_file_size(conn
, req
,
7149 fail_after_createfile
);
7152 /****************************************************************************
7153 Allow a UNIX info mknod.
7154 ****************************************************************************/
7156 static NTSTATUS
smb_unix_mknod(connection_struct
*conn
,
7159 const struct smb_filename
*smb_fname
)
7161 uint32_t file_type
= IVAL(pdata
,56);
7162 #if defined(HAVE_MAKEDEV)
7163 uint32_t dev_major
= IVAL(pdata
,60);
7164 uint32_t dev_minor
= IVAL(pdata
,68);
7166 SMB_DEV_T dev
= (SMB_DEV_T
)0;
7167 uint32_t raw_unixmode
= IVAL(pdata
,84);
7171 if (total_data
< 100) {
7172 return NT_STATUS_INVALID_PARAMETER
;
7175 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
7176 PERM_NEW_FILE
, &unixmode
);
7177 if (!NT_STATUS_IS_OK(status
)) {
7181 #if defined(HAVE_MAKEDEV)
7182 dev
= makedev(dev_major
, dev_minor
);
7185 switch (file_type
) {
7186 #if defined(S_IFIFO)
7187 case UNIX_TYPE_FIFO
:
7188 unixmode
|= S_IFIFO
;
7191 #if defined(S_IFSOCK)
7192 case UNIX_TYPE_SOCKET
:
7193 unixmode
|= S_IFSOCK
;
7196 #if defined(S_IFCHR)
7197 case UNIX_TYPE_CHARDEV
:
7198 unixmode
|= S_IFCHR
;
7201 #if defined(S_IFBLK)
7202 case UNIX_TYPE_BLKDEV
:
7203 unixmode
|= S_IFBLK
;
7207 return NT_STATUS_INVALID_PARAMETER
;
7210 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
7211 "%.0f mode 0%o for file %s\n", (double)dev
,
7212 (unsigned int)unixmode
, smb_fname_str_dbg(smb_fname
)));
7214 /* Ok - do the mknod. */
7215 if (SMB_VFS_MKNOD(conn
, smb_fname
->base_name
, unixmode
, dev
) != 0) {
7216 return map_nt_error_from_unix(errno
);
7219 /* If any of the other "set" calls fail we
7220 * don't want to end up with a half-constructed mknod.
7223 if (lp_inherit_permissions(SNUM(conn
))) {
7225 if (!parent_dirname(talloc_tos(), smb_fname
->base_name
,
7227 return NT_STATUS_NO_MEMORY
;
7229 inherit_access_posix_acl(conn
, parent
, smb_fname
->base_name
,
7231 TALLOC_FREE(parent
);
7234 return NT_STATUS_OK
;
7237 /****************************************************************************
7238 Deal with SMB_SET_FILE_UNIX_BASIC.
7239 ****************************************************************************/
7241 static NTSTATUS
smb_set_file_unix_basic(connection_struct
*conn
,
7242 struct smb_request
*req
,
7246 const struct smb_filename
*smb_fname
)
7248 struct smb_file_time ft
;
7249 uint32_t raw_unixmode
;
7252 uid_t set_owner
= (uid_t
)SMB_UID_NO_CHANGE
;
7253 gid_t set_grp
= (uid_t
)SMB_GID_NO_CHANGE
;
7254 NTSTATUS status
= NT_STATUS_OK
;
7255 bool delete_on_fail
= False
;
7256 enum perm_type ptype
;
7257 files_struct
*all_fsps
= NULL
;
7258 bool modify_mtime
= true;
7260 struct smb_filename
*smb_fname_tmp
= NULL
;
7261 SMB_STRUCT_STAT sbuf
;
7265 if (total_data
< 100) {
7266 return NT_STATUS_INVALID_PARAMETER
;
7269 if(IVAL(pdata
, 0) != SMB_SIZE_NO_CHANGE_LO
&&
7270 IVAL(pdata
, 4) != SMB_SIZE_NO_CHANGE_HI
) {
7271 size
=IVAL(pdata
,0); /* first 8 Bytes are size */
7272 size
|= (((off_t
)IVAL(pdata
,4)) << 32);
7275 ft
.atime
= interpret_long_date(pdata
+24); /* access_time */
7276 ft
.mtime
= interpret_long_date(pdata
+32); /* modification_time */
7277 set_owner
= (uid_t
)IVAL(pdata
,40);
7278 set_grp
= (gid_t
)IVAL(pdata
,48);
7279 raw_unixmode
= IVAL(pdata
,84);
7281 if (VALID_STAT(smb_fname
->st
)) {
7282 if (S_ISDIR(smb_fname
->st
.st_ex_mode
)) {
7283 ptype
= PERM_EXISTING_DIR
;
7285 ptype
= PERM_EXISTING_FILE
;
7288 ptype
= PERM_NEW_FILE
;
7291 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
7293 if (!NT_STATUS_IS_OK(status
)) {
7297 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
7298 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
7299 smb_fname_str_dbg(smb_fname
), (double)size
,
7300 (unsigned int)set_owner
, (unsigned int)set_grp
,
7301 (int)raw_unixmode
));
7303 sbuf
= smb_fname
->st
;
7305 if (!VALID_STAT(sbuf
)) {
7307 * The only valid use of this is to create character and block
7308 * devices, and named pipes. This is deprecated (IMHO) and
7309 * a new info level should be used for mknod. JRA.
7312 status
= smb_unix_mknod(conn
,
7316 if (!NT_STATUS_IS_OK(status
)) {
7320 smb_fname_tmp
= cp_smb_filename(talloc_tos(), smb_fname
);
7321 if (smb_fname_tmp
== NULL
) {
7322 return NT_STATUS_NO_MEMORY
;
7325 if (SMB_VFS_STAT(conn
, smb_fname_tmp
) != 0) {
7326 status
= map_nt_error_from_unix(errno
);
7327 TALLOC_FREE(smb_fname_tmp
);
7328 SMB_VFS_UNLINK(conn
, smb_fname
);
7332 sbuf
= smb_fname_tmp
->st
;
7333 smb_fname
= smb_fname_tmp
;
7335 /* Ensure we don't try and change anything else. */
7336 raw_unixmode
= SMB_MODE_NO_CHANGE
;
7337 size
= get_file_size_stat(&sbuf
);
7338 ft
.atime
= sbuf
.st_ex_atime
;
7339 ft
.mtime
= sbuf
.st_ex_mtime
;
7341 * We continue here as we might want to change the
7344 delete_on_fail
= True
;
7348 /* Horrible backwards compatibility hack as an old server bug
7349 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
7353 size
= get_file_size_stat(&sbuf
);
7358 * Deal with the UNIX specific mode set.
7361 if (raw_unixmode
!= SMB_MODE_NO_CHANGE
) {
7364 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7365 "setting mode 0%o for file %s\n",
7366 (unsigned int)unixmode
,
7367 smb_fname_str_dbg(smb_fname
)));
7368 if (fsp
&& fsp
->fh
->fd
!= -1) {
7369 ret
= SMB_VFS_FCHMOD(fsp
, unixmode
);
7371 ret
= SMB_VFS_CHMOD(conn
, smb_fname
->base_name
, unixmode
);
7374 return map_nt_error_from_unix(errno
);
7379 * Deal with the UNIX specific uid set.
7382 if ((set_owner
!= (uid_t
)SMB_UID_NO_CHANGE
) &&
7383 (sbuf
.st_ex_uid
!= set_owner
)) {
7386 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7387 "changing owner %u for path %s\n",
7388 (unsigned int)set_owner
,
7389 smb_fname_str_dbg(smb_fname
)));
7391 if (fsp
&& fsp
->fh
->fd
!= -1) {
7392 ret
= SMB_VFS_FCHOWN(fsp
, set_owner
, (gid_t
)-1);
7395 * UNIX extensions calls must always operate
7398 ret
= SMB_VFS_LCHOWN(conn
, smb_fname
->base_name
,
7399 set_owner
, (gid_t
)-1);
7403 status
= map_nt_error_from_unix(errno
);
7404 if (delete_on_fail
) {
7405 SMB_VFS_UNLINK(conn
, smb_fname
);
7412 * Deal with the UNIX specific gid set.
7415 if ((set_grp
!= (uid_t
)SMB_GID_NO_CHANGE
) &&
7416 (sbuf
.st_ex_gid
!= set_grp
)) {
7419 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7420 "changing group %u for file %s\n",
7421 (unsigned int)set_owner
,
7422 smb_fname_str_dbg(smb_fname
)));
7423 if (fsp
&& fsp
->fh
->fd
!= -1) {
7424 ret
= SMB_VFS_FCHOWN(fsp
, set_owner
, (gid_t
)-1);
7427 * UNIX extensions calls must always operate
7430 ret
= SMB_VFS_LCHOWN(conn
, smb_fname
->base_name
, (uid_t
)-1,
7434 status
= map_nt_error_from_unix(errno
);
7435 if (delete_on_fail
) {
7436 SMB_VFS_UNLINK(conn
, smb_fname
);
7442 /* Deal with any size changes. */
7444 status
= smb_set_file_size(conn
, req
,
7450 if (!NT_STATUS_IS_OK(status
)) {
7454 /* Deal with any time changes. */
7455 if (null_timespec(ft
.mtime
) && null_timespec(ft
.atime
)) {
7456 /* No change, don't cancel anything. */
7460 id
= vfs_file_id_from_sbuf(conn
, &sbuf
);
7461 for(all_fsps
= file_find_di_first(conn
->sconn
, id
); all_fsps
;
7462 all_fsps
= file_find_di_next(all_fsps
)) {
7464 * We're setting the time explicitly for UNIX.
7465 * Cancel any pending changes over all handles.
7467 all_fsps
->update_write_time_on_close
= false;
7468 TALLOC_FREE(all_fsps
->update_write_time_event
);
7472 * Override the "setting_write_time"
7473 * parameter here as it almost does what
7474 * we need. Just remember if we modified
7475 * mtime and send the notify ourselves.
7477 if (null_timespec(ft
.mtime
)) {
7478 modify_mtime
= false;
7481 status
= smb_set_file_time(conn
,
7487 notify_fname(conn
, NOTIFY_ACTION_MODIFIED
,
7488 FILE_NOTIFY_CHANGE_LAST_WRITE
, smb_fname
->base_name
);
7493 /****************************************************************************
7494 Deal with SMB_SET_FILE_UNIX_INFO2.
7495 ****************************************************************************/
7497 static NTSTATUS
smb_set_file_unix_info2(connection_struct
*conn
,
7498 struct smb_request
*req
,
7502 const struct smb_filename
*smb_fname
)
7505 uint32_t smb_fflags
;
7508 if (total_data
< 116) {
7509 return NT_STATUS_INVALID_PARAMETER
;
7512 /* Start by setting all the fields that are common between UNIX_BASIC
7515 status
= smb_set_file_unix_basic(conn
, req
, pdata
, total_data
,
7517 if (!NT_STATUS_IS_OK(status
)) {
7521 smb_fflags
= IVAL(pdata
, 108);
7522 smb_fmask
= IVAL(pdata
, 112);
7524 /* NB: We should only attempt to alter the file flags if the client
7525 * sends a non-zero mask.
7527 if (smb_fmask
!= 0) {
7528 int stat_fflags
= 0;
7530 if (!map_info2_flags_to_sbuf(&smb_fname
->st
, smb_fflags
,
7531 smb_fmask
, &stat_fflags
)) {
7532 /* Client asked to alter a flag we don't understand. */
7533 return NT_STATUS_INVALID_PARAMETER
;
7536 if (fsp
&& fsp
->fh
->fd
!= -1) {
7537 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
7538 return NT_STATUS_NOT_SUPPORTED
;
7540 if (SMB_VFS_CHFLAGS(conn
, smb_fname
->base_name
,
7541 stat_fflags
) != 0) {
7542 return map_nt_error_from_unix(errno
);
7547 /* XXX: need to add support for changing the create_time here. You
7548 * can do this for paths on Darwin with setattrlist(2). The right way
7549 * to hook this up is probably by extending the VFS utimes interface.
7552 return NT_STATUS_OK
;
7555 /****************************************************************************
7556 Create a directory with POSIX semantics.
7557 ****************************************************************************/
7559 static NTSTATUS
smb_posix_mkdir(connection_struct
*conn
,
7560 struct smb_request
*req
,
7563 struct smb_filename
*smb_fname
,
7564 int *pdata_return_size
)
7566 NTSTATUS status
= NT_STATUS_OK
;
7567 uint32_t raw_unixmode
= 0;
7568 uint32_t mod_unixmode
= 0;
7569 mode_t unixmode
= (mode_t
)0;
7570 files_struct
*fsp
= NULL
;
7571 uint16_t info_level_return
= 0;
7573 char *pdata
= *ppdata
;
7575 if (total_data
< 18) {
7576 return NT_STATUS_INVALID_PARAMETER
;
7579 raw_unixmode
= IVAL(pdata
,8);
7580 /* Next 4 bytes are not yet defined. */
7582 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
7583 PERM_NEW_DIR
, &unixmode
);
7584 if (!NT_STATUS_IS_OK(status
)) {
7588 mod_unixmode
= (uint32_t)unixmode
| FILE_FLAG_POSIX_SEMANTICS
;
7590 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
7591 smb_fname_str_dbg(smb_fname
), (unsigned int)unixmode
));
7593 status
= SMB_VFS_CREATE_FILE(
7596 0, /* root_dir_fid */
7597 smb_fname
, /* fname */
7598 FILE_READ_ATTRIBUTES
, /* access_mask */
7599 FILE_SHARE_NONE
, /* share_access */
7600 FILE_CREATE
, /* create_disposition*/
7601 FILE_DIRECTORY_FILE
, /* create_options */
7602 mod_unixmode
, /* file_attributes */
7603 0, /* oplock_request */
7605 0, /* allocation_size */
7606 0, /* private_flags */
7611 NULL
, NULL
); /* create context */
7613 if (NT_STATUS_IS_OK(status
)) {
7614 close_file(req
, fsp
, NORMAL_CLOSE
);
7617 info_level_return
= SVAL(pdata
,16);
7619 if (info_level_return
== SMB_QUERY_FILE_UNIX_BASIC
) {
7620 *pdata_return_size
= 12 + SMB_FILE_UNIX_BASIC_SIZE
;
7621 } else if (info_level_return
== SMB_QUERY_FILE_UNIX_INFO2
) {
7622 *pdata_return_size
= 12 + SMB_FILE_UNIX_INFO2_SIZE
;
7624 *pdata_return_size
= 12;
7627 /* Realloc the data size */
7628 *ppdata
= (char *)SMB_REALLOC(*ppdata
,*pdata_return_size
);
7629 if (*ppdata
== NULL
) {
7630 *pdata_return_size
= 0;
7631 return NT_STATUS_NO_MEMORY
;
7635 SSVAL(pdata
,0,NO_OPLOCK_RETURN
);
7636 SSVAL(pdata
,2,0); /* No fnum. */
7637 SIVAL(pdata
,4,info
); /* Was directory created. */
7639 switch (info_level_return
) {
7640 case SMB_QUERY_FILE_UNIX_BASIC
:
7641 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_BASIC
);
7642 SSVAL(pdata
,10,0); /* Padding. */
7643 store_file_unix_basic(conn
, pdata
+ 12, fsp
,
7646 case SMB_QUERY_FILE_UNIX_INFO2
:
7647 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_INFO2
);
7648 SSVAL(pdata
,10,0); /* Padding. */
7649 store_file_unix_basic_info2(conn
, pdata
+ 12, fsp
,
7653 SSVAL(pdata
,8,SMB_NO_INFO_LEVEL_RETURNED
);
7654 SSVAL(pdata
,10,0); /* Padding. */
7661 /****************************************************************************
7662 Open/Create a file with POSIX semantics.
7663 ****************************************************************************/
7665 #define SMB_O_RDONLY_MAPPING (FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA)
7666 #define SMB_O_WRONLY_MAPPING (FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA)
7668 static NTSTATUS
smb_posix_open(connection_struct
*conn
,
7669 struct smb_request
*req
,
7672 struct smb_filename
*smb_fname
,
7673 int *pdata_return_size
)
7675 bool extended_oplock_granted
= False
;
7676 char *pdata
= *ppdata
;
7678 uint32_t wire_open_mode
= 0;
7679 uint32_t raw_unixmode
= 0;
7680 uint32_t mod_unixmode
= 0;
7681 uint32_t create_disp
= 0;
7682 uint32_t access_mask
= 0;
7683 uint32_t create_options
= FILE_NON_DIRECTORY_FILE
;
7684 NTSTATUS status
= NT_STATUS_OK
;
7685 mode_t unixmode
= (mode_t
)0;
7686 files_struct
*fsp
= NULL
;
7687 int oplock_request
= 0;
7689 uint16_t info_level_return
= 0;
7691 if (total_data
< 18) {
7692 return NT_STATUS_INVALID_PARAMETER
;
7695 flags
= IVAL(pdata
,0);
7696 oplock_request
= (flags
& REQUEST_OPLOCK
) ? EXCLUSIVE_OPLOCK
: 0;
7697 if (oplock_request
) {
7698 oplock_request
|= (flags
& REQUEST_BATCH_OPLOCK
) ? BATCH_OPLOCK
: 0;
7701 wire_open_mode
= IVAL(pdata
,4);
7703 if (wire_open_mode
== (SMB_O_CREAT
|SMB_O_DIRECTORY
)) {
7704 return smb_posix_mkdir(conn
, req
,
7711 switch (wire_open_mode
& SMB_ACCMODE
) {
7713 access_mask
= SMB_O_RDONLY_MAPPING
;
7716 access_mask
= SMB_O_WRONLY_MAPPING
;
7719 access_mask
= (SMB_O_RDONLY_MAPPING
|
7720 SMB_O_WRONLY_MAPPING
);
7723 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
7724 (unsigned int)wire_open_mode
));
7725 return NT_STATUS_INVALID_PARAMETER
;
7728 wire_open_mode
&= ~SMB_ACCMODE
;
7730 /* First take care of O_CREAT|O_EXCL interactions. */
7731 switch (wire_open_mode
& (SMB_O_CREAT
| SMB_O_EXCL
)) {
7732 case (SMB_O_CREAT
| SMB_O_EXCL
):
7733 /* File exists fail. File not exist create. */
7734 create_disp
= FILE_CREATE
;
7737 /* File exists open. File not exist create. */
7738 create_disp
= FILE_OPEN_IF
;
7741 /* O_EXCL on its own without O_CREAT is undefined.
7742 We deliberately ignore it as some versions of
7743 Linux CIFSFS can send a bare O_EXCL on the
7744 wire which other filesystems in the kernel
7745 ignore. See bug 9519 for details. */
7750 /* File exists open. File not exist fail. */
7751 create_disp
= FILE_OPEN
;
7754 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
7755 (unsigned int)wire_open_mode
));
7756 return NT_STATUS_INVALID_PARAMETER
;
7759 /* Next factor in the effects of O_TRUNC. */
7760 wire_open_mode
&= ~(SMB_O_CREAT
| SMB_O_EXCL
);
7762 if (wire_open_mode
& SMB_O_TRUNC
) {
7763 switch (create_disp
) {
7765 /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
7766 /* Leave create_disp alone as
7767 (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
7769 /* File exists fail. File not exist create. */
7772 /* SMB_O_CREAT | SMB_O_TRUNC */
7773 /* File exists overwrite. File not exist create. */
7774 create_disp
= FILE_OVERWRITE_IF
;
7778 /* File exists overwrite. File not exist fail. */
7779 create_disp
= FILE_OVERWRITE
;
7782 /* Cannot get here. */
7783 smb_panic("smb_posix_open: logic error");
7784 return NT_STATUS_INVALID_PARAMETER
;
7788 raw_unixmode
= IVAL(pdata
,8);
7789 /* Next 4 bytes are not yet defined. */
7791 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
7792 (VALID_STAT(smb_fname
->st
) ?
7793 PERM_EXISTING_FILE
: PERM_NEW_FILE
),
7796 if (!NT_STATUS_IS_OK(status
)) {
7800 mod_unixmode
= (uint32_t)unixmode
| FILE_FLAG_POSIX_SEMANTICS
;
7802 if (wire_open_mode
& SMB_O_SYNC
) {
7803 create_options
|= FILE_WRITE_THROUGH
;
7805 if (wire_open_mode
& SMB_O_APPEND
) {
7806 access_mask
|= FILE_APPEND_DATA
;
7808 if (wire_open_mode
& SMB_O_DIRECT
) {
7809 mod_unixmode
|= FILE_FLAG_NO_BUFFERING
;
7812 if ((wire_open_mode
& SMB_O_DIRECTORY
) ||
7813 VALID_STAT_OF_DIR(smb_fname
->st
)) {
7814 if (access_mask
!= SMB_O_RDONLY_MAPPING
) {
7815 return NT_STATUS_FILE_IS_A_DIRECTORY
;
7817 create_options
&= ~FILE_NON_DIRECTORY_FILE
;
7818 create_options
|= FILE_DIRECTORY_FILE
;
7821 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
7822 smb_fname_str_dbg(smb_fname
),
7823 (unsigned int)wire_open_mode
,
7824 (unsigned int)unixmode
));
7826 status
= SMB_VFS_CREATE_FILE(
7829 0, /* root_dir_fid */
7830 smb_fname
, /* fname */
7831 access_mask
, /* access_mask */
7832 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
7834 create_disp
, /* create_disposition*/
7835 create_options
, /* create_options */
7836 mod_unixmode
, /* file_attributes */
7837 oplock_request
, /* oplock_request */
7839 0, /* allocation_size */
7840 0, /* private_flags */
7845 NULL
, NULL
); /* create context */
7847 if (!NT_STATUS_IS_OK(status
)) {
7851 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
7852 extended_oplock_granted
= True
;
7855 if(oplock_request
&& EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
7856 extended_oplock_granted
= True
;
7859 info_level_return
= SVAL(pdata
,16);
7861 /* Allocate the correct return size. */
7863 if (info_level_return
== SMB_QUERY_FILE_UNIX_BASIC
) {
7864 *pdata_return_size
= 12 + SMB_FILE_UNIX_BASIC_SIZE
;
7865 } else if (info_level_return
== SMB_QUERY_FILE_UNIX_INFO2
) {
7866 *pdata_return_size
= 12 + SMB_FILE_UNIX_INFO2_SIZE
;
7868 *pdata_return_size
= 12;
7871 /* Realloc the data size */
7872 *ppdata
= (char *)SMB_REALLOC(*ppdata
,*pdata_return_size
);
7873 if (*ppdata
== NULL
) {
7874 close_file(req
, fsp
, ERROR_CLOSE
);
7875 *pdata_return_size
= 0;
7876 return NT_STATUS_NO_MEMORY
;
7880 if (extended_oplock_granted
) {
7881 if (flags
& REQUEST_BATCH_OPLOCK
) {
7882 SSVAL(pdata
,0, BATCH_OPLOCK_RETURN
);
7884 SSVAL(pdata
,0, EXCLUSIVE_OPLOCK_RETURN
);
7886 } else if (fsp
->oplock_type
== LEVEL_II_OPLOCK
) {
7887 SSVAL(pdata
,0, LEVEL_II_OPLOCK_RETURN
);
7889 SSVAL(pdata
,0,NO_OPLOCK_RETURN
);
7892 SSVAL(pdata
,2,fsp
->fnum
);
7893 SIVAL(pdata
,4,info
); /* Was file created etc. */
7895 switch (info_level_return
) {
7896 case SMB_QUERY_FILE_UNIX_BASIC
:
7897 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_BASIC
);
7898 SSVAL(pdata
,10,0); /* padding. */
7899 store_file_unix_basic(conn
, pdata
+ 12, fsp
,
7902 case SMB_QUERY_FILE_UNIX_INFO2
:
7903 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_INFO2
);
7904 SSVAL(pdata
,10,0); /* padding. */
7905 store_file_unix_basic_info2(conn
, pdata
+ 12, fsp
,
7909 SSVAL(pdata
,8,SMB_NO_INFO_LEVEL_RETURNED
);
7910 SSVAL(pdata
,10,0); /* padding. */
7913 return NT_STATUS_OK
;
7916 /****************************************************************************
7917 Delete a file with POSIX semantics.
7918 ****************************************************************************/
7920 static NTSTATUS
smb_posix_unlink(connection_struct
*conn
,
7921 struct smb_request
*req
,
7924 struct smb_filename
*smb_fname
)
7926 NTSTATUS status
= NT_STATUS_OK
;
7927 files_struct
*fsp
= NULL
;
7931 int create_options
= 0;
7933 struct share_mode_lock
*lck
= NULL
;
7935 if (total_data
< 2) {
7936 return NT_STATUS_INVALID_PARAMETER
;
7939 flags
= SVAL(pdata
,0);
7941 if (!VALID_STAT(smb_fname
->st
)) {
7942 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
7945 if ((flags
== SMB_POSIX_UNLINK_DIRECTORY_TARGET
) &&
7946 !VALID_STAT_OF_DIR(smb_fname
->st
)) {
7947 return NT_STATUS_NOT_A_DIRECTORY
;
7950 DEBUG(10,("smb_posix_unlink: %s %s\n",
7951 (flags
== SMB_POSIX_UNLINK_DIRECTORY_TARGET
) ? "directory" : "file",
7952 smb_fname_str_dbg(smb_fname
)));
7954 if (VALID_STAT_OF_DIR(smb_fname
->st
)) {
7955 create_options
|= FILE_DIRECTORY_FILE
;
7958 status
= SMB_VFS_CREATE_FILE(
7961 0, /* root_dir_fid */
7962 smb_fname
, /* fname */
7963 DELETE_ACCESS
, /* access_mask */
7964 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
7966 FILE_OPEN
, /* create_disposition*/
7967 create_options
, /* create_options */
7968 FILE_FLAG_POSIX_SEMANTICS
|0777, /* file_attributes */
7969 0, /* oplock_request */
7971 0, /* allocation_size */
7972 0, /* private_flags */
7977 NULL
, NULL
); /* create context */
7979 if (!NT_STATUS_IS_OK(status
)) {
7984 * Don't lie to client. If we can't really delete due to
7985 * non-POSIX opens return SHARING_VIOLATION.
7988 lck
= get_existing_share_mode_lock(talloc_tos(), fsp
->file_id
);
7990 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
7991 "lock for file %s\n", fsp_str_dbg(fsp
)));
7992 close_file(req
, fsp
, NORMAL_CLOSE
);
7993 return NT_STATUS_INVALID_PARAMETER
;
7997 * See if others still have the file open. If this is the case, then
7998 * don't delete. If all opens are POSIX delete we can set the delete
7999 * on close disposition.
8001 for (i
=0; i
<lck
->data
->num_share_modes
; i
++) {
8002 struct share_mode_entry
*e
= &lck
->data
->share_modes
[i
];
8003 if (is_valid_share_mode_entry(e
)) {
8004 if (e
->flags
& SHARE_MODE_FLAG_POSIX_OPEN
) {
8007 if (share_mode_stale_pid(lck
->data
, i
)) {
8010 /* Fail with sharing violation. */
8012 close_file(req
, fsp
, NORMAL_CLOSE
);
8013 return NT_STATUS_SHARING_VIOLATION
;
8018 * Set the delete on close.
8020 status
= smb_set_file_disposition_info(conn
,
8028 if (!NT_STATUS_IS_OK(status
)) {
8029 close_file(req
, fsp
, NORMAL_CLOSE
);
8032 return close_file(req
, fsp
, NORMAL_CLOSE
);
8035 NTSTATUS
smbd_do_setfilepathinfo(connection_struct
*conn
,
8036 struct smb_request
*req
,
8037 TALLOC_CTX
*mem_ctx
,
8038 uint16_t info_level
,
8040 struct smb_filename
*smb_fname
,
8041 char **ppdata
, int total_data
,
8044 char *pdata
= *ppdata
;
8045 NTSTATUS status
= NT_STATUS_OK
;
8046 int data_return_size
= 0;
8050 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
8051 return NT_STATUS_INVALID_LEVEL
;
8054 if (!CAN_WRITE(conn
)) {
8055 /* Allow POSIX opens. The open path will deny
8056 * any non-readonly opens. */
8057 if (info_level
!= SMB_POSIX_PATH_OPEN
) {
8058 return NT_STATUS_DOS(ERRSRV
, ERRaccess
);
8062 DEBUG(3,("smbd_do_setfilepathinfo: %s (%s) info_level=%d "
8063 "totdata=%d\n", smb_fname_str_dbg(smb_fname
),
8065 info_level
, total_data
));
8067 switch (info_level
) {
8069 case SMB_INFO_STANDARD
:
8071 status
= smb_set_info_standard(conn
,
8079 case SMB_INFO_SET_EA
:
8081 status
= smb_info_set_ea(conn
,
8089 case SMB_SET_FILE_BASIC_INFO
:
8090 case SMB_FILE_BASIC_INFORMATION
:
8092 status
= smb_set_file_basic_info(conn
,
8100 case SMB_FILE_ALLOCATION_INFORMATION
:
8101 case SMB_SET_FILE_ALLOCATION_INFO
:
8103 status
= smb_set_file_allocation_info(conn
, req
,
8111 case SMB_FILE_END_OF_FILE_INFORMATION
:
8112 case SMB_SET_FILE_END_OF_FILE_INFO
:
8115 * XP/Win7 both fail after the createfile with
8116 * SMB_SET_FILE_END_OF_FILE_INFO but not
8117 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
8118 * The level is known here, so pass it down
8122 (info_level
== SMB_SET_FILE_END_OF_FILE_INFO
);
8124 status
= smb_set_file_end_of_file_info(conn
, req
,
8133 case SMB_FILE_DISPOSITION_INFORMATION
:
8134 case SMB_SET_FILE_DISPOSITION_INFO
: /* Set delete on close for open file. */
8137 /* JRA - We used to just ignore this on a path ?
8138 * Shouldn't this be invalid level on a pathname
8141 if (tran_call
!= TRANSACT2_SETFILEINFO
) {
8142 return ERROR_NT(NT_STATUS_INVALID_LEVEL
);
8145 status
= smb_set_file_disposition_info(conn
,
8153 case SMB_FILE_POSITION_INFORMATION
:
8155 status
= smb_file_position_information(conn
,
8162 case SMB_FILE_FULL_EA_INFORMATION
:
8164 status
= smb_set_file_full_ea_info(conn
,
8171 /* From tridge Samba4 :
8172 * MODE_INFORMATION in setfileinfo (I have no
8173 * idea what "mode information" on a file is - it takes a value of 0,
8174 * 2, 4 or 6. What could it be?).
8177 case SMB_FILE_MODE_INFORMATION
:
8179 status
= smb_file_mode_information(conn
,
8186 * CIFS UNIX extensions.
8189 case SMB_SET_FILE_UNIX_BASIC
:
8191 status
= smb_set_file_unix_basic(conn
, req
,
8199 case SMB_SET_FILE_UNIX_INFO2
:
8201 status
= smb_set_file_unix_info2(conn
, req
,
8209 case SMB_SET_FILE_UNIX_LINK
:
8212 /* We must have a pathname for this. */
8213 return NT_STATUS_INVALID_LEVEL
;
8215 status
= smb_set_file_unix_link(conn
, req
, pdata
,
8216 total_data
, smb_fname
);
8220 case SMB_SET_FILE_UNIX_HLINK
:
8223 /* We must have a pathname for this. */
8224 return NT_STATUS_INVALID_LEVEL
;
8226 status
= smb_set_file_unix_hlink(conn
, req
,
8232 case SMB_FILE_RENAME_INFORMATION
:
8234 status
= smb_file_rename_information(conn
, req
,
8240 case SMB2_FILE_RENAME_INFORMATION_INTERNAL
:
8242 /* SMB2 rename information. */
8243 status
= smb2_file_rename_information(conn
, req
,
8249 case SMB_FILE_LINK_INFORMATION
:
8251 status
= smb_file_link_information(conn
, req
,
8257 #if defined(HAVE_POSIX_ACLS)
8258 case SMB_SET_POSIX_ACL
:
8260 status
= smb_set_posix_acl(conn
,
8269 case SMB_SET_POSIX_LOCK
:
8272 return NT_STATUS_INVALID_LEVEL
;
8274 status
= smb_set_posix_lock(conn
, req
,
8275 pdata
, total_data
, fsp
);
8279 case SMB_POSIX_PATH_OPEN
:
8282 /* We must have a pathname for this. */
8283 return NT_STATUS_INVALID_LEVEL
;
8286 status
= smb_posix_open(conn
, req
,
8294 case SMB_POSIX_PATH_UNLINK
:
8297 /* We must have a pathname for this. */
8298 return NT_STATUS_INVALID_LEVEL
;
8301 status
= smb_posix_unlink(conn
, req
,
8309 return NT_STATUS_INVALID_LEVEL
;
8312 if (!NT_STATUS_IS_OK(status
)) {
8316 *ret_data_size
= data_return_size
;
8317 return NT_STATUS_OK
;
8320 /****************************************************************************
8321 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
8322 ****************************************************************************/
8324 static void call_trans2setfilepathinfo(connection_struct
*conn
,
8325 struct smb_request
*req
,
8326 unsigned int tran_call
,
8327 char **pparams
, int total_params
,
8328 char **ppdata
, int total_data
,
8329 unsigned int max_data_bytes
)
8331 char *params
= *pparams
;
8332 char *pdata
= *ppdata
;
8333 uint16_t info_level
;
8334 struct smb_filename
*smb_fname
= NULL
;
8335 files_struct
*fsp
= NULL
;
8336 NTSTATUS status
= NT_STATUS_OK
;
8337 int data_return_size
= 0;
8340 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8344 if (tran_call
== TRANSACT2_SETFILEINFO
) {
8345 if (total_params
< 4) {
8346 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8350 fsp
= file_fsp(req
, SVAL(params
,0));
8351 /* Basic check for non-null fsp. */
8352 if (!check_fsp_open(conn
, req
, fsp
)) {
8355 info_level
= SVAL(params
,2);
8357 smb_fname
= cp_smb_filename(talloc_tos(), fsp
->fsp_name
);
8358 if (smb_fname
== NULL
) {
8359 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8363 if(fsp
->fh
->fd
== -1) {
8365 * This is actually a SETFILEINFO on a directory
8366 * handle (returned from an NT SMB). NT5.0 seems
8367 * to do this call. JRA.
8369 if (INFO_LEVEL_IS_UNIX(info_level
)) {
8370 /* Always do lstat for UNIX calls. */
8371 if (SMB_VFS_LSTAT(conn
, smb_fname
)) {
8372 DEBUG(3,("call_trans2setfilepathinfo: "
8373 "SMB_VFS_LSTAT of %s failed "
8375 smb_fname_str_dbg(smb_fname
),
8377 reply_nterror(req
, map_nt_error_from_unix(errno
));
8381 if (SMB_VFS_STAT(conn
, smb_fname
) != 0) {
8382 DEBUG(3,("call_trans2setfilepathinfo: "
8383 "fileinfo of %s failed (%s)\n",
8384 smb_fname_str_dbg(smb_fname
),
8386 reply_nterror(req
, map_nt_error_from_unix(errno
));
8390 } else if (fsp
->print_file
) {
8392 * Doing a DELETE_ON_CLOSE should cancel a print job.
8394 if ((info_level
== SMB_SET_FILE_DISPOSITION_INFO
) && CVAL(pdata
,0)) {
8395 fsp
->fh
->private_options
|= NTCREATEX_OPTIONS_PRIVATE_DELETE_ON_CLOSE
;
8397 DEBUG(3,("call_trans2setfilepathinfo: "
8398 "Cancelling print job (%s)\n",
8402 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 2,
8408 NT_STATUS_OBJECT_PATH_NOT_FOUND
);
8413 * Original code - this is an open file.
8415 if (SMB_VFS_FSTAT(fsp
, &smb_fname
->st
) != 0) {
8416 DEBUG(3,("call_trans2setfilepathinfo: fstat "
8417 "of %s failed (%s)\n", fsp_fnum_dbg(fsp
),
8419 reply_nterror(req
, map_nt_error_from_unix(errno
));
8425 uint32_t ucf_flags
= 0;
8428 if (total_params
< 7) {
8429 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8433 info_level
= SVAL(params
,0);
8434 srvstr_get_path(req
, params
, req
->flags2
, &fname
, ¶ms
[6],
8435 total_params
- 6, STR_TERMINATE
,
8437 if (!NT_STATUS_IS_OK(status
)) {
8438 reply_nterror(req
, status
);
8442 if (info_level
== SMB_SET_FILE_UNIX_BASIC
||
8443 info_level
== SMB_SET_FILE_UNIX_INFO2
||
8444 info_level
== SMB_FILE_RENAME_INFORMATION
||
8445 info_level
== SMB_POSIX_PATH_UNLINK
) {
8446 ucf_flags
|= UCF_UNIX_NAME_LOOKUP
;
8449 status
= filename_convert(req
, conn
,
8450 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
8455 if (!NT_STATUS_IS_OK(status
)) {
8456 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
8457 reply_botherror(req
,
8458 NT_STATUS_PATH_NOT_COVERED
,
8459 ERRSRV
, ERRbadpath
);
8462 reply_nterror(req
, status
);
8466 if (INFO_LEVEL_IS_UNIX(info_level
)) {
8468 * For CIFS UNIX extensions the target name may not exist.
8471 /* Always do lstat for UNIX calls. */
8472 SMB_VFS_LSTAT(conn
, smb_fname
);
8474 } else if (!VALID_STAT(smb_fname
->st
) &&
8475 SMB_VFS_STAT(conn
, smb_fname
)) {
8476 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
8478 smb_fname_str_dbg(smb_fname
),
8480 reply_nterror(req
, map_nt_error_from_unix(errno
));
8485 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (%s) info_level=%d "
8486 "totdata=%d\n", tran_call
, smb_fname_str_dbg(smb_fname
),
8488 info_level
,total_data
));
8490 /* Realloc the parameter size */
8491 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
8492 if (*pparams
== NULL
) {
8493 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8500 status
= smbd_do_setfilepathinfo(conn
, req
, req
,
8506 if (!NT_STATUS_IS_OK(status
)) {
8507 if (open_was_deferred(req
->xconn
, req
->mid
)) {
8508 /* We have re-scheduled this call. */
8511 if (blocking_lock_was_deferred_smb1(req
->sconn
, req
->mid
)) {
8512 /* We have re-scheduled this call. */
8515 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
8516 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
8517 ERRSRV
, ERRbadpath
);
8520 if (info_level
== SMB_POSIX_PATH_OPEN
) {
8521 reply_openerror(req
, status
);
8526 * Invalid EA name needs to return 2 param bytes,
8527 * not a zero-length error packet.
8529 if (NT_STATUS_EQUAL(status
, STATUS_INVALID_EA_NAME
)) {
8530 send_trans2_replies(conn
, req
, status
, params
, 2, NULL
, 0,
8533 reply_nterror(req
, status
);
8538 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 2, *ppdata
, data_return_size
,
8544 /****************************************************************************
8545 Reply to a TRANS2_MKDIR (make directory with extended attributes).
8546 ****************************************************************************/
8548 static void call_trans2mkdir(connection_struct
*conn
, struct smb_request
*req
,
8549 char **pparams
, int total_params
,
8550 char **ppdata
, int total_data
,
8551 unsigned int max_data_bytes
)
8553 struct smb_filename
*smb_dname
= NULL
;
8554 char *params
= *pparams
;
8555 char *pdata
= *ppdata
;
8556 char *directory
= NULL
;
8557 NTSTATUS status
= NT_STATUS_OK
;
8558 struct ea_list
*ea_list
= NULL
;
8559 TALLOC_CTX
*ctx
= talloc_tos();
8561 if (!CAN_WRITE(conn
)) {
8562 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
8566 if (total_params
< 5) {
8567 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8571 srvstr_get_path(ctx
, params
, req
->flags2
, &directory
, ¶ms
[4],
8572 total_params
- 4, STR_TERMINATE
,
8574 if (!NT_STATUS_IS_OK(status
)) {
8575 reply_nterror(req
, status
);
8579 DEBUG(3,("call_trans2mkdir : name = %s\n", directory
));
8581 status
= filename_convert(ctx
,
8583 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
8589 if (!NT_STATUS_IS_OK(status
)) {
8590 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
8591 reply_botherror(req
,
8592 NT_STATUS_PATH_NOT_COVERED
,
8593 ERRSRV
, ERRbadpath
);
8596 reply_nterror(req
, status
);
8601 * OS/2 workplace shell seems to send SET_EA requests of "null"
8602 * length (4 bytes containing IVAL 4).
8603 * They seem to have no effect. Bug #3212. JRA.
8606 if (total_data
&& (total_data
!= 4)) {
8607 /* Any data in this call is an EA list. */
8608 if (total_data
< 10) {
8609 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8613 if (IVAL(pdata
,0) > total_data
) {
8614 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
8615 IVAL(pdata
,0), (unsigned int)total_data
));
8616 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8620 ea_list
= read_ea_list(talloc_tos(), pdata
+ 4,
8623 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8627 if (!lp_ea_support(SNUM(conn
))) {
8628 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
8632 /* If total_data == 4 Windows doesn't care what values
8633 * are placed in that field, it just ignores them.
8634 * The System i QNTC IBM SMB client puts bad values here,
8635 * so ignore them. */
8637 status
= create_directory(conn
, req
, smb_dname
);
8639 if (!NT_STATUS_IS_OK(status
)) {
8640 reply_nterror(req
, status
);
8644 /* Try and set any given EA. */
8646 status
= set_ea(conn
, NULL
, smb_dname
, ea_list
);
8647 if (!NT_STATUS_IS_OK(status
)) {
8648 reply_nterror(req
, status
);
8653 /* Realloc the parameter and data sizes */
8654 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
8655 if(*pparams
== NULL
) {
8656 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8663 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 2, *ppdata
, 0, max_data_bytes
);
8666 TALLOC_FREE(smb_dname
);
8670 /****************************************************************************
8671 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
8672 We don't actually do this - we just send a null response.
8673 ****************************************************************************/
8675 static void call_trans2findnotifyfirst(connection_struct
*conn
,
8676 struct smb_request
*req
,
8677 char **pparams
, int total_params
,
8678 char **ppdata
, int total_data
,
8679 unsigned int max_data_bytes
)
8681 char *params
= *pparams
;
8682 uint16_t info_level
;
8684 if (total_params
< 6) {
8685 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8689 info_level
= SVAL(params
,4);
8690 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level
));
8692 switch (info_level
) {
8697 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
8701 /* Realloc the parameter and data sizes */
8702 *pparams
= (char *)SMB_REALLOC(*pparams
,6);
8703 if (*pparams
== NULL
) {
8704 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8709 SSVAL(params
,0,fnf_handle
);
8710 SSVAL(params
,2,0); /* No changes */
8711 SSVAL(params
,4,0); /* No EA errors */
8718 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 6, *ppdata
, 0, max_data_bytes
);
8723 /****************************************************************************
8724 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
8725 changes). Currently this does nothing.
8726 ****************************************************************************/
8728 static void call_trans2findnotifynext(connection_struct
*conn
,
8729 struct smb_request
*req
,
8730 char **pparams
, int total_params
,
8731 char **ppdata
, int total_data
,
8732 unsigned int max_data_bytes
)
8734 char *params
= *pparams
;
8736 DEBUG(3,("call_trans2findnotifynext\n"));
8738 /* Realloc the parameter and data sizes */
8739 *pparams
= (char *)SMB_REALLOC(*pparams
,4);
8740 if (*pparams
== NULL
) {
8741 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8746 SSVAL(params
,0,0); /* No changes */
8747 SSVAL(params
,2,0); /* No EA errors */
8749 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 4, *ppdata
, 0, max_data_bytes
);
8754 /****************************************************************************
8755 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
8756 ****************************************************************************/
8758 static void call_trans2getdfsreferral(connection_struct
*conn
,
8759 struct smb_request
*req
,
8760 char **pparams
, int total_params
,
8761 char **ppdata
, int total_data
,
8762 unsigned int max_data_bytes
)
8764 char *params
= *pparams
;
8765 char *pathname
= NULL
;
8767 int max_referral_level
;
8768 NTSTATUS status
= NT_STATUS_OK
;
8769 TALLOC_CTX
*ctx
= talloc_tos();
8771 DEBUG(10,("call_trans2getdfsreferral\n"));
8773 if (total_params
< 3) {
8774 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8778 max_referral_level
= SVAL(params
,0);
8780 if(!lp_host_msdfs()) {
8781 reply_nterror(req
, NT_STATUS_NOT_IMPLEMENTED
);
8785 srvstr_pull_talloc(ctx
, params
, req
->flags2
, &pathname
, ¶ms
[2],
8786 total_params
- 2, STR_TERMINATE
);
8788 reply_nterror(req
, NT_STATUS_NOT_FOUND
);
8791 if((reply_size
= setup_dfs_referral(conn
, pathname
, max_referral_level
,
8792 ppdata
,&status
)) < 0) {
8793 reply_nterror(req
, status
);
8797 SSVAL((discard_const_p(uint8_t, req
->inbuf
)), smb_flg2
,
8798 SVAL(req
->inbuf
,smb_flg2
) | FLAGS2_DFS_PATHNAMES
);
8799 send_trans2_replies(conn
, req
, NT_STATUS_OK
, 0,0,*ppdata
,reply_size
, max_data_bytes
);
8804 #define LMCAT_SPL 0x53
8805 #define LMFUNC_GETJOBID 0x60
8807 /****************************************************************************
8808 Reply to a TRANS2_IOCTL - used for OS/2 printing.
8809 ****************************************************************************/
8811 static void call_trans2ioctl(connection_struct
*conn
,
8812 struct smb_request
*req
,
8813 char **pparams
, int total_params
,
8814 char **ppdata
, int total_data
,
8815 unsigned int max_data_bytes
)
8817 char *pdata
= *ppdata
;
8818 files_struct
*fsp
= file_fsp(req
, SVAL(req
->vwv
+15, 0));
8822 /* check for an invalid fid before proceeding */
8825 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
8829 if ((SVAL(req
->vwv
+16, 0) == LMCAT_SPL
)
8830 && (SVAL(req
->vwv
+17, 0) == LMFUNC_GETJOBID
)) {
8831 *ppdata
= (char *)SMB_REALLOC(*ppdata
, 32);
8832 if (*ppdata
== NULL
) {
8833 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8838 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
8839 CAN ACCEPT THIS IN UNICODE. JRA. */
8842 SSVAL(pdata
, 0, print_spool_rap_jobid(fsp
->print_file
));
8844 status
= srvstr_push(pdata
, req
->flags2
, pdata
+ 2,
8845 lp_netbios_name(), 15,
8846 STR_ASCII
|STR_TERMINATE
, &len
); /* Our NetBIOS name */
8847 if (!NT_STATUS_IS_OK(status
)) {
8848 reply_nterror(req
, status
);
8851 status
= srvstr_push(pdata
, req
->flags2
, pdata
+18,
8852 lp_servicename(talloc_tos(), SNUM(conn
)), 13,
8853 STR_ASCII
|STR_TERMINATE
, &len
); /* Service name */
8854 if (!NT_STATUS_IS_OK(status
)) {
8855 reply_nterror(req
, status
);
8858 send_trans2_replies(conn
, req
, NT_STATUS_OK
, *pparams
, 0, *ppdata
, 32,
8863 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
8864 reply_nterror(req
, NT_STATUS_NOT_IMPLEMENTED
);
8867 /****************************************************************************
8868 Reply to a SMBfindclose (stop trans2 directory search).
8869 ****************************************************************************/
8871 void reply_findclose(struct smb_request
*req
)
8874 struct smbd_server_connection
*sconn
= req
->sconn
;
8876 START_PROFILE(SMBfindclose
);
8879 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8880 END_PROFILE(SMBfindclose
);
8884 dptr_num
= SVALS(req
->vwv
+0, 0);
8886 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num
));
8888 dptr_close(sconn
, &dptr_num
);
8890 reply_outbuf(req
, 0, 0);
8892 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num
));
8894 END_PROFILE(SMBfindclose
);
8898 /****************************************************************************
8899 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
8900 ****************************************************************************/
8902 void reply_findnclose(struct smb_request
*req
)
8906 START_PROFILE(SMBfindnclose
);
8909 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8910 END_PROFILE(SMBfindnclose
);
8914 dptr_num
= SVAL(req
->vwv
+0, 0);
8916 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num
));
8918 /* We never give out valid handles for a
8919 findnotifyfirst - so any dptr_num is ok here.
8922 reply_outbuf(req
, 0, 0);
8924 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num
));
8926 END_PROFILE(SMBfindnclose
);
8930 static void handle_trans2(connection_struct
*conn
, struct smb_request
*req
,
8931 struct trans_state
*state
)
8933 if (get_Protocol() >= PROTOCOL_NT1
) {
8934 req
->flags2
|= 0x40; /* IS_LONG_NAME */
8935 SSVAL((discard_const_p(uint8_t, req
->inbuf
)),smb_flg2
,req
->flags2
);
8938 if (ENCRYPTION_REQUIRED(conn
) && !req
->encrypted
) {
8939 if (state
->call
!= TRANSACT2_QFSINFO
&&
8940 state
->call
!= TRANSACT2_SETFSINFO
) {
8941 DEBUG(0,("handle_trans2: encryption required "
8943 (unsigned int)state
->call
));
8944 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
8949 SMB_PERFCOUNT_SET_SUBOP(&req
->pcd
, state
->call
);
8951 /* Now we must call the relevant TRANS2 function */
8952 switch(state
->call
) {
8953 case TRANSACT2_OPEN
:
8955 START_PROFILE(Trans2_open
);
8956 call_trans2open(conn
, req
,
8957 &state
->param
, state
->total_param
,
8958 &state
->data
, state
->total_data
,
8959 state
->max_data_return
);
8960 END_PROFILE(Trans2_open
);
8964 case TRANSACT2_FINDFIRST
:
8966 START_PROFILE(Trans2_findfirst
);
8967 call_trans2findfirst(conn
, req
,
8968 &state
->param
, state
->total_param
,
8969 &state
->data
, state
->total_data
,
8970 state
->max_data_return
);
8971 END_PROFILE(Trans2_findfirst
);
8975 case TRANSACT2_FINDNEXT
:
8977 START_PROFILE(Trans2_findnext
);
8978 call_trans2findnext(conn
, req
,
8979 &state
->param
, state
->total_param
,
8980 &state
->data
, state
->total_data
,
8981 state
->max_data_return
);
8982 END_PROFILE(Trans2_findnext
);
8986 case TRANSACT2_QFSINFO
:
8988 START_PROFILE(Trans2_qfsinfo
);
8989 call_trans2qfsinfo(conn
, req
,
8990 &state
->param
, state
->total_param
,
8991 &state
->data
, state
->total_data
,
8992 state
->max_data_return
);
8993 END_PROFILE(Trans2_qfsinfo
);
8997 case TRANSACT2_SETFSINFO
:
8999 START_PROFILE(Trans2_setfsinfo
);
9000 call_trans2setfsinfo(conn
, req
,
9001 &state
->param
, state
->total_param
,
9002 &state
->data
, state
->total_data
,
9003 state
->max_data_return
);
9004 END_PROFILE(Trans2_setfsinfo
);
9008 case TRANSACT2_QPATHINFO
:
9009 case TRANSACT2_QFILEINFO
:
9011 START_PROFILE(Trans2_qpathinfo
);
9012 call_trans2qfilepathinfo(conn
, req
, state
->call
,
9013 &state
->param
, state
->total_param
,
9014 &state
->data
, state
->total_data
,
9015 state
->max_data_return
);
9016 END_PROFILE(Trans2_qpathinfo
);
9020 case TRANSACT2_SETPATHINFO
:
9021 case TRANSACT2_SETFILEINFO
:
9023 START_PROFILE(Trans2_setpathinfo
);
9024 call_trans2setfilepathinfo(conn
, req
, state
->call
,
9025 &state
->param
, state
->total_param
,
9026 &state
->data
, state
->total_data
,
9027 state
->max_data_return
);
9028 END_PROFILE(Trans2_setpathinfo
);
9032 case TRANSACT2_FINDNOTIFYFIRST
:
9034 START_PROFILE(Trans2_findnotifyfirst
);
9035 call_trans2findnotifyfirst(conn
, req
,
9036 &state
->param
, state
->total_param
,
9037 &state
->data
, state
->total_data
,
9038 state
->max_data_return
);
9039 END_PROFILE(Trans2_findnotifyfirst
);
9043 case TRANSACT2_FINDNOTIFYNEXT
:
9045 START_PROFILE(Trans2_findnotifynext
);
9046 call_trans2findnotifynext(conn
, req
,
9047 &state
->param
, state
->total_param
,
9048 &state
->data
, state
->total_data
,
9049 state
->max_data_return
);
9050 END_PROFILE(Trans2_findnotifynext
);
9054 case TRANSACT2_MKDIR
:
9056 START_PROFILE(Trans2_mkdir
);
9057 call_trans2mkdir(conn
, req
,
9058 &state
->param
, state
->total_param
,
9059 &state
->data
, state
->total_data
,
9060 state
->max_data_return
);
9061 END_PROFILE(Trans2_mkdir
);
9065 case TRANSACT2_GET_DFS_REFERRAL
:
9067 START_PROFILE(Trans2_get_dfs_referral
);
9068 call_trans2getdfsreferral(conn
, req
,
9069 &state
->param
, state
->total_param
,
9070 &state
->data
, state
->total_data
,
9071 state
->max_data_return
);
9072 END_PROFILE(Trans2_get_dfs_referral
);
9076 case TRANSACT2_IOCTL
:
9078 START_PROFILE(Trans2_ioctl
);
9079 call_trans2ioctl(conn
, req
,
9080 &state
->param
, state
->total_param
,
9081 &state
->data
, state
->total_data
,
9082 state
->max_data_return
);
9083 END_PROFILE(Trans2_ioctl
);
9088 /* Error in request */
9089 DEBUG(2,("Unknown request %d in trans2 call\n", state
->call
));
9090 reply_nterror(req
, NT_STATUS_NOT_IMPLEMENTED
);
9094 /****************************************************************************
9095 Reply to a SMBtrans2.
9096 ****************************************************************************/
9098 void reply_trans2(struct smb_request
*req
)
9100 connection_struct
*conn
= req
->conn
;
9105 unsigned int tran_call
;
9106 struct trans_state
*state
;
9109 START_PROFILE(SMBtrans2
);
9111 if (req
->wct
< 14) {
9112 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
9113 END_PROFILE(SMBtrans2
);
9117 dsoff
= SVAL(req
->vwv
+12, 0);
9118 dscnt
= SVAL(req
->vwv
+11, 0);
9119 psoff
= SVAL(req
->vwv
+10, 0);
9120 pscnt
= SVAL(req
->vwv
+9, 0);
9121 tran_call
= SVAL(req
->vwv
+14, 0);
9123 result
= allow_new_trans(conn
->pending_trans
, req
->mid
);
9124 if (!NT_STATUS_IS_OK(result
)) {
9125 DEBUG(2, ("Got invalid trans2 request: %s\n",
9126 nt_errstr(result
)));
9127 reply_nterror(req
, result
);
9128 END_PROFILE(SMBtrans2
);
9133 switch (tran_call
) {
9134 /* List the allowed trans2 calls on IPC$ */
9135 case TRANSACT2_OPEN
:
9136 case TRANSACT2_GET_DFS_REFERRAL
:
9137 case TRANSACT2_QFILEINFO
:
9138 case TRANSACT2_QFSINFO
:
9139 case TRANSACT2_SETFSINFO
:
9142 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
9143 END_PROFILE(SMBtrans2
);
9148 if ((state
= talloc(conn
, struct trans_state
)) == NULL
) {
9149 DEBUG(0, ("talloc failed\n"));
9150 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
9151 END_PROFILE(SMBtrans2
);
9155 state
->cmd
= SMBtrans2
;
9157 state
->mid
= req
->mid
;
9158 state
->vuid
= req
->vuid
;
9159 state
->setup_count
= SVAL(req
->vwv
+13, 0);
9160 state
->setup
= NULL
;
9161 state
->total_param
= SVAL(req
->vwv
+0, 0);
9162 state
->param
= NULL
;
9163 state
->total_data
= SVAL(req
->vwv
+1, 0);
9165 state
->max_param_return
= SVAL(req
->vwv
+2, 0);
9166 state
->max_data_return
= SVAL(req
->vwv
+3, 0);
9167 state
->max_setup_return
= SVAL(req
->vwv
+4, 0);
9168 state
->close_on_completion
= BITSETW(req
->vwv
+5, 0);
9169 state
->one_way
= BITSETW(req
->vwv
+5, 1);
9171 state
->call
= tran_call
;
9173 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
9174 is so as a sanity check */
9175 if (state
->setup_count
!= 1) {
9177 * Need to have rc=0 for ioctl to get job id for OS/2.
9178 * Network printing will fail if function is not successful.
9179 * Similar function in reply.c will be used if protocol
9180 * is LANMAN1.0 instead of LM1.2X002.
9181 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
9182 * outbuf doesn't have to be set(only job id is used).
9184 if ( (state
->setup_count
== 4)
9185 && (tran_call
== TRANSACT2_IOCTL
)
9186 && (SVAL(req
->vwv
+16, 0) == LMCAT_SPL
)
9187 && (SVAL(req
->vwv
+17, 0) == LMFUNC_GETJOBID
)) {
9188 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
9190 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state
->setup_count
));
9191 DEBUG(2,("Transaction is %d\n",tran_call
));
9193 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
9194 END_PROFILE(SMBtrans2
);
9199 if ((dscnt
> state
->total_data
) || (pscnt
> state
->total_param
))
9202 if (state
->total_data
) {
9204 if (trans_oob(state
->total_data
, 0, dscnt
)
9205 || trans_oob(smb_len(req
->inbuf
), dsoff
, dscnt
)) {
9209 /* Can't use talloc here, the core routines do realloc on the
9210 * params and data. */
9211 state
->data
= (char *)SMB_MALLOC(state
->total_data
);
9212 if (state
->data
== NULL
) {
9213 DEBUG(0,("reply_trans2: data malloc fail for %u "
9214 "bytes !\n", (unsigned int)state
->total_data
));
9216 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
9217 END_PROFILE(SMBtrans2
);
9221 memcpy(state
->data
,smb_base(req
->inbuf
)+dsoff
,dscnt
);
9224 if (state
->total_param
) {
9226 if (trans_oob(state
->total_param
, 0, pscnt
)
9227 || trans_oob(smb_len(req
->inbuf
), psoff
, pscnt
)) {
9231 /* Can't use talloc here, the core routines do realloc on the
9232 * params and data. */
9233 state
->param
= (char *)SMB_MALLOC(state
->total_param
);
9234 if (state
->param
== NULL
) {
9235 DEBUG(0,("reply_trans: param malloc fail for %u "
9236 "bytes !\n", (unsigned int)state
->total_param
));
9237 SAFE_FREE(state
->data
);
9239 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
9240 END_PROFILE(SMBtrans2
);
9244 memcpy(state
->param
,smb_base(req
->inbuf
)+psoff
,pscnt
);
9247 state
->received_data
= dscnt
;
9248 state
->received_param
= pscnt
;
9250 if ((state
->received_param
== state
->total_param
) &&
9251 (state
->received_data
== state
->total_data
)) {
9253 handle_trans2(conn
, req
, state
);
9255 SAFE_FREE(state
->data
);
9256 SAFE_FREE(state
->param
);
9258 END_PROFILE(SMBtrans2
);
9262 DLIST_ADD(conn
->pending_trans
, state
);
9264 /* We need to send an interim response then receive the rest
9265 of the parameter/data bytes */
9266 reply_outbuf(req
, 0, 0);
9267 show_msg((char *)req
->outbuf
);
9268 END_PROFILE(SMBtrans2
);
9273 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
9274 SAFE_FREE(state
->data
);
9275 SAFE_FREE(state
->param
);
9277 END_PROFILE(SMBtrans2
);
9278 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
9282 /****************************************************************************
9283 Reply to a SMBtranss2
9284 ****************************************************************************/
9286 void reply_transs2(struct smb_request
*req
)
9288 connection_struct
*conn
= req
->conn
;
9289 unsigned int pcnt
,poff
,dcnt
,doff
,pdisp
,ddisp
;
9290 struct trans_state
*state
;
9292 START_PROFILE(SMBtranss2
);
9294 show_msg((const char *)req
->inbuf
);
9296 /* Windows clients expect all replies to
9297 a transact secondary (SMBtranss2 0x33)
9298 to have a command code of transact
9299 (SMBtrans2 0x32). See bug #8989
9300 and also [MS-CIFS] section 2.2.4.47.2
9303 req
->cmd
= SMBtrans2
;
9306 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
9307 END_PROFILE(SMBtranss2
);
9311 for (state
= conn
->pending_trans
; state
!= NULL
;
9312 state
= state
->next
) {
9313 if (state
->mid
== req
->mid
) {
9318 if ((state
== NULL
) || (state
->cmd
!= SMBtrans2
)) {
9319 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
9320 END_PROFILE(SMBtranss2
);
9324 /* Revise state->total_param and state->total_data in case they have
9325 changed downwards */
9327 if (SVAL(req
->vwv
+0, 0) < state
->total_param
)
9328 state
->total_param
= SVAL(req
->vwv
+0, 0);
9329 if (SVAL(req
->vwv
+1, 0) < state
->total_data
)
9330 state
->total_data
= SVAL(req
->vwv
+1, 0);
9332 pcnt
= SVAL(req
->vwv
+2, 0);
9333 poff
= SVAL(req
->vwv
+3, 0);
9334 pdisp
= SVAL(req
->vwv
+4, 0);
9336 dcnt
= SVAL(req
->vwv
+5, 0);
9337 doff
= SVAL(req
->vwv
+6, 0);
9338 ddisp
= SVAL(req
->vwv
+7, 0);
9340 state
->received_param
+= pcnt
;
9341 state
->received_data
+= dcnt
;
9343 if ((state
->received_data
> state
->total_data
) ||
9344 (state
->received_param
> state
->total_param
))
9348 if (trans_oob(state
->total_param
, pdisp
, pcnt
)
9349 || trans_oob(smb_len(req
->inbuf
), poff
, pcnt
)) {
9352 memcpy(state
->param
+pdisp
,smb_base(req
->inbuf
)+poff
,pcnt
);
9356 if (trans_oob(state
->total_data
, ddisp
, dcnt
)
9357 || trans_oob(smb_len(req
->inbuf
), doff
, dcnt
)) {
9360 memcpy(state
->data
+ddisp
, smb_base(req
->inbuf
)+doff
,dcnt
);
9363 if ((state
->received_param
< state
->total_param
) ||
9364 (state
->received_data
< state
->total_data
)) {
9365 END_PROFILE(SMBtranss2
);
9369 handle_trans2(conn
, req
, state
);
9371 DLIST_REMOVE(conn
->pending_trans
, state
);
9372 SAFE_FREE(state
->data
);
9373 SAFE_FREE(state
->param
);
9376 END_PROFILE(SMBtranss2
);
9381 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
9382 DLIST_REMOVE(conn
->pending_trans
, state
);
9383 SAFE_FREE(state
->data
);
9384 SAFE_FREE(state
->param
);
9386 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
9387 END_PROFILE(SMBtranss2
);