2 Unix SMB/CIFS implementation.
3 SMB transaction2 handling
4 Copyright (C) Jeremy Allison 1994-2007
5 Copyright (C) Stefan (metze) Metzmacher 2003
6 Copyright (C) Volker Lendecke 2005-2007
7 Copyright (C) Steve French 2005
8 Copyright (C) James Peach 2006-2007
10 Extensively modified by Andrew Tridgell, 1995
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 3 of the License, or
15 (at your option) any later version.
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with this program. If not, see <http://www.gnu.org/licenses/>.
27 #include "system/filesys.h"
29 #include "smbd/smbd.h"
30 #include "smbd/globals.h"
31 #include "../libcli/auth/libcli_auth.h"
32 #include "../librpc/gen_ndr/xattr.h"
33 #include "../librpc/gen_ndr/ndr_security.h"
34 #include "../librpc/gen_ndr/open_files.h"
35 #include "libcli/security/security.h"
38 #include "smbprofile.h"
39 #include "rpc_server/srv_pipe_hnd.h"
42 #define DIR_ENTRY_SAFETY_MARGIN 4096
44 static char *store_file_unix_basic(connection_struct
*conn
,
47 const SMB_STRUCT_STAT
*psbuf
);
49 static char *store_file_unix_basic_info2(connection_struct
*conn
,
52 const SMB_STRUCT_STAT
*psbuf
);
54 /********************************************************************
55 The canonical "check access" based on object handle or path function.
56 ********************************************************************/
58 NTSTATUS
check_access(connection_struct
*conn
,
60 const struct smb_filename
*smb_fname
,
64 if (!(fsp
->access_mask
& access_mask
)) {
65 return NT_STATUS_ACCESS_DENIED
;
68 NTSTATUS status
= smbd_check_access_rights(conn
,
71 if (!NT_STATUS_IS_OK(status
)) {
78 /********************************************************************
79 Roundup a value to the nearest allocation roundup size boundary.
80 Only do this for Windows clients.
81 ********************************************************************/
83 uint64_t smb_roundup(connection_struct
*conn
, uint64_t val
)
85 uint64_t rval
= lp_allocation_roundup_size(SNUM(conn
));
87 /* Only roundup for Windows clients. */
88 enum remote_arch_types ra_type
= get_remote_arch();
89 if (rval
&& (ra_type
!= RA_SAMBA
) && (ra_type
!= RA_CIFSFS
)) {
90 val
= SMB_ROUNDUP(val
,rval
);
95 /********************************************************************
96 Create a 64 bit FileIndex. If the file is on the same device as
97 the root of the share, just return the 64-bit inode. If it isn't,
98 mangle as we used to do.
99 ********************************************************************/
101 uint64_t get_FileIndex(connection_struct
*conn
, const SMB_STRUCT_STAT
*psbuf
)
104 if (conn
->base_share_dev
== psbuf
->st_ex_dev
) {
105 return (uint64_t)psbuf
->st_ex_ino
;
107 file_index
= ((psbuf
->st_ex_ino
) & UINT32_MAX
); /* FileIndexLow */
108 file_index
|= ((uint64_t)((psbuf
->st_ex_dev
) & UINT32_MAX
)) << 32; /* FileIndexHigh */
112 /****************************************************************************
113 Utility functions for dealing with extended attributes.
114 ****************************************************************************/
116 /****************************************************************************
117 Refuse to allow clients to overwrite our private xattrs.
118 ****************************************************************************/
120 static bool samba_private_attr_name(const char *unix_ea_name
)
122 static const char * const prohibited_ea_names
[] = {
123 SAMBA_POSIX_INHERITANCE_EA_NAME
,
124 SAMBA_XATTR_DOS_ATTRIB
,
132 for (i
= 0; prohibited_ea_names
[i
]; i
++) {
133 if (strequal( prohibited_ea_names
[i
], unix_ea_name
))
136 if (strncasecmp_m(unix_ea_name
, SAMBA_XATTR_DOSSTREAM_PREFIX
,
137 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX
)) == 0) {
143 /****************************************************************************
144 Get one EA value. Fill in a struct ea_struct.
145 ****************************************************************************/
147 NTSTATUS
get_ea_value(TALLOC_CTX
*mem_ctx
, connection_struct
*conn
,
148 files_struct
*fsp
, const char *fname
,
149 const char *ea_name
, struct ea_struct
*pea
)
151 /* Get the value of this xattr. Max size is 64k. */
152 size_t attr_size
= 256;
158 val
= talloc_realloc(mem_ctx
, val
, char, attr_size
);
160 return NT_STATUS_NO_MEMORY
;
163 if (fsp
&& fsp
->fh
->fd
!= -1) {
164 sizeret
= SMB_VFS_FGETXATTR(fsp
, ea_name
, val
, attr_size
);
166 sizeret
= SMB_VFS_GETXATTR(conn
, fname
, ea_name
, val
, attr_size
);
169 if (sizeret
== -1 && errno
== ERANGE
&& attr_size
!= 65536) {
175 return map_nt_error_from_unix(errno
);
178 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name
, (unsigned int)sizeret
));
179 dump_data(10, (uint8
*)val
, sizeret
);
182 if (strnequal(ea_name
, "user.", 5)) {
183 pea
->name
= talloc_strdup(mem_ctx
, &ea_name
[5]);
185 pea
->name
= talloc_strdup(mem_ctx
, ea_name
);
187 if (pea
->name
== NULL
) {
189 return NT_STATUS_NO_MEMORY
;
191 pea
->value
.data
= (unsigned char *)val
;
192 pea
->value
.length
= (size_t)sizeret
;
196 NTSTATUS
get_ea_names_from_file(TALLOC_CTX
*mem_ctx
, connection_struct
*conn
,
197 files_struct
*fsp
, const char *fname
,
198 char ***pnames
, size_t *pnum_names
)
200 /* Get a list of all xattrs. Max namesize is 64k. */
201 size_t ea_namelist_size
= 1024;
202 char *ea_namelist
= NULL
;
207 ssize_t sizeret
= -1;
209 if (!lp_ea_support(SNUM(conn
))) {
218 * TALLOC the result early to get the talloc hierarchy right.
221 names
= talloc_array(mem_ctx
, char *, 1);
223 DEBUG(0, ("talloc failed\n"));
224 return NT_STATUS_NO_MEMORY
;
227 while (ea_namelist_size
<= 65536) {
229 ea_namelist
= talloc_realloc(
230 names
, ea_namelist
, char, ea_namelist_size
);
231 if (ea_namelist
== NULL
) {
232 DEBUG(0, ("talloc failed\n"));
234 return NT_STATUS_NO_MEMORY
;
237 if (fsp
&& fsp
->fh
->fd
!= -1) {
238 sizeret
= SMB_VFS_FLISTXATTR(fsp
, ea_namelist
,
241 sizeret
= SMB_VFS_LISTXATTR(conn
, fname
, ea_namelist
,
245 if ((sizeret
== -1) && (errno
== ERANGE
)) {
246 ea_namelist_size
*= 2;
255 return map_nt_error_from_unix(errno
);
258 DEBUG(10, ("get_ea_list_from_file: ea_namelist size = %u\n",
259 (unsigned int)sizeret
));
271 * Ensure the result is 0-terminated
274 if (ea_namelist
[sizeret
-1] != '\0') {
276 return NT_STATUS_INTERNAL_ERROR
;
284 for (p
= ea_namelist
; p
- ea_namelist
< sizeret
; p
+= strlen(p
)+1) {
288 tmp
= talloc_realloc(mem_ctx
, names
, char *, num_names
);
290 DEBUG(0, ("talloc failed\n"));
292 return NT_STATUS_NO_MEMORY
;
298 for (p
= ea_namelist
; p
- ea_namelist
< sizeret
; p
+= strlen(p
)+1) {
299 names
[num_names
++] = p
;
307 *pnum_names
= num_names
;
311 /****************************************************************************
312 Return a linked list of the total EA's. Plus the total size
313 ****************************************************************************/
315 static NTSTATUS
get_ea_list_from_file_path(TALLOC_CTX
*mem_ctx
, connection_struct
*conn
, files_struct
*fsp
,
316 const char *fname
, size_t *pea_total_len
, struct ea_list
**ea_list
)
318 /* Get a list of all xattrs. Max namesize is 64k. */
321 struct ea_list
*ea_list_head
= NULL
;
326 status
= get_ea_names_from_file(talloc_tos(), conn
, fsp
, fname
,
329 if (!NT_STATUS_IS_OK(status
)) {
333 if (num_names
== 0) {
338 for (i
=0; i
<num_names
; i
++) {
339 struct ea_list
*listp
;
342 if (strnequal(names
[i
], "system.", 7)
343 || samba_private_attr_name(names
[i
]))
346 listp
= talloc(mem_ctx
, struct ea_list
);
348 return NT_STATUS_NO_MEMORY
;
351 status
= get_ea_value(mem_ctx
, conn
, fsp
,
355 if (!NT_STATUS_IS_OK(status
)) {
359 push_ascii_fstring(dos_ea_name
, listp
->ea
.name
);
362 4 + strlen(dos_ea_name
) + 1 + listp
->ea
.value
.length
;
364 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
365 "= %u\n", (unsigned int)*pea_total_len
, dos_ea_name
,
366 (unsigned int)listp
->ea
.value
.length
));
368 DLIST_ADD_END(ea_list_head
, listp
, struct ea_list
*);
372 /* Add on 4 for total length. */
373 if (*pea_total_len
) {
377 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
378 (unsigned int)*pea_total_len
));
380 *ea_list
= ea_list_head
;
384 static NTSTATUS
get_ea_list_from_file(TALLOC_CTX
*mem_ctx
, connection_struct
*conn
, files_struct
*fsp
,
385 const struct smb_filename
*smb_fname
, size_t *pea_total_len
, struct ea_list
**ea_list
)
390 if (!lp_ea_support(SNUM(conn
))) {
394 if (is_ntfs_stream_smb_fname(smb_fname
)) {
395 return NT_STATUS_INVALID_PARAMETER
;
398 return get_ea_list_from_file_path(mem_ctx
, conn
, fsp
, smb_fname
->base_name
, pea_total_len
, ea_list
);
401 /****************************************************************************
402 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
404 ****************************************************************************/
406 static unsigned int fill_ea_buffer(TALLOC_CTX
*mem_ctx
, char *pdata
, unsigned int total_data_size
,
407 connection_struct
*conn
, struct ea_list
*ea_list
)
409 unsigned int ret_data_size
= 4;
412 SMB_ASSERT(total_data_size
>= 4);
414 if (!lp_ea_support(SNUM(conn
))) {
419 for (p
= pdata
+ 4; ea_list
; ea_list
= ea_list
->next
) {
422 push_ascii_fstring(dos_ea_name
, ea_list
->ea
.name
);
423 dos_namelen
= strlen(dos_ea_name
);
424 if (dos_namelen
> 255 || dos_namelen
== 0) {
427 if (ea_list
->ea
.value
.length
> 65535) {
430 if (4 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
> total_data_size
) {
434 /* We know we have room. */
435 SCVAL(p
,0,ea_list
->ea
.flags
);
436 SCVAL(p
,1,dos_namelen
);
437 SSVAL(p
,2,ea_list
->ea
.value
.length
);
438 strlcpy(p
+4, dos_ea_name
, dos_namelen
+1);
439 memcpy( p
+ 4 + dos_namelen
+ 1, ea_list
->ea
.value
.data
, ea_list
->ea
.value
.length
);
441 total_data_size
-= 4 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
;
442 p
+= 4 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
;
445 ret_data_size
= PTR_DIFF(p
, pdata
);
446 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size
));
447 SIVAL(pdata
,0,ret_data_size
);
448 return ret_data_size
;
451 static NTSTATUS
fill_ea_chained_buffer(TALLOC_CTX
*mem_ctx
,
453 unsigned int total_data_size
,
454 unsigned int *ret_data_size
,
455 connection_struct
*conn
,
456 struct ea_list
*ea_list
)
458 uint8_t *p
= (uint8_t *)pdata
;
459 uint8_t *last_start
= NULL
;
463 if (!lp_ea_support(SNUM(conn
))) {
464 return NT_STATUS_NO_EAS_ON_FILE
;
467 for (; ea_list
; ea_list
= ea_list
->next
) {
473 SIVAL(last_start
, 0, PTR_DIFF(p
, last_start
));
477 push_ascii_fstring(dos_ea_name
, ea_list
->ea
.name
);
478 dos_namelen
= strlen(dos_ea_name
);
479 if (dos_namelen
> 255 || dos_namelen
== 0) {
480 return NT_STATUS_INTERNAL_ERROR
;
482 if (ea_list
->ea
.value
.length
> 65535) {
483 return NT_STATUS_INTERNAL_ERROR
;
486 this_size
= 0x08 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
;
489 size_t pad
= 4 - (this_size
% 4);
493 if (this_size
> total_data_size
) {
494 return NT_STATUS_INFO_LENGTH_MISMATCH
;
497 /* We know we have room. */
498 SIVAL(p
, 0x00, 0); /* next offset */
499 SCVAL(p
, 0x04, ea_list
->ea
.flags
);
500 SCVAL(p
, 0x05, dos_namelen
);
501 SSVAL(p
, 0x06, ea_list
->ea
.value
.length
);
502 strlcpy((char *)(p
+0x08), dos_ea_name
, dos_namelen
+1);
503 memcpy(p
+ 0x08 + dos_namelen
+ 1, ea_list
->ea
.value
.data
, ea_list
->ea
.value
.length
);
505 total_data_size
-= this_size
;
509 *ret_data_size
= PTR_DIFF(p
, pdata
);
510 DEBUG(10,("fill_ea_chained_buffer: data_size = %u\n", *ret_data_size
));
514 static unsigned int estimate_ea_size(connection_struct
*conn
, files_struct
*fsp
, const struct smb_filename
*smb_fname
)
516 size_t total_ea_len
= 0;
518 struct ea_list
*ea_list
;
520 if (!lp_ea_support(SNUM(conn
))) {
523 mem_ctx
= talloc_stackframe();
525 /* If this is a stream fsp, then we need to instead find the
526 * estimated ea len from the main file, not the stream
527 * (streams cannot have EAs), but the estimate isn't just 0 in
529 if (is_ntfs_stream_smb_fname(smb_fname
)) {
532 (void)get_ea_list_from_file_path(mem_ctx
, conn
, fsp
, smb_fname
->base_name
, &total_ea_len
, &ea_list
);
533 TALLOC_FREE(mem_ctx
);
537 /****************************************************************************
538 Ensure the EA name is case insensitive by matching any existing EA name.
539 ****************************************************************************/
541 static void canonicalize_ea_name(connection_struct
*conn
, files_struct
*fsp
, const char *fname
, fstring unix_ea_name
)
544 TALLOC_CTX
*mem_ctx
= talloc_tos();
545 struct ea_list
*ea_list
;
546 NTSTATUS status
= get_ea_list_from_file_path(mem_ctx
, conn
, fsp
, fname
, &total_ea_len
, &ea_list
);
547 if (!NT_STATUS_IS_OK(status
)) {
551 for (; ea_list
; ea_list
= ea_list
->next
) {
552 if (strequal(&unix_ea_name
[5], ea_list
->ea
.name
)) {
553 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
554 &unix_ea_name
[5], ea_list
->ea
.name
));
555 strlcpy(&unix_ea_name
[5], ea_list
->ea
.name
, sizeof(fstring
)-5);
561 /****************************************************************************
562 Set or delete an extended attribute.
563 ****************************************************************************/
565 NTSTATUS
set_ea(connection_struct
*conn
, files_struct
*fsp
,
566 const struct smb_filename
*smb_fname
, struct ea_list
*ea_list
)
571 if (!lp_ea_support(SNUM(conn
))) {
572 return NT_STATUS_EAS_NOT_SUPPORTED
;
575 status
= check_access(conn
, fsp
, smb_fname
, FILE_WRITE_EA
);
576 if (!NT_STATUS_IS_OK(status
)) {
580 /* Setting EAs on streams isn't supported. */
581 if (is_ntfs_stream_smb_fname(smb_fname
)) {
582 return NT_STATUS_INVALID_PARAMETER
;
585 fname
= smb_fname
->base_name
;
587 for (;ea_list
; ea_list
= ea_list
->next
) {
589 fstring unix_ea_name
;
591 fstrcpy(unix_ea_name
, "user."); /* All EA's must start with user. */
592 fstrcat(unix_ea_name
, ea_list
->ea
.name
);
594 canonicalize_ea_name(conn
, fsp
, fname
, unix_ea_name
);
596 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name
, (unsigned int)ea_list
->ea
.value
.length
));
598 if (samba_private_attr_name(unix_ea_name
)) {
599 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name
));
600 return NT_STATUS_ACCESS_DENIED
;
603 if (ea_list
->ea
.value
.length
== 0) {
604 /* Remove the attribute. */
605 if (fsp
&& (fsp
->fh
->fd
!= -1)) {
606 DEBUG(10,("set_ea: deleting ea name %s on "
607 "file %s by file descriptor.\n",
608 unix_ea_name
, fsp_str_dbg(fsp
)));
609 ret
= SMB_VFS_FREMOVEXATTR(fsp
, unix_ea_name
);
611 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
612 unix_ea_name
, fname
));
613 ret
= SMB_VFS_REMOVEXATTR(conn
, fname
, unix_ea_name
);
616 /* Removing a non existent attribute always succeeds. */
617 if (ret
== -1 && errno
== ENOATTR
) {
618 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
624 if (fsp
&& (fsp
->fh
->fd
!= -1)) {
625 DEBUG(10,("set_ea: setting ea name %s on file "
626 "%s by file descriptor.\n",
627 unix_ea_name
, fsp_str_dbg(fsp
)));
628 ret
= SMB_VFS_FSETXATTR(fsp
, unix_ea_name
,
629 ea_list
->ea
.value
.data
, ea_list
->ea
.value
.length
, 0);
631 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
632 unix_ea_name
, fname
));
633 ret
= SMB_VFS_SETXATTR(conn
, fname
, unix_ea_name
,
634 ea_list
->ea
.value
.data
, ea_list
->ea
.value
.length
, 0);
640 if (errno
== ENOTSUP
) {
641 return NT_STATUS_EAS_NOT_SUPPORTED
;
644 return map_nt_error_from_unix(errno
);
650 /****************************************************************************
651 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
652 ****************************************************************************/
654 static struct ea_list
*read_ea_name_list(TALLOC_CTX
*ctx
, const char *pdata
, size_t data_size
)
656 struct ea_list
*ea_list_head
= NULL
;
657 size_t converted_size
, offset
= 0;
659 while (offset
+ 2 < data_size
) {
660 struct ea_list
*eal
= talloc_zero(ctx
, struct ea_list
);
661 unsigned int namelen
= CVAL(pdata
,offset
);
663 offset
++; /* Go past the namelen byte. */
665 /* integer wrap paranioa. */
666 if ((offset
+ namelen
< offset
) || (offset
+ namelen
< namelen
) ||
667 (offset
> data_size
) || (namelen
> data_size
) ||
668 (offset
+ namelen
>= data_size
)) {
671 /* Ensure the name is null terminated. */
672 if (pdata
[offset
+ namelen
] != '\0') {
675 if (!pull_ascii_talloc(ctx
, &eal
->ea
.name
, &pdata
[offset
],
677 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
678 "failed: %s", strerror(errno
)));
684 offset
+= (namelen
+ 1); /* Go past the name + terminating zero. */
685 DLIST_ADD_END(ea_list_head
, eal
, struct ea_list
*);
686 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal
->ea
.name
));
692 /****************************************************************************
693 Read one EA list entry from the buffer.
694 ****************************************************************************/
696 struct ea_list
*read_ea_list_entry(TALLOC_CTX
*ctx
, const char *pdata
, size_t data_size
, size_t *pbytes_used
)
698 struct ea_list
*eal
= talloc_zero(ctx
, struct ea_list
);
700 unsigned int namelen
;
701 size_t converted_size
;
711 eal
->ea
.flags
= CVAL(pdata
,0);
712 namelen
= CVAL(pdata
,1);
713 val_len
= SVAL(pdata
,2);
715 if (4 + namelen
+ 1 + val_len
> data_size
) {
719 /* Ensure the name is null terminated. */
720 if (pdata
[namelen
+ 4] != '\0') {
723 if (!pull_ascii_talloc(ctx
, &eal
->ea
.name
, pdata
+ 4, &converted_size
)) {
724 DEBUG(0,("read_ea_list_entry: pull_ascii_talloc failed: %s",
731 eal
->ea
.value
= data_blob_talloc(eal
, NULL
, (size_t)val_len
+ 1);
732 if (!eal
->ea
.value
.data
) {
736 memcpy(eal
->ea
.value
.data
, pdata
+ 4 + namelen
+ 1, val_len
);
738 /* Ensure we're null terminated just in case we print the value. */
739 eal
->ea
.value
.data
[val_len
] = '\0';
740 /* But don't count the null. */
741 eal
->ea
.value
.length
--;
744 *pbytes_used
= 4 + namelen
+ 1 + val_len
;
747 DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal
->ea
.name
));
748 dump_data(10, eal
->ea
.value
.data
, eal
->ea
.value
.length
);
753 /****************************************************************************
754 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
755 ****************************************************************************/
757 static struct ea_list
*read_ea_list(TALLOC_CTX
*ctx
, const char *pdata
, size_t data_size
)
759 struct ea_list
*ea_list_head
= NULL
;
761 size_t bytes_used
= 0;
763 while (offset
< data_size
) {
764 struct ea_list
*eal
= read_ea_list_entry(ctx
, pdata
+ offset
, data_size
- offset
, &bytes_used
);
770 DLIST_ADD_END(ea_list_head
, eal
, struct ea_list
*);
771 offset
+= bytes_used
;
777 /****************************************************************************
778 Count the total EA size needed.
779 ****************************************************************************/
781 static size_t ea_list_size(struct ea_list
*ealist
)
784 struct ea_list
*listp
;
787 for (listp
= ealist
; listp
; listp
= listp
->next
) {
788 push_ascii_fstring(dos_ea_name
, listp
->ea
.name
);
789 ret
+= 4 + strlen(dos_ea_name
) + 1 + listp
->ea
.value
.length
;
791 /* Add on 4 for total length. */
799 /****************************************************************************
800 Return a union of EA's from a file list and a list of names.
801 The TALLOC context for the two lists *MUST* be identical as we steal
802 memory from one list to add to another. JRA.
803 ****************************************************************************/
805 static struct ea_list
*ea_list_union(struct ea_list
*name_list
, struct ea_list
*file_list
, size_t *total_ea_len
)
807 struct ea_list
*nlistp
, *flistp
;
809 for (nlistp
= name_list
; nlistp
; nlistp
= nlistp
->next
) {
810 for (flistp
= file_list
; flistp
; flistp
= flistp
->next
) {
811 if (strequal(nlistp
->ea
.name
, flistp
->ea
.name
)) {
817 /* Copy the data from this entry. */
818 nlistp
->ea
.flags
= flistp
->ea
.flags
;
819 nlistp
->ea
.value
= flistp
->ea
.value
;
822 nlistp
->ea
.flags
= 0;
823 ZERO_STRUCT(nlistp
->ea
.value
);
827 *total_ea_len
= ea_list_size(name_list
);
831 /****************************************************************************
832 Send the required number of replies back.
833 We assume all fields other than the data fields are
834 set correctly for the type of call.
835 HACK ! Always assumes smb_setup field is zero.
836 ****************************************************************************/
838 void send_trans2_replies(connection_struct
*conn
,
839 struct smb_request
*req
,
846 /* As we are using a protocol > LANMAN1 then the max_send
847 variable must have been set in the sessetupX call.
848 This takes precedence over the max_xmit field in the
849 global struct. These different max_xmit variables should
850 be merged as this is now too confusing */
852 int data_to_send
= datasize
;
853 int params_to_send
= paramsize
;
855 const char *pp
= params
;
856 const char *pd
= pdata
;
857 int params_sent_thistime
, data_sent_thistime
, total_sent_thistime
;
858 int alignment_offset
= 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
859 int data_alignment_offset
= 0;
860 bool overflow
= False
;
861 struct smbd_server_connection
*sconn
= req
->sconn
;
862 int max_send
= sconn
->smb1
.sessions
.max_send
;
864 /* Modify the data_to_send and datasize and set the error if
865 we're trying to send more than max_data_bytes. We still send
866 the part of the packet(s) that fit. Strange, but needed
869 if (max_data_bytes
> 0 && datasize
> max_data_bytes
) {
870 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
871 max_data_bytes
, datasize
));
872 datasize
= data_to_send
= max_data_bytes
;
876 /* If there genuinely are no parameters or data to send just send the empty packet */
878 if(params_to_send
== 0 && data_to_send
== 0) {
879 reply_outbuf(req
, 10, 0);
880 show_msg((char *)req
->outbuf
);
881 if (!srv_send_smb(sconn
,
884 IS_CONN_ENCRYPTED(conn
),
886 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
888 TALLOC_FREE(req
->outbuf
);
892 /* When sending params and data ensure that both are nicely aligned */
893 /* Only do this alignment when there is also data to send - else
894 can cause NT redirector problems. */
896 if (((params_to_send
% 4) != 0) && (data_to_send
!= 0))
897 data_alignment_offset
= 4 - (params_to_send
% 4);
899 /* Space is bufsize minus Netbios over TCP header minus SMB header */
900 /* The alignment_offset is to align the param bytes on an even byte
901 boundary. NT 4.0 Beta needs this to work correctly. */
903 useable_space
= max_send
- (smb_size
906 + data_alignment_offset
);
908 if (useable_space
< 0) {
909 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
910 "= %d!!!", useable_space
));
911 exit_server_cleanly("send_trans2_replies: Not enough space");
914 while (params_to_send
|| data_to_send
) {
915 /* Calculate whether we will totally or partially fill this packet */
917 total_sent_thistime
= params_to_send
+ data_to_send
;
919 /* We can never send more than useable_space */
921 * Note that 'useable_space' does not include the alignment offsets,
922 * but we must include the alignment offsets in the calculation of
923 * the length of the data we send over the wire, as the alignment offsets
924 * are sent here. Fix from Marc_Jacobsen@hp.com.
927 total_sent_thistime
= MIN(total_sent_thistime
, useable_space
);
929 reply_outbuf(req
, 10, total_sent_thistime
+ alignment_offset
930 + data_alignment_offset
);
932 /* Set total params and data to be sent */
933 SSVAL(req
->outbuf
,smb_tprcnt
,paramsize
);
934 SSVAL(req
->outbuf
,smb_tdrcnt
,datasize
);
936 /* Calculate how many parameters and data we can fit into
937 * this packet. Parameters get precedence
940 params_sent_thistime
= MIN(params_to_send
,useable_space
);
941 data_sent_thistime
= useable_space
- params_sent_thistime
;
942 data_sent_thistime
= MIN(data_sent_thistime
,data_to_send
);
944 SSVAL(req
->outbuf
,smb_prcnt
, params_sent_thistime
);
946 /* smb_proff is the offset from the start of the SMB header to the
947 parameter bytes, however the first 4 bytes of outbuf are
948 the Netbios over TCP header. Thus use smb_base() to subtract
949 them from the calculation */
951 SSVAL(req
->outbuf
,smb_proff
,
952 ((smb_buf(req
->outbuf
)+alignment_offset
)
953 - smb_base(req
->outbuf
)));
955 if(params_sent_thistime
== 0)
956 SSVAL(req
->outbuf
,smb_prdisp
,0);
958 /* Absolute displacement of param bytes sent in this packet */
959 SSVAL(req
->outbuf
,smb_prdisp
,pp
- params
);
961 SSVAL(req
->outbuf
,smb_drcnt
, data_sent_thistime
);
962 if(data_sent_thistime
== 0) {
963 SSVAL(req
->outbuf
,smb_droff
,0);
964 SSVAL(req
->outbuf
,smb_drdisp
, 0);
966 /* The offset of the data bytes is the offset of the
967 parameter bytes plus the number of parameters being sent this time */
968 SSVAL(req
->outbuf
, smb_droff
,
969 ((smb_buf(req
->outbuf
)+alignment_offset
)
970 - smb_base(req
->outbuf
))
971 + params_sent_thistime
+ data_alignment_offset
);
972 SSVAL(req
->outbuf
,smb_drdisp
, pd
- pdata
);
975 /* Initialize the padding for alignment */
977 if (alignment_offset
!= 0) {
978 memset(smb_buf(req
->outbuf
), 0, alignment_offset
);
981 /* Copy the param bytes into the packet */
983 if(params_sent_thistime
) {
984 memcpy((smb_buf(req
->outbuf
)+alignment_offset
), pp
,
985 params_sent_thistime
);
988 /* Copy in the data bytes */
989 if(data_sent_thistime
) {
990 if (data_alignment_offset
!= 0) {
991 memset((smb_buf(req
->outbuf
)+alignment_offset
+
992 params_sent_thistime
), 0,
993 data_alignment_offset
);
995 memcpy(smb_buf(req
->outbuf
)+alignment_offset
996 +params_sent_thistime
+data_alignment_offset
,
997 pd
,data_sent_thistime
);
1000 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
1001 params_sent_thistime
, data_sent_thistime
, useable_space
));
1002 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
1003 params_to_send
, data_to_send
, paramsize
, datasize
));
1006 error_packet_set((char *)req
->outbuf
,
1007 ERRDOS
,ERRbufferoverflow
,
1008 STATUS_BUFFER_OVERFLOW
,
1012 /* Send the packet */
1013 show_msg((char *)req
->outbuf
);
1014 if (!srv_send_smb(sconn
,
1015 (char *)req
->outbuf
,
1016 true, req
->seqnum
+1,
1017 IS_CONN_ENCRYPTED(conn
),
1019 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
1021 TALLOC_FREE(req
->outbuf
);
1023 pp
+= params_sent_thistime
;
1024 pd
+= data_sent_thistime
;
1026 params_to_send
-= params_sent_thistime
;
1027 data_to_send
-= data_sent_thistime
;
1030 if(params_to_send
< 0 || data_to_send
< 0) {
1031 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
1032 params_to_send
, data_to_send
));
1040 /****************************************************************************
1041 Reply to a TRANSACT2_OPEN.
1042 ****************************************************************************/
1044 static void call_trans2open(connection_struct
*conn
,
1045 struct smb_request
*req
,
1046 char **pparams
, int total_params
,
1047 char **ppdata
, int total_data
,
1048 unsigned int max_data_bytes
)
1050 struct smb_filename
*smb_fname
= NULL
;
1051 char *params
= *pparams
;
1052 char *pdata
= *ppdata
;
1055 bool oplock_request
;
1057 bool return_additional_info
;
1066 int fattr
=0,mtime
=0;
1067 SMB_INO_T inode
= 0;
1070 struct ea_list
*ea_list
= NULL
;
1075 uint32 create_disposition
;
1076 uint32 create_options
= 0;
1077 uint32_t private_flags
= 0;
1078 TALLOC_CTX
*ctx
= talloc_tos();
1081 * Ensure we have enough parameters to perform the operation.
1084 if (total_params
< 29) {
1085 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1089 flags
= SVAL(params
, 0);
1090 deny_mode
= SVAL(params
, 2);
1091 open_attr
= SVAL(params
,6);
1092 oplock_request
= (flags
& REQUEST_OPLOCK
) ? EXCLUSIVE_OPLOCK
: 0;
1093 if (oplock_request
) {
1094 oplock_request
|= (flags
& REQUEST_BATCH_OPLOCK
) ? BATCH_OPLOCK
: 0;
1098 return_additional_info
= BITSETW(params
,0);
1099 open_sattr
= SVAL(params
, 4);
1100 open_time
= make_unix_date3(params
+8);
1102 open_ofun
= SVAL(params
,12);
1103 open_size
= IVAL(params
,14);
1104 pname
= ¶ms
[28];
1107 reply_nterror(req
, NT_STATUS_NETWORK_ACCESS_DENIED
);
1111 srvstr_get_path(ctx
, params
, req
->flags2
, &fname
, pname
,
1112 total_params
- 28, STR_TERMINATE
,
1114 if (!NT_STATUS_IS_OK(status
)) {
1115 reply_nterror(req
, status
);
1119 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
1120 fname
, (unsigned int)deny_mode
, (unsigned int)open_attr
,
1121 (unsigned int)open_ofun
, open_size
));
1123 status
= filename_convert(ctx
,
1125 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
1130 if (!NT_STATUS_IS_OK(status
)) {
1131 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
1132 reply_botherror(req
,
1133 NT_STATUS_PATH_NOT_COVERED
,
1134 ERRSRV
, ERRbadpath
);
1137 reply_nterror(req
, status
);
1141 if (open_ofun
== 0) {
1142 reply_nterror(req
, NT_STATUS_OBJECT_NAME_COLLISION
);
1146 if (!map_open_params_to_ntcreate(smb_fname
->base_name
, deny_mode
,
1148 &access_mask
, &share_mode
,
1149 &create_disposition
,
1152 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
1156 /* Any data in this call is an EA list. */
1157 if (total_data
&& (total_data
!= 4)) {
1158 if (total_data
< 10) {
1159 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1163 if (IVAL(pdata
,0) > total_data
) {
1164 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
1165 IVAL(pdata
,0), (unsigned int)total_data
));
1166 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1170 ea_list
= read_ea_list(talloc_tos(), pdata
+ 4,
1173 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1177 if (!lp_ea_support(SNUM(conn
))) {
1178 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
1183 status
= SMB_VFS_CREATE_FILE(
1186 0, /* root_dir_fid */
1187 smb_fname
, /* fname */
1188 access_mask
, /* access_mask */
1189 share_mode
, /* share_access */
1190 create_disposition
, /* create_disposition*/
1191 create_options
, /* create_options */
1192 open_attr
, /* file_attributes */
1193 oplock_request
, /* oplock_request */
1194 open_size
, /* allocation_size */
1197 ea_list
, /* ea_list */
1199 &smb_action
); /* psbuf */
1201 if (!NT_STATUS_IS_OK(status
)) {
1202 if (open_was_deferred(req
->sconn
, req
->mid
)) {
1203 /* We have re-scheduled this call. */
1206 reply_openerror(req
, status
);
1210 size
= get_file_size_stat(&smb_fname
->st
);
1211 fattr
= dos_mode(conn
, smb_fname
);
1212 mtime
= convert_timespec_to_time_t(smb_fname
->st
.st_ex_mtime
);
1213 inode
= smb_fname
->st
.st_ex_ino
;
1214 if (fattr
& FILE_ATTRIBUTE_DIRECTORY
) {
1215 close_file(req
, fsp
, ERROR_CLOSE
);
1216 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
1220 /* Realloc the size of parameters and data we will return */
1221 *pparams
= (char *)SMB_REALLOC(*pparams
, 30);
1222 if(*pparams
== NULL
) {
1223 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1228 SSVAL(params
,0,fsp
->fnum
);
1229 SSVAL(params
,2,fattr
);
1230 srv_put_dos_date2(params
,4, mtime
);
1231 SIVAL(params
,8, (uint32
)size
);
1232 SSVAL(params
,12,deny_mode
);
1233 SSVAL(params
,14,0); /* open_type - file or directory. */
1234 SSVAL(params
,16,0); /* open_state - only valid for IPC device. */
1236 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
1237 smb_action
|= EXTENDED_OPLOCK_GRANTED
;
1240 SSVAL(params
,18,smb_action
);
1243 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1245 SIVAL(params
,20,inode
);
1246 SSVAL(params
,24,0); /* Padding. */
1248 uint32 ea_size
= estimate_ea_size(conn
, fsp
,
1250 SIVAL(params
, 26, ea_size
);
1252 SIVAL(params
, 26, 0);
1255 /* Send the required number of replies */
1256 send_trans2_replies(conn
, req
, params
, 30, *ppdata
, 0, max_data_bytes
);
1258 TALLOC_FREE(smb_fname
);
1261 /*********************************************************
1262 Routine to check if a given string matches exactly.
1263 as a special case a mask of "." does NOT match. That
1264 is required for correct wildcard semantics
1265 Case can be significant or not.
1266 **********************************************************/
1268 static bool exact_match(bool has_wild
,
1269 bool case_sensitive
,
1273 if (mask
[0] == '.' && mask
[1] == 0) {
1281 if (case_sensitive
) {
1282 return strcmp(str
,mask
)==0;
1284 return strcasecmp_m(str
,mask
) == 0;
1288 /****************************************************************************
1289 Return the filetype for UNIX extensions.
1290 ****************************************************************************/
1292 static uint32
unix_filetype(mode_t mode
)
1295 return UNIX_TYPE_FILE
;
1296 else if(S_ISDIR(mode
))
1297 return UNIX_TYPE_DIR
;
1299 else if(S_ISLNK(mode
))
1300 return UNIX_TYPE_SYMLINK
;
1303 else if(S_ISCHR(mode
))
1304 return UNIX_TYPE_CHARDEV
;
1307 else if(S_ISBLK(mode
))
1308 return UNIX_TYPE_BLKDEV
;
1311 else if(S_ISFIFO(mode
))
1312 return UNIX_TYPE_FIFO
;
1315 else if(S_ISSOCK(mode
))
1316 return UNIX_TYPE_SOCKET
;
1319 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode
));
1320 return UNIX_TYPE_UNKNOWN
;
1323 /****************************************************************************
1324 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1325 ****************************************************************************/
1327 enum perm_type
{ PERM_NEW_FILE
, PERM_NEW_DIR
, PERM_EXISTING_FILE
, PERM_EXISTING_DIR
};
1329 static NTSTATUS
unix_perms_from_wire( connection_struct
*conn
,
1330 const SMB_STRUCT_STAT
*psbuf
,
1332 enum perm_type ptype
,
1337 if (perms
== SMB_MODE_NO_CHANGE
) {
1338 if (!VALID_STAT(*psbuf
)) {
1339 return NT_STATUS_INVALID_PARAMETER
;
1341 *ret_perms
= psbuf
->st_ex_mode
;
1342 return NT_STATUS_OK
;
1346 ret
|= ((perms
& UNIX_X_OTH
) ? S_IXOTH
: 0);
1347 ret
|= ((perms
& UNIX_W_OTH
) ? S_IWOTH
: 0);
1348 ret
|= ((perms
& UNIX_R_OTH
) ? S_IROTH
: 0);
1349 ret
|= ((perms
& UNIX_X_GRP
) ? S_IXGRP
: 0);
1350 ret
|= ((perms
& UNIX_W_GRP
) ? S_IWGRP
: 0);
1351 ret
|= ((perms
& UNIX_R_GRP
) ? S_IRGRP
: 0);
1352 ret
|= ((perms
& UNIX_X_USR
) ? S_IXUSR
: 0);
1353 ret
|= ((perms
& UNIX_W_USR
) ? S_IWUSR
: 0);
1354 ret
|= ((perms
& UNIX_R_USR
) ? S_IRUSR
: 0);
1356 ret
|= ((perms
& UNIX_STICKY
) ? S_ISVTX
: 0);
1359 ret
|= ((perms
& UNIX_SET_GID
) ? S_ISGID
: 0);
1362 ret
|= ((perms
& UNIX_SET_UID
) ? S_ISUID
: 0);
1367 /* Apply mode mask */
1368 ret
&= lp_create_mask(SNUM(conn
));
1369 /* Add in force bits */
1370 ret
|= lp_force_create_mode(SNUM(conn
));
1373 ret
&= lp_dir_mask(SNUM(conn
));
1374 /* Add in force bits */
1375 ret
|= lp_force_dir_mode(SNUM(conn
));
1377 case PERM_EXISTING_FILE
:
1378 /* Apply mode mask */
1379 ret
&= lp_security_mask(SNUM(conn
));
1380 /* Add in force bits */
1381 ret
|= lp_force_security_mode(SNUM(conn
));
1383 case PERM_EXISTING_DIR
:
1384 /* Apply mode mask */
1385 ret
&= lp_dir_security_mask(SNUM(conn
));
1386 /* Add in force bits */
1387 ret
|= lp_force_dir_security_mode(SNUM(conn
));
1392 return NT_STATUS_OK
;
1395 /****************************************************************************
1396 Needed to show the msdfs symlinks as directories. Modifies psbuf
1397 to be a directory if it's a msdfs link.
1398 ****************************************************************************/
1400 static bool check_msdfs_link(connection_struct
*conn
,
1401 const char *pathname
,
1402 SMB_STRUCT_STAT
*psbuf
)
1404 int saved_errno
= errno
;
1405 if(lp_host_msdfs() &&
1406 lp_msdfs_root(SNUM(conn
)) &&
1407 is_msdfs_link(conn
, pathname
, psbuf
)) {
1409 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1412 psbuf
->st_ex_mode
= (psbuf
->st_ex_mode
& 0xFFF) | S_IFDIR
;
1413 errno
= saved_errno
;
1416 errno
= saved_errno
;
1421 /****************************************************************************
1422 Get a level dependent lanman2 dir entry.
1423 ****************************************************************************/
1425 struct smbd_dirptr_lanman2_state
{
1426 connection_struct
*conn
;
1427 uint32_t info_level
;
1428 bool check_mangled_names
;
1430 bool got_exact_match
;
1433 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX
*ctx
,
1439 struct smbd_dirptr_lanman2_state
*state
=
1440 (struct smbd_dirptr_lanman2_state
*)private_data
;
1442 char mangled_name
[13]; /* mangled 8.3 name. */
1446 /* Mangle fname if it's an illegal name. */
1447 if (mangle_must_mangle(dname
, state
->conn
->params
)) {
1448 ok
= name_to_8_3(dname
, mangled_name
,
1449 true, state
->conn
->params
);
1453 fname
= mangled_name
;
1458 got_match
= exact_match(state
->has_wild
,
1459 state
->conn
->case_sensitive
,
1461 state
->got_exact_match
= got_match
;
1463 got_match
= mask_match(fname
, mask
,
1464 state
->conn
->case_sensitive
);
1467 if(!got_match
&& state
->check_mangled_names
&&
1468 !mangle_is_8_3(fname
, false, state
->conn
->params
)) {
1470 * It turns out that NT matches wildcards against
1471 * both long *and* short names. This may explain some
1472 * of the wildcard wierdness from old DOS clients
1473 * that some people have been seeing.... JRA.
1475 /* Force the mangling into 8.3. */
1476 ok
= name_to_8_3(fname
, mangled_name
,
1477 false, state
->conn
->params
);
1482 got_match
= exact_match(state
->has_wild
,
1483 state
->conn
->case_sensitive
,
1484 mangled_name
, mask
);
1485 state
->got_exact_match
= got_match
;
1487 got_match
= mask_match(mangled_name
, mask
,
1488 state
->conn
->case_sensitive
);
1496 *_fname
= talloc_strdup(ctx
, fname
);
1497 if (*_fname
== NULL
) {
1504 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX
*ctx
,
1506 struct smb_filename
*smb_fname
,
1509 struct smbd_dirptr_lanman2_state
*state
=
1510 (struct smbd_dirptr_lanman2_state
*)private_data
;
1511 bool ms_dfs_link
= false;
1514 if (INFO_LEVEL_IS_UNIX(state
->info_level
)) {
1515 if (SMB_VFS_LSTAT(state
->conn
, smb_fname
) != 0) {
1516 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1517 "Couldn't lstat [%s] (%s)\n",
1518 smb_fname_str_dbg(smb_fname
),
1522 } else if (!VALID_STAT(smb_fname
->st
) &&
1523 SMB_VFS_STAT(state
->conn
, smb_fname
) != 0) {
1524 /* Needed to show the msdfs symlinks as
1527 ms_dfs_link
= check_msdfs_link(state
->conn
,
1528 smb_fname
->base_name
,
1531 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1532 "Couldn't stat [%s] (%s)\n",
1533 smb_fname_str_dbg(smb_fname
),
1540 mode
= dos_mode_msdfs(state
->conn
, smb_fname
);
1542 mode
= dos_mode(state
->conn
, smb_fname
);
1549 static bool smbd_marshall_dir_entry(TALLOC_CTX
*ctx
,
1550 connection_struct
*conn
,
1552 uint32_t info_level
,
1553 struct ea_list
*name_list
,
1554 bool check_mangled_names
,
1555 bool requires_resume_key
,
1558 const struct smb_filename
*smb_fname
,
1559 int space_remaining
,
1566 uint64_t *last_entry_off
)
1568 char *p
, *q
, *pdata
= *ppdata
;
1570 uint64_t file_size
= 0;
1571 uint64_t allocation_size
= 0;
1572 uint64_t file_index
= 0;
1574 struct timespec mdate_ts
, adate_ts
, cdate_ts
, create_date_ts
;
1575 time_t mdate
= (time_t)0, adate
= (time_t)0, create_date
= (time_t)0;
1577 char *last_entry_ptr
;
1582 *out_of_space
= false;
1584 ZERO_STRUCT(mdate_ts
);
1585 ZERO_STRUCT(adate_ts
);
1586 ZERO_STRUCT(create_date_ts
);
1587 ZERO_STRUCT(cdate_ts
);
1589 if (!(mode
& FILE_ATTRIBUTE_DIRECTORY
)) {
1590 file_size
= get_file_size_stat(&smb_fname
->st
);
1592 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
, NULL
, &smb_fname
->st
);
1594 file_index
= get_FileIndex(conn
, &smb_fname
->st
);
1596 mdate_ts
= smb_fname
->st
.st_ex_mtime
;
1597 adate_ts
= smb_fname
->st
.st_ex_atime
;
1598 create_date_ts
= get_create_timespec(conn
, NULL
, smb_fname
);
1599 cdate_ts
= get_change_timespec(conn
, NULL
, smb_fname
);
1601 if (lp_dos_filetime_resolution(SNUM(conn
))) {
1602 dos_filetime_timespec(&create_date_ts
);
1603 dos_filetime_timespec(&mdate_ts
);
1604 dos_filetime_timespec(&adate_ts
);
1605 dos_filetime_timespec(&cdate_ts
);
1608 create_date
= convert_timespec_to_time_t(create_date_ts
);
1609 mdate
= convert_timespec_to_time_t(mdate_ts
);
1610 adate
= convert_timespec_to_time_t(adate_ts
);
1612 /* align the record */
1613 SMB_ASSERT(align
>= 1);
1615 off
= (int)PTR_DIFF(pdata
, base_data
);
1616 pad
= (off
+ (align
-1)) & ~(align
-1);
1619 if (pad
&& pad
> space_remaining
) {
1620 *out_of_space
= true;
1621 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1622 "for padding (wanted %u, had %d)\n",
1625 return false; /* Not finished - just out of space */
1629 /* initialize padding to 0 */
1631 memset(pdata
, 0, pad
);
1633 space_remaining
-= pad
;
1635 DEBUG(10,("smbd_marshall_dir_entry: space_remaining = %d\n",
1645 switch (info_level
) {
1646 case SMB_FIND_INFO_STANDARD
:
1647 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1648 if(requires_resume_key
) {
1652 srv_put_dos_date2(p
,0,create_date
);
1653 srv_put_dos_date2(p
,4,adate
);
1654 srv_put_dos_date2(p
,8,mdate
);
1655 SIVAL(p
,12,(uint32
)file_size
);
1656 SIVAL(p
,16,(uint32
)allocation_size
);
1660 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1661 p
+= ucs2_align(base_data
, p
, 0);
1663 len
= srvstr_push(base_data
, flags2
, p
,
1664 fname
, PTR_DIFF(end_data
, p
),
1666 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1668 SCVAL(nameptr
, -1, len
- 2);
1670 SCVAL(nameptr
, -1, 0);
1674 SCVAL(nameptr
, -1, len
- 1);
1676 SCVAL(nameptr
, -1, 0);
1682 case SMB_FIND_EA_SIZE
:
1683 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
1684 if (requires_resume_key
) {
1688 srv_put_dos_date2(p
,0,create_date
);
1689 srv_put_dos_date2(p
,4,adate
);
1690 srv_put_dos_date2(p
,8,mdate
);
1691 SIVAL(p
,12,(uint32
)file_size
);
1692 SIVAL(p
,16,(uint32
)allocation_size
);
1695 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
1697 SIVAL(p
,22,ea_size
); /* Extended attributes */
1701 len
= srvstr_push(base_data
, flags2
,
1702 p
, fname
, PTR_DIFF(end_data
, p
),
1703 STR_TERMINATE
| STR_NOALIGN
);
1704 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1717 SCVAL(nameptr
,0,len
);
1719 SCVAL(p
,0,0); p
+= 1; /* Extra zero byte ? - why.. */
1722 case SMB_FIND_EA_LIST
:
1724 struct ea_list
*file_list
= NULL
;
1728 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
1732 if (requires_resume_key
) {
1736 srv_put_dos_date2(p
,0,create_date
);
1737 srv_put_dos_date2(p
,4,adate
);
1738 srv_put_dos_date2(p
,8,mdate
);
1739 SIVAL(p
,12,(uint32
)file_size
);
1740 SIVAL(p
,16,(uint32
)allocation_size
);
1742 p
+= 22; /* p now points to the EA area. */
1744 status
= get_ea_list_from_file(ctx
, conn
, NULL
,
1746 &ea_len
, &file_list
);
1747 if (!NT_STATUS_IS_OK(status
)) {
1750 name_list
= ea_list_union(name_list
, file_list
, &ea_len
);
1752 /* We need to determine if this entry will fit in the space available. */
1753 /* Max string size is 255 bytes. */
1754 if (PTR_DIFF(p
+ 255 + ea_len
,pdata
) > space_remaining
) {
1755 *out_of_space
= true;
1756 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1757 "(wanted %u, had %d)\n",
1758 (unsigned int)PTR_DIFF(p
+ 255 + ea_len
,pdata
),
1760 return False
; /* Not finished - just out of space */
1763 /* Push the ea_data followed by the name. */
1764 p
+= fill_ea_buffer(ctx
, p
, space_remaining
, conn
, name_list
);
1766 len
= srvstr_push(base_data
, flags2
,
1767 p
+ 1, fname
, PTR_DIFF(end_data
, p
+1),
1768 STR_TERMINATE
| STR_NOALIGN
);
1769 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1782 SCVAL(nameptr
,0,len
);
1784 SCVAL(p
,0,0); p
+= 1; /* Extra zero byte ? - why.. */
1788 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
1789 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1790 was_8_3
= mangle_is_8_3(fname
, True
, conn
->params
);
1792 SIVAL(p
,0,reskey
); p
+= 4;
1793 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
1794 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
1795 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
1796 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
1797 SOFF_T(p
,0,file_size
); p
+= 8;
1798 SOFF_T(p
,0,allocation_size
); p
+= 8;
1799 SIVAL(p
,0,mode
); p
+= 4;
1800 q
= p
; p
+= 4; /* q is placeholder for name length. */
1802 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
1804 SIVAL(p
,0,ea_size
); /* Extended attributes */
1807 /* Clear the short name buffer. This is
1808 * IMPORTANT as not doing so will trigger
1809 * a Win2k client bug. JRA.
1811 if (!was_8_3
&& check_mangled_names
) {
1812 char mangled_name
[13]; /* mangled 8.3 name. */
1813 if (!name_to_8_3(fname
,mangled_name
,True
,
1815 /* Error - mangle failed ! */
1816 memset(mangled_name
,'\0',12);
1818 mangled_name
[12] = 0;
1819 len
= srvstr_push(base_data
, flags2
,
1820 p
+2, mangled_name
, 24,
1821 STR_UPPER
|STR_UNICODE
);
1823 memset(p
+ 2 + len
,'\0',24 - len
);
1830 len
= srvstr_push(base_data
, flags2
, p
,
1831 fname
, PTR_DIFF(end_data
, p
),
1832 STR_TERMINATE_ASCII
);
1836 len
= PTR_DIFF(p
, pdata
);
1837 pad
= (len
+ (align
-1)) & ~(align
-1);
1839 * offset to the next entry, the caller
1840 * will overwrite it for the last entry
1841 * that's why we always include the padding
1845 * set padding to zero
1848 memset(p
, 0, pad
- len
);
1855 case SMB_FIND_FILE_DIRECTORY_INFO
:
1856 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1858 SIVAL(p
,0,reskey
); p
+= 4;
1859 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
1860 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
1861 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
1862 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
1863 SOFF_T(p
,0,file_size
); p
+= 8;
1864 SOFF_T(p
,0,allocation_size
); p
+= 8;
1865 SIVAL(p
,0,mode
); p
+= 4;
1866 len
= srvstr_push(base_data
, flags2
,
1867 p
+ 4, fname
, PTR_DIFF(end_data
, p
+4),
1868 STR_TERMINATE_ASCII
);
1872 len
= PTR_DIFF(p
, pdata
);
1873 pad
= (len
+ (align
-1)) & ~(align
-1);
1875 * offset to the next entry, the caller
1876 * will overwrite it for the last entry
1877 * that's why we always include the padding
1881 * set padding to zero
1884 memset(p
, 0, pad
- len
);
1891 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
1892 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1894 SIVAL(p
,0,reskey
); p
+= 4;
1895 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
1896 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
1897 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
1898 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
1899 SOFF_T(p
,0,file_size
); p
+= 8;
1900 SOFF_T(p
,0,allocation_size
); p
+= 8;
1901 SIVAL(p
,0,mode
); p
+= 4;
1902 q
= p
; p
+= 4; /* q is placeholder for name length. */
1904 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
1906 SIVAL(p
,0,ea_size
); /* Extended attributes */
1909 len
= srvstr_push(base_data
, flags2
, p
,
1910 fname
, PTR_DIFF(end_data
, p
),
1911 STR_TERMINATE_ASCII
);
1915 len
= PTR_DIFF(p
, pdata
);
1916 pad
= (len
+ (align
-1)) & ~(align
-1);
1918 * offset to the next entry, the caller
1919 * will overwrite it for the last entry
1920 * that's why we always include the padding
1924 * set padding to zero
1927 memset(p
, 0, pad
- len
);
1934 case SMB_FIND_FILE_NAMES_INFO
:
1935 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1937 SIVAL(p
,0,reskey
); p
+= 4;
1939 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1940 acl on a dir (tridge) */
1941 len
= srvstr_push(base_data
, flags2
, p
,
1942 fname
, PTR_DIFF(end_data
, p
),
1943 STR_TERMINATE_ASCII
);
1947 len
= PTR_DIFF(p
, pdata
);
1948 pad
= (len
+ (align
-1)) & ~(align
-1);
1950 * offset to the next entry, the caller
1951 * will overwrite it for the last entry
1952 * that's why we always include the padding
1956 * set padding to zero
1959 memset(p
, 0, pad
- len
);
1966 case SMB_FIND_ID_FULL_DIRECTORY_INFO
:
1967 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1969 SIVAL(p
,0,reskey
); p
+= 4;
1970 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
1971 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
1972 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
1973 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
1974 SOFF_T(p
,0,file_size
); p
+= 8;
1975 SOFF_T(p
,0,allocation_size
); p
+= 8;
1976 SIVAL(p
,0,mode
); p
+= 4;
1977 q
= p
; p
+= 4; /* q is placeholder for name length. */
1979 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
1981 SIVAL(p
,0,ea_size
); /* Extended attributes */
1984 SIVAL(p
,0,0); p
+= 4; /* Unknown - reserved ? */
1985 SBVAL(p
,0,file_index
); p
+= 8;
1986 len
= srvstr_push(base_data
, flags2
, p
,
1987 fname
, PTR_DIFF(end_data
, p
),
1988 STR_TERMINATE_ASCII
);
1992 len
= PTR_DIFF(p
, pdata
);
1993 pad
= (len
+ (align
-1)) & ~(align
-1);
1995 * offset to the next entry, the caller
1996 * will overwrite it for the last entry
1997 * that's why we always include the padding
2001 * set padding to zero
2004 memset(p
, 0, pad
- len
);
2011 case SMB_FIND_ID_BOTH_DIRECTORY_INFO
:
2012 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
2013 was_8_3
= mangle_is_8_3(fname
, True
, conn
->params
);
2015 SIVAL(p
,0,reskey
); p
+= 4;
2016 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
2017 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
2018 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
2019 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
2020 SOFF_T(p
,0,file_size
); p
+= 8;
2021 SOFF_T(p
,0,allocation_size
); p
+= 8;
2022 SIVAL(p
,0,mode
); p
+= 4;
2023 q
= p
; p
+= 4; /* q is placeholder for name length */
2025 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
2027 SIVAL(p
,0,ea_size
); /* Extended attributes */
2030 /* Clear the short name buffer. This is
2031 * IMPORTANT as not doing so will trigger
2032 * a Win2k client bug. JRA.
2034 if (!was_8_3
&& check_mangled_names
) {
2035 char mangled_name
[13]; /* mangled 8.3 name. */
2036 if (!name_to_8_3(fname
,mangled_name
,True
,
2038 /* Error - mangle failed ! */
2039 memset(mangled_name
,'\0',12);
2041 mangled_name
[12] = 0;
2042 len
= srvstr_push(base_data
, flags2
,
2043 p
+2, mangled_name
, 24,
2044 STR_UPPER
|STR_UNICODE
);
2047 memset(p
+ 2 + len
,'\0',24 - len
);
2054 SSVAL(p
,0,0); p
+= 2; /* Reserved ? */
2055 SBVAL(p
,0,file_index
); p
+= 8;
2056 len
= srvstr_push(base_data
, flags2
, p
,
2057 fname
, PTR_DIFF(end_data
, p
),
2058 STR_TERMINATE_ASCII
);
2062 len
= PTR_DIFF(p
, pdata
);
2063 pad
= (len
+ (align
-1)) & ~(align
-1);
2065 * offset to the next entry, the caller
2066 * will overwrite it for the last entry
2067 * that's why we always include the padding
2071 * set padding to zero
2074 memset(p
, 0, pad
- len
);
2081 /* CIFS UNIX Extension. */
2083 case SMB_FIND_FILE_UNIX
:
2084 case SMB_FIND_FILE_UNIX_INFO2
:
2086 SIVAL(p
,0,reskey
); p
+= 4; /* Used for continuing search. */
2088 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
2090 if (info_level
== SMB_FIND_FILE_UNIX
) {
2091 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
2092 p
= store_file_unix_basic(conn
, p
,
2093 NULL
, &smb_fname
->st
);
2094 len
= srvstr_push(base_data
, flags2
, p
,
2095 fname
, PTR_DIFF(end_data
, p
),
2098 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
2099 p
= store_file_unix_basic_info2(conn
, p
,
2100 NULL
, &smb_fname
->st
);
2103 len
= srvstr_push(base_data
, flags2
, p
, fname
,
2104 PTR_DIFF(end_data
, p
), 0);
2105 SIVAL(nameptr
, 0, len
);
2110 len
= PTR_DIFF(p
, pdata
);
2111 pad
= (len
+ (align
-1)) & ~(align
-1);
2113 * offset to the next entry, the caller
2114 * will overwrite it for the last entry
2115 * that's why we always include the padding
2119 * set padding to zero
2122 memset(p
, 0, pad
- len
);
2127 /* End of SMB_QUERY_FILE_UNIX_BASIC */
2135 if (PTR_DIFF(p
,pdata
) > space_remaining
) {
2136 *out_of_space
= true;
2137 DEBUG(9,("smbd_marshall_dir_entry: out of space "
2138 "(wanted %u, had %d)\n",
2139 (unsigned int)PTR_DIFF(p
,pdata
),
2141 return false; /* Not finished - just out of space */
2144 /* Setup the last entry pointer, as an offset from base_data */
2145 *last_entry_off
= PTR_DIFF(last_entry_ptr
,base_data
);
2146 /* Advance the data pointer to the next slot */
2152 bool smbd_dirptr_lanman2_entry(TALLOC_CTX
*ctx
,
2153 connection_struct
*conn
,
2154 struct dptr_struct
*dirptr
,
2156 const char *path_mask
,
2159 int requires_resume_key
,
2167 int space_remaining
,
2169 bool *got_exact_match
,
2170 int *_last_entry_off
,
2171 struct ea_list
*name_list
)
2174 const char *mask
= NULL
;
2175 long prev_dirpos
= 0;
2178 struct smb_filename
*smb_fname
= NULL
;
2179 struct smbd_dirptr_lanman2_state state
;
2181 uint64_t last_entry_off
= 0;
2185 state
.info_level
= info_level
;
2186 state
.check_mangled_names
= lp_manglednames(conn
->params
);
2187 state
.has_wild
= dptr_has_wild(dirptr
);
2188 state
.got_exact_match
= false;
2190 *out_of_space
= false;
2191 *got_exact_match
= false;
2193 p
= strrchr_m(path_mask
,'/');
2204 ok
= smbd_dirptr_get_entry(ctx
,
2210 smbd_dirptr_lanman2_match_fn
,
2211 smbd_dirptr_lanman2_mode_fn
,
2221 *got_exact_match
= state
.got_exact_match
;
2223 ok
= smbd_marshall_dir_entry(ctx
,
2228 state
.check_mangled_names
,
2229 requires_resume_key
,
2242 TALLOC_FREE(smb_fname
);
2243 if (*out_of_space
) {
2244 dptr_SeekDir(dirptr
, prev_dirpos
);
2251 *_last_entry_off
= last_entry_off
;
2255 static bool get_lanman2_dir_entry(TALLOC_CTX
*ctx
,
2256 connection_struct
*conn
,
2257 struct dptr_struct
*dirptr
,
2259 const char *path_mask
,
2262 bool requires_resume_key
,
2268 int space_remaining
,
2270 bool *got_exact_match
,
2271 int *last_entry_off
,
2272 struct ea_list
*name_list
)
2275 const bool do_pad
= true;
2277 if (info_level
>= 1 && info_level
<= 3) {
2278 /* No alignment on earlier info levels. */
2282 return smbd_dirptr_lanman2_entry(ctx
, conn
, dirptr
, flags2
,
2283 path_mask
, dirtype
, info_level
,
2284 requires_resume_key
, dont_descend
, ask_sharemode
,
2286 ppdata
, base_data
, end_data
,
2288 out_of_space
, got_exact_match
,
2289 last_entry_off
, name_list
);
2292 /****************************************************************************
2293 Reply to a TRANS2_FINDFIRST.
2294 ****************************************************************************/
2296 static void call_trans2findfirst(connection_struct
*conn
,
2297 struct smb_request
*req
,
2298 char **pparams
, int total_params
,
2299 char **ppdata
, int total_data
,
2300 unsigned int max_data_bytes
)
2302 /* We must be careful here that we don't return more than the
2303 allowed number of data bytes. If this means returning fewer than
2304 maxentries then so be it. We assume that the redirector has
2305 enough room for the fixed number of parameter bytes it has
2307 struct smb_filename
*smb_dname
= NULL
;
2308 char *params
= *pparams
;
2309 char *pdata
= *ppdata
;
2313 uint16 findfirst_flags
;
2314 bool close_after_first
;
2316 bool requires_resume_key
;
2318 char *directory
= NULL
;
2321 int last_entry_off
=0;
2325 bool finished
= False
;
2326 bool dont_descend
= False
;
2327 bool out_of_space
= False
;
2328 int space_remaining
;
2329 bool mask_contains_wcard
= False
;
2330 struct ea_list
*ea_list
= NULL
;
2331 NTSTATUS ntstatus
= NT_STATUS_OK
;
2332 bool ask_sharemode
= lp_parm_bool(SNUM(conn
), "smbd", "search ask sharemode", true);
2333 TALLOC_CTX
*ctx
= talloc_tos();
2334 struct dptr_struct
*dirptr
= NULL
;
2335 struct smbd_server_connection
*sconn
= req
->sconn
;
2336 uint32_t ucf_flags
= (UCF_SAVE_LCOMP
| UCF_ALWAYS_ALLOW_WCARD_LCOMP
);
2337 bool backup_priv
= false;
2339 if (total_params
< 13) {
2340 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2344 dirtype
= SVAL(params
,0);
2345 maxentries
= SVAL(params
,2);
2346 findfirst_flags
= SVAL(params
,4);
2347 close_after_first
= (findfirst_flags
& FLAG_TRANS2_FIND_CLOSE
);
2348 close_if_end
= (findfirst_flags
& FLAG_TRANS2_FIND_CLOSE_IF_END
);
2349 requires_resume_key
= (findfirst_flags
& FLAG_TRANS2_FIND_REQUIRE_RESUME
);
2350 backup_priv
= ((findfirst_flags
& FLAG_TRANS2_FIND_BACKUP_INTENT
) &&
2351 security_token_has_privilege(get_current_nttok(conn
),
2354 info_level
= SVAL(params
,6);
2356 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2357 close_if_end = %d requires_resume_key = %d backup_priv = %d level = 0x%x, max_data_bytes = %d\n",
2358 (unsigned int)dirtype
, maxentries
, close_after_first
, close_if_end
, requires_resume_key
,
2360 info_level
, max_data_bytes
));
2363 /* W2K3 seems to treat zero as 1. */
2367 switch (info_level
) {
2368 case SMB_FIND_INFO_STANDARD
:
2369 case SMB_FIND_EA_SIZE
:
2370 case SMB_FIND_EA_LIST
:
2371 case SMB_FIND_FILE_DIRECTORY_INFO
:
2372 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
2373 case SMB_FIND_FILE_NAMES_INFO
:
2374 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
2375 case SMB_FIND_ID_FULL_DIRECTORY_INFO
:
2376 case SMB_FIND_ID_BOTH_DIRECTORY_INFO
:
2378 case SMB_FIND_FILE_UNIX
:
2379 case SMB_FIND_FILE_UNIX_INFO2
:
2380 /* Always use filesystem for UNIX mtime query. */
2381 ask_sharemode
= false;
2382 if (!lp_unix_extensions()) {
2383 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2386 ucf_flags
|= UCF_UNIX_NAME_LOOKUP
;
2389 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2393 srvstr_get_path_wcard(ctx
, params
, req
->flags2
, &directory
,
2394 params
+12, total_params
- 12,
2395 STR_TERMINATE
, &ntstatus
, &mask_contains_wcard
);
2396 if (!NT_STATUS_IS_OK(ntstatus
)) {
2397 reply_nterror(req
, ntstatus
);
2403 ntstatus
= filename_convert_with_privilege(ctx
,
2408 &mask_contains_wcard
,
2411 ntstatus
= filename_convert(ctx
, conn
,
2412 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
2415 &mask_contains_wcard
,
2419 if (!NT_STATUS_IS_OK(ntstatus
)) {
2420 if (NT_STATUS_EQUAL(ntstatus
,NT_STATUS_PATH_NOT_COVERED
)) {
2421 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
2422 ERRSRV
, ERRbadpath
);
2425 reply_nterror(req
, ntstatus
);
2429 mask
= smb_dname
->original_lcomp
;
2431 directory
= smb_dname
->base_name
;
2433 p
= strrchr_m(directory
,'/');
2435 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2436 if((directory
[0] == '.') && (directory
[1] == '\0')) {
2437 mask
= talloc_strdup(ctx
,"*");
2439 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2442 mask_contains_wcard
= True
;
2448 if (p
== NULL
|| p
== directory
) {
2449 /* Ensure we don't have a directory name of "". */
2450 directory
= talloc_strdup(talloc_tos(), ".");
2452 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2457 DEBUG(5,("dir=%s, mask = %s\n",directory
, mask
));
2459 if (info_level
== SMB_FIND_EA_LIST
) {
2462 if (total_data
< 4) {
2463 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2467 ea_size
= IVAL(pdata
,0);
2468 if (ea_size
!= total_data
) {
2469 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2470 total_data=%u (should be %u)\n", (unsigned int)total_data
, (unsigned int)IVAL(pdata
,0) ));
2471 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2475 if (!lp_ea_support(SNUM(conn
))) {
2476 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
2480 /* Pull out the list of names. */
2481 ea_list
= read_ea_name_list(ctx
, pdata
+ 4, ea_size
- 4);
2483 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2488 *ppdata
= (char *)SMB_REALLOC(
2489 *ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
2490 if(*ppdata
== NULL
) {
2491 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2495 data_end
= pdata
+ max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
- 1;
2497 /* Realloc the params space */
2498 *pparams
= (char *)SMB_REALLOC(*pparams
, 10);
2499 if (*pparams
== NULL
) {
2500 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2505 /* Save the wildcard match and attribs we are using on this directory -
2506 needed as lanman2 assumes these are being saved between calls */
2508 ntstatus
= dptr_create(conn
,
2516 mask_contains_wcard
,
2520 if (!NT_STATUS_IS_OK(ntstatus
)) {
2521 reply_nterror(req
, ntstatus
);
2526 /* Remember this in case we have
2527 to do a findnext. */
2528 dptr_set_priv(dirptr
);
2531 dptr_num
= dptr_dnum(dirptr
);
2532 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num
, mask
, dirtype
));
2534 /* Initialize per TRANS2_FIND_FIRST operation data */
2535 dptr_init_search_op(dirptr
);
2537 /* We don't need to check for VOL here as this is returned by
2538 a different TRANS2 call. */
2540 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2541 directory
,lp_dontdescend(ctx
, SNUM(conn
))));
2542 if (in_list(directory
,lp_dontdescend(ctx
, SNUM(conn
)),conn
->case_sensitive
))
2543 dont_descend
= True
;
2546 space_remaining
= max_data_bytes
;
2547 out_of_space
= False
;
2549 for (i
=0;(i
<maxentries
) && !finished
&& !out_of_space
;i
++) {
2550 bool got_exact_match
= False
;
2552 /* this is a heuristic to avoid seeking the dirptr except when
2553 absolutely necessary. It allows for a filename of about 40 chars */
2554 if (space_remaining
< DIRLEN_GUESS
&& numentries
> 0) {
2555 out_of_space
= True
;
2558 finished
= !get_lanman2_dir_entry(ctx
,
2562 mask
,dirtype
,info_level
,
2563 requires_resume_key
,dont_descend
,
2566 space_remaining
, &out_of_space
,
2568 &last_entry_off
, ea_list
);
2571 if (finished
&& out_of_space
)
2574 if (!finished
&& !out_of_space
)
2578 * As an optimisation if we know we aren't looking
2579 * for a wildcard name (ie. the name matches the wildcard exactly)
2580 * then we can finish on any (first) match.
2581 * This speeds up large directory searches. JRA.
2587 /* Ensure space_remaining never goes -ve. */
2588 if (PTR_DIFF(p
,pdata
) > max_data_bytes
) {
2589 space_remaining
= 0;
2590 out_of_space
= true;
2592 space_remaining
= max_data_bytes
- PTR_DIFF(p
,pdata
);
2596 /* Check if we can close the dirptr */
2597 if(close_after_first
|| (finished
&& close_if_end
)) {
2598 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num
));
2599 dptr_close(sconn
, &dptr_num
);
2603 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2604 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2605 * the protocol level is less than NT1. Tested with smbclient. JRA.
2606 * This should fix the OS/2 client bug #2335.
2609 if(numentries
== 0) {
2610 dptr_close(sconn
, &dptr_num
);
2611 if (get_Protocol() < PROTOCOL_NT1
) {
2612 reply_force_doserror(req
, ERRDOS
, ERRnofiles
);
2615 reply_botherror(req
, NT_STATUS_NO_SUCH_FILE
,
2616 ERRDOS
, ERRbadfile
);
2621 /* At this point pdata points to numentries directory entries. */
2623 /* Set up the return parameter block */
2624 SSVAL(params
,0,dptr_num
);
2625 SSVAL(params
,2,numentries
);
2626 SSVAL(params
,4,finished
);
2627 SSVAL(params
,6,0); /* Never an EA error */
2628 SSVAL(params
,8,last_entry_off
);
2630 send_trans2_replies(conn
, req
, params
, 10, pdata
, PTR_DIFF(p
,pdata
),
2633 if ((! *directory
) && dptr_path(sconn
, dptr_num
)) {
2634 directory
= talloc_strdup(talloc_tos(),dptr_path(sconn
, dptr_num
));
2636 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2640 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2641 smb_fn_name(req
->cmd
),
2642 mask
, directory
, dirtype
, numentries
) );
2645 * Force a name mangle here to ensure that the
2646 * mask as an 8.3 name is top of the mangled cache.
2647 * The reasons for this are subtle. Don't remove
2648 * this code unless you know what you are doing
2649 * (see PR#13758). JRA.
2652 if(!mangle_is_8_3_wildcards( mask
, False
, conn
->params
)) {
2653 char mangled_name
[13];
2654 name_to_8_3(mask
, mangled_name
, True
, conn
->params
);
2662 TALLOC_FREE(smb_dname
);
2666 /****************************************************************************
2667 Reply to a TRANS2_FINDNEXT.
2668 ****************************************************************************/
2670 static void call_trans2findnext(connection_struct
*conn
,
2671 struct smb_request
*req
,
2672 char **pparams
, int total_params
,
2673 char **ppdata
, int total_data
,
2674 unsigned int max_data_bytes
)
2676 /* We must be careful here that we don't return more than the
2677 allowed number of data bytes. If this means returning fewer than
2678 maxentries then so be it. We assume that the redirector has
2679 enough room for the fixed number of parameter bytes it has
2681 char *params
= *pparams
;
2682 char *pdata
= *ppdata
;
2688 uint16 findnext_flags
;
2689 bool close_after_request
;
2691 bool requires_resume_key
;
2693 bool mask_contains_wcard
= False
;
2694 char *resume_name
= NULL
;
2695 const char *mask
= NULL
;
2696 const char *directory
= NULL
;
2700 int i
, last_entry_off
=0;
2701 bool finished
= False
;
2702 bool dont_descend
= False
;
2703 bool out_of_space
= False
;
2704 int space_remaining
;
2705 struct ea_list
*ea_list
= NULL
;
2706 NTSTATUS ntstatus
= NT_STATUS_OK
;
2707 bool ask_sharemode
= lp_parm_bool(SNUM(conn
), "smbd", "search ask sharemode", true);
2708 TALLOC_CTX
*ctx
= talloc_tos();
2709 struct dptr_struct
*dirptr
;
2710 struct smbd_server_connection
*sconn
= req
->sconn
;
2711 bool backup_priv
= false;
2713 if (total_params
< 13) {
2714 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2718 dptr_num
= SVAL(params
,0);
2719 maxentries
= SVAL(params
,2);
2720 info_level
= SVAL(params
,4);
2721 resume_key
= IVAL(params
,6);
2722 findnext_flags
= SVAL(params
,10);
2723 close_after_request
= (findnext_flags
& FLAG_TRANS2_FIND_CLOSE
);
2724 close_if_end
= (findnext_flags
& FLAG_TRANS2_FIND_CLOSE_IF_END
);
2725 requires_resume_key
= (findnext_flags
& FLAG_TRANS2_FIND_REQUIRE_RESUME
);
2726 continue_bit
= (findnext_flags
& FLAG_TRANS2_FIND_CONTINUE
);
2728 if (!continue_bit
) {
2729 /* We only need resume_name if continue_bit is zero. */
2730 srvstr_get_path_wcard(ctx
, params
, req
->flags2
, &resume_name
,
2732 total_params
- 12, STR_TERMINATE
, &ntstatus
,
2733 &mask_contains_wcard
);
2734 if (!NT_STATUS_IS_OK(ntstatus
)) {
2735 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2736 complain (it thinks we're asking for the directory above the shared
2737 path or an invalid name). Catch this as the resume name is only compared, never used in
2738 a file access. JRA. */
2739 srvstr_pull_talloc(ctx
, params
, req
->flags2
,
2740 &resume_name
, params
+12,
2744 if (!resume_name
|| !(ISDOT(resume_name
) || ISDOTDOT(resume_name
))) {
2745 reply_nterror(req
, ntstatus
);
2751 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2752 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2753 resume_key = %d resume name = %s continue=%d level = %d\n",
2754 dptr_num
, max_data_bytes
, maxentries
, close_after_request
, close_if_end
,
2755 requires_resume_key
, resume_key
,
2756 resume_name
? resume_name
: "(NULL)", continue_bit
, info_level
));
2759 /* W2K3 seems to treat zero as 1. */
2763 switch (info_level
) {
2764 case SMB_FIND_INFO_STANDARD
:
2765 case SMB_FIND_EA_SIZE
:
2766 case SMB_FIND_EA_LIST
:
2767 case SMB_FIND_FILE_DIRECTORY_INFO
:
2768 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
2769 case SMB_FIND_FILE_NAMES_INFO
:
2770 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
2771 case SMB_FIND_ID_FULL_DIRECTORY_INFO
:
2772 case SMB_FIND_ID_BOTH_DIRECTORY_INFO
:
2774 case SMB_FIND_FILE_UNIX
:
2775 case SMB_FIND_FILE_UNIX_INFO2
:
2776 /* Always use filesystem for UNIX mtime query. */
2777 ask_sharemode
= false;
2778 if (!lp_unix_extensions()) {
2779 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2784 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2788 if (info_level
== SMB_FIND_EA_LIST
) {
2791 if (total_data
< 4) {
2792 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2796 ea_size
= IVAL(pdata
,0);
2797 if (ea_size
!= total_data
) {
2798 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2799 total_data=%u (should be %u)\n", (unsigned int)total_data
, (unsigned int)IVAL(pdata
,0) ));
2800 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2804 if (!lp_ea_support(SNUM(conn
))) {
2805 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
2809 /* Pull out the list of names. */
2810 ea_list
= read_ea_name_list(ctx
, pdata
+ 4, ea_size
- 4);
2812 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2817 *ppdata
= (char *)SMB_REALLOC(
2818 *ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
2819 if(*ppdata
== NULL
) {
2820 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2825 data_end
= pdata
+ max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
- 1;
2827 /* Realloc the params space */
2828 *pparams
= (char *)SMB_REALLOC(*pparams
, 6*SIZEOFWORD
);
2829 if(*pparams
== NULL
) {
2830 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2836 /* Check that the dptr is valid */
2837 if(!(dirptr
= dptr_fetch_lanman2(sconn
, dptr_num
))) {
2838 reply_nterror(req
, STATUS_NO_MORE_FILES
);
2842 directory
= dptr_path(sconn
, dptr_num
);
2844 /* Get the wildcard mask from the dptr */
2845 if((mask
= dptr_wcard(sconn
, dptr_num
))== NULL
) {
2846 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num
));
2847 reply_nterror(req
, STATUS_NO_MORE_FILES
);
2851 /* Get the attr mask from the dptr */
2852 dirtype
= dptr_attr(sconn
, dptr_num
);
2854 backup_priv
= dptr_get_priv(dirptr
);
2856 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld) "
2857 "backup_priv = %d\n",
2858 dptr_num
, mask
, dirtype
,
2860 dptr_TellDir(dirptr
),
2863 /* Initialize per TRANS2_FIND_NEXT operation data */
2864 dptr_init_search_op(dirptr
);
2866 /* We don't need to check for VOL here as this is returned by
2867 a different TRANS2 call. */
2869 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2870 directory
,lp_dontdescend(ctx
, SNUM(conn
))));
2871 if (in_list(directory
,lp_dontdescend(ctx
, SNUM(conn
)),conn
->case_sensitive
))
2872 dont_descend
= True
;
2875 space_remaining
= max_data_bytes
;
2876 out_of_space
= False
;
2883 * Seek to the correct position. We no longer use the resume key but
2884 * depend on the last file name instead.
2887 if(!continue_bit
&& resume_name
&& *resume_name
) {
2890 long current_pos
= 0;
2892 * Remember, name_to_8_3 is called by
2893 * get_lanman2_dir_entry(), so the resume name
2894 * could be mangled. Ensure we check the unmangled name.
2897 if (mangle_is_mangled(resume_name
, conn
->params
)) {
2898 char *new_resume_name
= NULL
;
2899 mangle_lookup_name_from_8_3(ctx
,
2903 if (new_resume_name
) {
2904 resume_name
= new_resume_name
;
2909 * Fix for NT redirector problem triggered by resume key indexes
2910 * changing between directory scans. We now return a resume key of 0
2911 * and instead look for the filename to continue from (also given
2912 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2913 * findfirst/findnext (as is usual) then the directory pointer
2914 * should already be at the correct place.
2917 finished
= !dptr_SearchDir(dirptr
, resume_name
, ¤t_pos
, &st
);
2918 } /* end if resume_name && !continue_bit */
2920 for (i
=0;(i
<(int)maxentries
) && !finished
&& !out_of_space
;i
++) {
2921 bool got_exact_match
= False
;
2923 /* this is a heuristic to avoid seeking the dirptr except when
2924 absolutely necessary. It allows for a filename of about 40 chars */
2925 if (space_remaining
< DIRLEN_GUESS
&& numentries
> 0) {
2926 out_of_space
= True
;
2929 finished
= !get_lanman2_dir_entry(ctx
,
2933 mask
,dirtype
,info_level
,
2934 requires_resume_key
,dont_descend
,
2937 space_remaining
, &out_of_space
,
2939 &last_entry_off
, ea_list
);
2942 if (finished
&& out_of_space
)
2945 if (!finished
&& !out_of_space
)
2949 * As an optimisation if we know we aren't looking
2950 * for a wildcard name (ie. the name matches the wildcard exactly)
2951 * then we can finish on any (first) match.
2952 * This speeds up large directory searches. JRA.
2958 space_remaining
= max_data_bytes
- PTR_DIFF(p
,pdata
);
2961 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2962 smb_fn_name(req
->cmd
),
2963 mask
, directory
, dirtype
, numentries
) );
2965 /* Check if we can close the dirptr */
2966 if(close_after_request
|| (finished
&& close_if_end
)) {
2967 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num
));
2968 dptr_close(sconn
, &dptr_num
); /* This frees up the saved mask */
2975 /* Set up the return parameter block */
2976 SSVAL(params
,0,numentries
);
2977 SSVAL(params
,2,finished
);
2978 SSVAL(params
,4,0); /* Never an EA error */
2979 SSVAL(params
,6,last_entry_off
);
2981 send_trans2_replies(conn
, req
, params
, 8, pdata
, PTR_DIFF(p
,pdata
),
2987 unsigned char *create_volume_objectid(connection_struct
*conn
, unsigned char objid
[16])
2989 E_md4hash(lp_servicename(talloc_tos(), SNUM(conn
)),objid
);
2993 static void samba_extended_info_version(struct smb_extended_info
*extended_info
)
2995 SMB_ASSERT(extended_info
!= NULL
);
2997 extended_info
->samba_magic
= SAMBA_EXTENDED_INFO_MAGIC
;
2998 extended_info
->samba_version
= ((SAMBA_VERSION_MAJOR
& 0xff) << 24)
2999 | ((SAMBA_VERSION_MINOR
& 0xff) << 16)
3000 | ((SAMBA_VERSION_RELEASE
& 0xff) << 8);
3001 #ifdef SAMBA_VERSION_REVISION
3002 extended_info
->samba_version
|= (tolower(*SAMBA_VERSION_REVISION
) - 'a' + 1) & 0xff;
3004 extended_info
->samba_subversion
= 0;
3005 #ifdef SAMBA_VERSION_RC_RELEASE
3006 extended_info
->samba_subversion
|= (SAMBA_VERSION_RC_RELEASE
& 0xff) << 24;
3008 #ifdef SAMBA_VERSION_PRE_RELEASE
3009 extended_info
->samba_subversion
|= (SAMBA_VERSION_PRE_RELEASE
& 0xff) << 16;
3012 #ifdef SAMBA_VERSION_VENDOR_PATCH
3013 extended_info
->samba_subversion
|= (SAMBA_VERSION_VENDOR_PATCH
& 0xffff);
3015 extended_info
->samba_gitcommitdate
= 0;
3016 #ifdef SAMBA_VERSION_COMMIT_TIME
3017 unix_to_nt_time(&extended_info
->samba_gitcommitdate
, SAMBA_VERSION_COMMIT_TIME
);
3020 memset(extended_info
->samba_version_string
, 0,
3021 sizeof(extended_info
->samba_version_string
));
3023 snprintf (extended_info
->samba_version_string
,
3024 sizeof(extended_info
->samba_version_string
),
3025 "%s", samba_version_string());
3028 NTSTATUS
smbd_do_qfsinfo(connection_struct
*conn
,
3029 TALLOC_CTX
*mem_ctx
,
3030 uint16_t info_level
,
3032 unsigned int max_data_bytes
,
3036 char *pdata
, *end_data
;
3037 int data_len
= 0, len
;
3038 const char *vname
= volume_label(talloc_tos(), SNUM(conn
));
3039 int snum
= SNUM(conn
);
3040 char *fstype
= lp_fstype(talloc_tos(), SNUM(conn
));
3041 uint32 additional_flags
= 0;
3042 struct smb_filename smb_fname_dot
;
3046 if (info_level
!= SMB_QUERY_CIFS_UNIX_INFO
) {
3047 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
3048 "info level (0x%x) on IPC$.\n",
3049 (unsigned int)info_level
));
3050 return NT_STATUS_ACCESS_DENIED
;
3054 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level
));
3056 ZERO_STRUCT(smb_fname_dot
);
3057 smb_fname_dot
.base_name
= discard_const_p(char, ".");
3059 if(SMB_VFS_STAT(conn
, &smb_fname_dot
) != 0) {
3060 DEBUG(2,("stat of . failed (%s)\n", strerror(errno
)));
3061 return map_nt_error_from_unix(errno
);
3064 st
= smb_fname_dot
.st
;
3066 *ppdata
= (char *)SMB_REALLOC(
3067 *ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
3068 if (*ppdata
== NULL
) {
3069 return NT_STATUS_NO_MEMORY
;
3073 memset((char *)pdata
,'\0',max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
3074 end_data
= pdata
+ max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
- 1;
3076 switch (info_level
) {
3077 case SMB_INFO_ALLOCATION
:
3079 uint64_t dfree
,dsize
,bsize
,block_size
,sectors_per_unit
,bytes_per_sector
;
3081 if (get_dfree_info(conn
,".",False
,&bsize
,&dfree
,&dsize
) == (uint64_t)-1) {
3082 return map_nt_error_from_unix(errno
);
3085 block_size
= lp_block_size(snum
);
3086 if (bsize
< block_size
) {
3087 uint64_t factor
= block_size
/bsize
;
3092 if (bsize
> block_size
) {
3093 uint64_t factor
= bsize
/block_size
;
3098 bytes_per_sector
= 512;
3099 sectors_per_unit
= bsize
/bytes_per_sector
;
3101 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
3102 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st
.st_ex_dev
, (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
3103 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
3105 SIVAL(pdata
,l1_idFileSystem
,st
.st_ex_dev
);
3106 SIVAL(pdata
,l1_cSectorUnit
,sectors_per_unit
);
3107 SIVAL(pdata
,l1_cUnit
,dsize
);
3108 SIVAL(pdata
,l1_cUnitAvail
,dfree
);
3109 SSVAL(pdata
,l1_cbSector
,bytes_per_sector
);
3113 case SMB_INFO_VOLUME
:
3114 /* Return volume name */
3116 * Add volume serial number - hash of a combination of
3117 * the called hostname and the service name.
3119 SIVAL(pdata
,0,str_checksum(lp_servicename(talloc_tos(), snum
)) ^ (str_checksum(get_local_machine_name())<<16) );
3121 * Win2k3 and previous mess this up by sending a name length
3122 * one byte short. I believe only older clients (OS/2 Win9x) use
3123 * this call so try fixing this by adding a terminating null to
3124 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
3128 pdata
+l2_vol_szVolLabel
, vname
,
3129 PTR_DIFF(end_data
, pdata
+l2_vol_szVolLabel
),
3130 STR_NOALIGN
|STR_TERMINATE
);
3131 SCVAL(pdata
,l2_vol_cch
,len
);
3132 data_len
= l2_vol_szVolLabel
+ len
;
3133 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %d, name = %s\n",
3134 (unsigned)convert_timespec_to_time_t(st
.st_ex_ctime
),
3138 case SMB_QUERY_FS_ATTRIBUTE_INFO
:
3139 case SMB_FS_ATTRIBUTE_INFORMATION
:
3141 additional_flags
= 0;
3142 #if defined(HAVE_SYS_QUOTAS)
3143 additional_flags
|= FILE_VOLUME_QUOTAS
;
3146 if(lp_nt_acl_support(SNUM(conn
))) {
3147 additional_flags
|= FILE_PERSISTENT_ACLS
;
3150 /* Capabilities are filled in at connection time through STATVFS call */
3151 additional_flags
|= conn
->fs_capabilities
;
3152 additional_flags
|= lp_parm_int(conn
->params
->service
,
3153 "share", "fake_fscaps",
3156 SIVAL(pdata
,0,FILE_CASE_PRESERVED_NAMES
|FILE_CASE_SENSITIVE_SEARCH
|
3157 FILE_SUPPORTS_OBJECT_IDS
|FILE_UNICODE_ON_DISK
|
3158 additional_flags
); /* FS ATTRIBUTES */
3160 SIVAL(pdata
,4,255); /* Max filename component length */
3161 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
3162 and will think we can't do long filenames */
3163 len
= srvstr_push(pdata
, flags2
, pdata
+12, fstype
,
3164 PTR_DIFF(end_data
, pdata
+12),
3167 data_len
= 12 + len
;
3170 case SMB_QUERY_FS_LABEL_INFO
:
3171 case SMB_FS_LABEL_INFORMATION
:
3172 len
= srvstr_push(pdata
, flags2
, pdata
+4, vname
,
3173 PTR_DIFF(end_data
, pdata
+4), 0);
3178 case SMB_QUERY_FS_VOLUME_INFO
:
3179 case SMB_FS_VOLUME_INFORMATION
:
3182 * Add volume serial number - hash of a combination of
3183 * the called hostname and the service name.
3185 SIVAL(pdata
,8,str_checksum(lp_servicename(talloc_tos(), snum
)) ^
3186 (str_checksum(get_local_machine_name())<<16));
3188 /* Max label len is 32 characters. */
3189 len
= srvstr_push(pdata
, flags2
, pdata
+18, vname
,
3190 PTR_DIFF(end_data
, pdata
+18),
3192 SIVAL(pdata
,12,len
);
3195 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3196 (int)strlen(vname
),vname
,
3197 lp_servicename(talloc_tos(), snum
)));
3200 case SMB_QUERY_FS_SIZE_INFO
:
3201 case SMB_FS_SIZE_INFORMATION
:
3203 uint64_t dfree
,dsize
,bsize
,block_size
,sectors_per_unit
,bytes_per_sector
;
3205 if (get_dfree_info(conn
,".",False
,&bsize
,&dfree
,&dsize
) == (uint64_t)-1) {
3206 return map_nt_error_from_unix(errno
);
3208 block_size
= lp_block_size(snum
);
3209 if (bsize
< block_size
) {
3210 uint64_t factor
= block_size
/bsize
;
3215 if (bsize
> block_size
) {
3216 uint64_t factor
= bsize
/block_size
;
3221 bytes_per_sector
= 512;
3222 sectors_per_unit
= bsize
/bytes_per_sector
;
3223 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3224 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
3225 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
3226 SBIG_UINT(pdata
,0,dsize
);
3227 SBIG_UINT(pdata
,8,dfree
);
3228 SIVAL(pdata
,16,sectors_per_unit
);
3229 SIVAL(pdata
,20,bytes_per_sector
);
3233 case SMB_FS_FULL_SIZE_INFORMATION
:
3235 uint64_t dfree
,dsize
,bsize
,block_size
,sectors_per_unit
,bytes_per_sector
;
3237 if (get_dfree_info(conn
,".",False
,&bsize
,&dfree
,&dsize
) == (uint64_t)-1) {
3238 return map_nt_error_from_unix(errno
);
3240 block_size
= lp_block_size(snum
);
3241 if (bsize
< block_size
) {
3242 uint64_t factor
= block_size
/bsize
;
3247 if (bsize
> block_size
) {
3248 uint64_t factor
= bsize
/block_size
;
3253 bytes_per_sector
= 512;
3254 sectors_per_unit
= bsize
/bytes_per_sector
;
3255 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3256 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
3257 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
3258 SBIG_UINT(pdata
,0,dsize
); /* Total Allocation units. */
3259 SBIG_UINT(pdata
,8,dfree
); /* Caller available allocation units. */
3260 SBIG_UINT(pdata
,16,dfree
); /* Actual available allocation units. */
3261 SIVAL(pdata
,24,sectors_per_unit
); /* Sectors per allocation unit. */
3262 SIVAL(pdata
,28,bytes_per_sector
); /* Bytes per sector. */
3266 case SMB_QUERY_FS_DEVICE_INFO
:
3267 case SMB_FS_DEVICE_INFORMATION
:
3269 uint32_t characteristics
= FILE_DEVICE_IS_MOUNTED
;
3271 if (!CAN_WRITE(conn
)) {
3272 characteristics
|= FILE_READ_ONLY_DEVICE
;
3275 SIVAL(pdata
,0,FILE_DEVICE_DISK
); /* dev type */
3276 SIVAL(pdata
,4,characteristics
);
3280 #ifdef HAVE_SYS_QUOTAS
3281 case SMB_FS_QUOTA_INFORMATION
:
3283 * what we have to send --metze:
3285 * Unknown1: 24 NULL bytes
3286 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3287 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3288 * Quota Flags: 2 byte :
3289 * Unknown3: 6 NULL bytes
3293 * details for Quota Flags:
3295 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3296 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3297 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3298 * 0x0001 Enable Quotas: enable quota for this fs
3302 /* we need to fake up a fsp here,
3303 * because its not send in this call
3306 SMB_NTQUOTA_STRUCT quotas
;
3309 ZERO_STRUCT(quotas
);
3312 fsp
.fnum
= FNUM_FIELD_INVALID
;
3315 if (get_current_uid(conn
) != 0) {
3316 DEBUG(0,("set_user_quota: access_denied "
3317 "service [%s] user [%s]\n",
3318 lp_servicename(talloc_tos(), SNUM(conn
)),
3319 conn
->session_info
->unix_info
->unix_name
));
3320 return NT_STATUS_ACCESS_DENIED
;
3323 if (vfs_get_ntquota(&fsp
, SMB_USER_FS_QUOTA_TYPE
, NULL
, "as
)!=0) {
3324 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn
))));
3325 return map_nt_error_from_unix(errno
);
3330 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3331 lp_servicename(talloc_tos(), SNUM(conn
))));
3333 /* Unknown1 24 NULL bytes*/
3334 SBIG_UINT(pdata
,0,(uint64_t)0);
3335 SBIG_UINT(pdata
,8,(uint64_t)0);
3336 SBIG_UINT(pdata
,16,(uint64_t)0);
3338 /* Default Soft Quota 8 bytes */
3339 SBIG_UINT(pdata
,24,quotas
.softlim
);
3341 /* Default Hard Quota 8 bytes */
3342 SBIG_UINT(pdata
,32,quotas
.hardlim
);
3344 /* Quota flag 2 bytes */
3345 SSVAL(pdata
,40,quotas
.qflags
);
3347 /* Unknown3 6 NULL bytes */
3353 #endif /* HAVE_SYS_QUOTAS */
3354 case SMB_FS_OBJECTID_INFORMATION
:
3356 unsigned char objid
[16];
3357 struct smb_extended_info extended_info
;
3358 memcpy(pdata
,create_volume_objectid(conn
, objid
),16);
3359 samba_extended_info_version (&extended_info
);
3360 SIVAL(pdata
,16,extended_info
.samba_magic
);
3361 SIVAL(pdata
,20,extended_info
.samba_version
);
3362 SIVAL(pdata
,24,extended_info
.samba_subversion
);
3363 SBIG_UINT(pdata
,28,extended_info
.samba_gitcommitdate
);
3364 memcpy(pdata
+36,extended_info
.samba_version_string
,28);
3370 * Query the version and capabilities of the CIFS UNIX extensions
3374 case SMB_QUERY_CIFS_UNIX_INFO
:
3376 bool large_write
= lp_min_receive_file_size() &&
3377 !srv_is_signing_active(conn
->sconn
);
3378 bool large_read
= !srv_is_signing_active(conn
->sconn
);
3379 int encrypt_caps
= 0;
3381 if (!lp_unix_extensions()) {
3382 return NT_STATUS_INVALID_LEVEL
;
3385 switch (conn
->encrypt_level
) {
3386 case SMB_SIGNING_OFF
:
3389 case SMB_SIGNING_IF_REQUIRED
:
3390 case SMB_SIGNING_DEFAULT
:
3391 encrypt_caps
= CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP
;
3393 case SMB_SIGNING_REQUIRED
:
3394 encrypt_caps
= CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP
|
3395 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP
;
3396 large_write
= false;
3402 SSVAL(pdata
,0,CIFS_UNIX_MAJOR_VERSION
);
3403 SSVAL(pdata
,2,CIFS_UNIX_MINOR_VERSION
);
3405 /* We have POSIX ACLs, pathname, encryption,
3406 * large read/write, and locking capability. */
3408 SBIG_UINT(pdata
,4,((uint64_t)(
3409 CIFS_UNIX_POSIX_ACLS_CAP
|
3410 CIFS_UNIX_POSIX_PATHNAMES_CAP
|
3411 CIFS_UNIX_FCNTL_LOCKS_CAP
|
3412 CIFS_UNIX_EXTATTR_CAP
|
3413 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP
|
3415 (large_read
? CIFS_UNIX_LARGE_READ_CAP
: 0) |
3417 CIFS_UNIX_LARGE_WRITE_CAP
: 0))));
3421 case SMB_QUERY_POSIX_FS_INFO
:
3424 vfs_statvfs_struct svfs
;
3426 if (!lp_unix_extensions()) {
3427 return NT_STATUS_INVALID_LEVEL
;
3430 rc
= SMB_VFS_STATVFS(conn
, ".", &svfs
);
3434 SIVAL(pdata
,0,svfs
.OptimalTransferSize
);
3435 SIVAL(pdata
,4,svfs
.BlockSize
);
3436 SBIG_UINT(pdata
,8,svfs
.TotalBlocks
);
3437 SBIG_UINT(pdata
,16,svfs
.BlocksAvail
);
3438 SBIG_UINT(pdata
,24,svfs
.UserBlocksAvail
);
3439 SBIG_UINT(pdata
,32,svfs
.TotalFileNodes
);
3440 SBIG_UINT(pdata
,40,svfs
.FreeFileNodes
);
3441 SBIG_UINT(pdata
,48,svfs
.FsIdentifier
);
3442 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3444 } else if (rc
== EOPNOTSUPP
) {
3445 return NT_STATUS_INVALID_LEVEL
;
3446 #endif /* EOPNOTSUPP */
3448 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn
))));
3449 return NT_STATUS_DOS(ERRSRV
, ERRerror
);
3454 case SMB_QUERY_POSIX_WHOAMI
:
3460 if (!lp_unix_extensions()) {
3461 return NT_STATUS_INVALID_LEVEL
;
3464 if (max_data_bytes
< 40) {
3465 return NT_STATUS_BUFFER_TOO_SMALL
;
3468 if (security_session_user_level(conn
->session_info
, NULL
) < SECURITY_USER
) {
3469 flags
|= SMB_WHOAMI_GUEST
;
3472 /* NOTE: 8 bytes for UID/GID, irrespective of native
3473 * platform size. This matches
3474 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3476 data_len
= 4 /* flags */
3483 + 4 /* pad/reserved */
3484 + (conn
->session_info
->unix_token
->ngroups
* 8)
3486 + (conn
->session_info
->security_token
->num_sids
*
3490 SIVAL(pdata
, 0, flags
);
3491 SIVAL(pdata
, 4, SMB_WHOAMI_MASK
);
3493 (uint64_t)conn
->session_info
->unix_token
->uid
);
3494 SBIG_UINT(pdata
, 16,
3495 (uint64_t)conn
->session_info
->unix_token
->gid
);
3498 if (data_len
>= max_data_bytes
) {
3499 /* Potential overflow, skip the GIDs and SIDs. */
3501 SIVAL(pdata
, 24, 0); /* num_groups */
3502 SIVAL(pdata
, 28, 0); /* num_sids */
3503 SIVAL(pdata
, 32, 0); /* num_sid_bytes */
3504 SIVAL(pdata
, 36, 0); /* reserved */
3510 SIVAL(pdata
, 24, conn
->session_info
->unix_token
->ngroups
);
3511 SIVAL(pdata
, 28, conn
->session_info
->security_token
->num_sids
);
3513 /* We walk the SID list twice, but this call is fairly
3514 * infrequent, and I don't expect that it's performance
3515 * sensitive -- jpeach
3517 for (i
= 0, sid_bytes
= 0;
3518 i
< conn
->session_info
->security_token
->num_sids
; ++i
) {
3519 sid_bytes
+= ndr_size_dom_sid(
3520 &conn
->session_info
->security_token
->sids
[i
],
3524 /* SID list byte count */
3525 SIVAL(pdata
, 32, sid_bytes
);
3527 /* 4 bytes pad/reserved - must be zero */
3528 SIVAL(pdata
, 36, 0);
3532 for (i
= 0; i
< conn
->session_info
->unix_token
->ngroups
; ++i
) {
3533 SBIG_UINT(pdata
, data_len
,
3534 (uint64_t)conn
->session_info
->unix_token
->groups
[i
]);
3540 i
< conn
->session_info
->security_token
->num_sids
; ++i
) {
3541 int sid_len
= ndr_size_dom_sid(
3542 &conn
->session_info
->security_token
->sids
[i
],
3545 sid_linearize(pdata
+ data_len
, sid_len
,
3546 &conn
->session_info
->security_token
->sids
[i
]);
3547 data_len
+= sid_len
;
3553 case SMB_MAC_QUERY_FS_INFO
:
3555 * Thursby MAC extension... ONLY on NTFS filesystems
3556 * once we do streams then we don't need this
3558 if (strequal(lp_fstype(talloc_tos(), SNUM(conn
)),"NTFS")) {
3560 SIVAL(pdata
,84,0x100); /* Don't support mac... */
3565 return NT_STATUS_INVALID_LEVEL
;
3568 *ret_data_len
= data_len
;
3569 return NT_STATUS_OK
;
3572 /****************************************************************************
3573 Reply to a TRANS2_QFSINFO (query filesystem info).
3574 ****************************************************************************/
3576 static void call_trans2qfsinfo(connection_struct
*conn
,
3577 struct smb_request
*req
,
3578 char **pparams
, int total_params
,
3579 char **ppdata
, int total_data
,
3580 unsigned int max_data_bytes
)
3582 char *params
= *pparams
;
3583 uint16_t info_level
;
3587 if (total_params
< 2) {
3588 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3592 info_level
= SVAL(params
,0);
3594 if (ENCRYPTION_REQUIRED(conn
) && !req
->encrypted
) {
3595 if (info_level
!= SMB_QUERY_CIFS_UNIX_INFO
) {
3596 DEBUG(0,("call_trans2qfsinfo: encryption required "
3597 "and info level 0x%x sent.\n",
3598 (unsigned int)info_level
));
3599 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3604 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level
));
3606 status
= smbd_do_qfsinfo(conn
, req
,
3611 if (!NT_STATUS_IS_OK(status
)) {
3612 reply_nterror(req
, status
);
3616 send_trans2_replies(conn
, req
, params
, 0, *ppdata
, data_len
,
3619 DEBUG( 4, ( "%s info_level = %d\n",
3620 smb_fn_name(req
->cmd
), info_level
) );
3625 /****************************************************************************
3626 Reply to a TRANS2_SETFSINFO (set filesystem info).
3627 ****************************************************************************/
3629 static void call_trans2setfsinfo(connection_struct
*conn
,
3630 struct smb_request
*req
,
3631 char **pparams
, int total_params
,
3632 char **ppdata
, int total_data
,
3633 unsigned int max_data_bytes
)
3635 struct smbd_server_connection
*sconn
= req
->sconn
;
3636 char *pdata
= *ppdata
;
3637 char *params
= *pparams
;
3640 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",
3641 lp_servicename(talloc_tos(), SNUM(conn
))));
3644 if (total_params
< 4) {
3645 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3647 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3651 info_level
= SVAL(params
,2);
3654 if (info_level
!= SMB_REQUEST_TRANSPORT_ENCRYPTION
&&
3655 info_level
!= SMB_SET_CIFS_UNIX_INFO
) {
3656 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3657 "info level (0x%x) on IPC$.\n",
3658 (unsigned int)info_level
));
3659 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3664 if (ENCRYPTION_REQUIRED(conn
) && !req
->encrypted
) {
3665 if (info_level
!= SMB_REQUEST_TRANSPORT_ENCRYPTION
) {
3666 DEBUG(0,("call_trans2setfsinfo: encryption required "
3667 "and info level 0x%x sent.\n",
3668 (unsigned int)info_level
));
3669 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3674 switch(info_level
) {
3675 case SMB_SET_CIFS_UNIX_INFO
:
3676 if (!lp_unix_extensions()) {
3677 DEBUG(2,("call_trans2setfsinfo: "
3678 "SMB_SET_CIFS_UNIX_INFO is invalid with "
3679 "unix extensions off\n"));
3681 NT_STATUS_INVALID_LEVEL
);
3685 /* There should be 12 bytes of capabilities set. */
3686 if (total_data
< 12) {
3689 NT_STATUS_INVALID_PARAMETER
);
3692 sconn
->smb1
.unix_info
.client_major
= SVAL(pdata
,0);
3693 sconn
->smb1
.unix_info
.client_minor
= SVAL(pdata
,2);
3694 sconn
->smb1
.unix_info
.client_cap_low
= IVAL(pdata
,4);
3695 sconn
->smb1
.unix_info
.client_cap_high
= IVAL(pdata
,8);
3696 /* Just print these values for now. */
3697 DEBUG(10, ("call_trans2setfsinfo: set unix_info info. "
3698 "major = %u, minor = %u cap_low = 0x%x, "
3700 (unsigned int)sconn
->
3701 smb1
.unix_info
.client_major
,
3702 (unsigned int)sconn
->
3703 smb1
.unix_info
.client_minor
,
3704 (unsigned int)sconn
->
3705 smb1
.unix_info
.client_cap_low
,
3706 (unsigned int)sconn
->
3707 smb1
.unix_info
.client_cap_high
));
3709 /* Here is where we must switch to posix pathname processing... */
3710 if (sconn
->smb1
.unix_info
.client_cap_low
& CIFS_UNIX_POSIX_PATHNAMES_CAP
) {
3711 lp_set_posix_pathnames();
3712 mangle_change_to_posix();
3715 if ((sconn
->smb1
.unix_info
.client_cap_low
& CIFS_UNIX_FCNTL_LOCKS_CAP
) &&
3716 !(sconn
->smb1
.unix_info
.client_cap_low
& CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP
)) {
3717 /* Client that knows how to do posix locks,
3718 * but not posix open/mkdir operations. Set a
3719 * default type for read/write checks. */
3721 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK
);
3726 case SMB_REQUEST_TRANSPORT_ENCRYPTION
:
3729 size_t param_len
= 0;
3730 size_t data_len
= total_data
;
3732 if (!lp_unix_extensions()) {
3735 NT_STATUS_INVALID_LEVEL
);
3739 if (lp_smb_encrypt(SNUM(conn
)) == SMB_SIGNING_OFF
) {
3742 NT_STATUS_NOT_SUPPORTED
);
3746 if (req
->sconn
->smb1
.echo_handler
.trusted_fde
) {
3747 DEBUG( 2,("call_trans2setfsinfo: "
3748 "request transport encryption disabled"
3749 "with 'fork echo handler = yes'\n"));
3752 NT_STATUS_NOT_SUPPORTED
);
3756 DEBUG( 4,("call_trans2setfsinfo: "
3757 "request transport encryption.\n"));
3759 status
= srv_request_encryption_setup(conn
,
3760 (unsigned char **)ppdata
,
3762 (unsigned char **)pparams
,
3765 if (!NT_STATUS_EQUAL(status
, NT_STATUS_MORE_PROCESSING_REQUIRED
) &&
3766 !NT_STATUS_IS_OK(status
)) {
3767 reply_nterror(req
, status
);
3771 send_trans2_replies(conn
, req
,
3778 if (NT_STATUS_IS_OK(status
)) {
3779 /* Server-side transport
3780 * encryption is now *on*. */
3781 status
= srv_encryption_start(conn
);
3782 if (!NT_STATUS_IS_OK(status
)) {
3783 char *reason
= talloc_asprintf(talloc_tos(),
3784 "Failure in setting "
3785 "up encrypted transport: %s",
3787 exit_server_cleanly(reason
);
3793 case SMB_FS_QUOTA_INFORMATION
:
3795 files_struct
*fsp
= NULL
;
3796 SMB_NTQUOTA_STRUCT quotas
;
3798 ZERO_STRUCT(quotas
);
3801 if ((get_current_uid(conn
) != 0) || !CAN_WRITE(conn
)) {
3802 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3803 lp_servicename(talloc_tos(), SNUM(conn
)),
3804 conn
->session_info
->unix_info
->unix_name
));
3805 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3809 /* note: normaly there're 48 bytes,
3810 * but we didn't use the last 6 bytes for now
3813 fsp
= file_fsp(req
, SVAL(params
,0));
3815 if (!check_fsp_ntquota_handle(conn
, req
,
3817 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3819 req
, NT_STATUS_INVALID_HANDLE
);
3823 if (total_data
< 42) {
3824 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3828 NT_STATUS_INVALID_PARAMETER
);
3832 /* unknown_1 24 NULL bytes in pdata*/
3834 /* the soft quotas 8 bytes (uint64_t)*/
3835 quotas
.softlim
= BVAL(pdata
,24);
3837 /* the hard quotas 8 bytes (uint64_t)*/
3838 quotas
.hardlim
= BVAL(pdata
,32);
3840 /* quota_flags 2 bytes **/
3841 quotas
.qflags
= SVAL(pdata
,40);
3843 /* unknown_2 6 NULL bytes follow*/
3845 /* now set the quotas */
3846 if (vfs_set_ntquota(fsp
, SMB_USER_FS_QUOTA_TYPE
, NULL
, "as
)!=0) {
3847 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn
))));
3848 reply_nterror(req
, map_nt_error_from_unix(errno
));
3855 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3857 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
3863 * sending this reply works fine,
3864 * but I'm not sure it's the same
3865 * like windows do...
3868 reply_outbuf(req
, 10, 0);
3871 #if defined(HAVE_POSIX_ACLS)
3872 /****************************************************************************
3873 Utility function to count the number of entries in a POSIX acl.
3874 ****************************************************************************/
3876 static unsigned int count_acl_entries(connection_struct
*conn
, SMB_ACL_T posix_acl
)
3878 unsigned int ace_count
= 0;
3879 int entry_id
= SMB_ACL_FIRST_ENTRY
;
3880 SMB_ACL_ENTRY_T entry
;
3882 while ( posix_acl
&& (sys_acl_get_entry(posix_acl
, entry_id
, &entry
) == 1)) {
3884 if (entry_id
== SMB_ACL_FIRST_ENTRY
) {
3885 entry_id
= SMB_ACL_NEXT_ENTRY
;
3892 /****************************************************************************
3893 Utility function to marshall a POSIX acl into wire format.
3894 ****************************************************************************/
3896 static bool marshall_posix_acl(connection_struct
*conn
, char *pdata
, SMB_STRUCT_STAT
*pst
, SMB_ACL_T posix_acl
)
3898 int entry_id
= SMB_ACL_FIRST_ENTRY
;
3899 SMB_ACL_ENTRY_T entry
;
3901 while ( posix_acl
&& (sys_acl_get_entry(posix_acl
, entry_id
, &entry
) == 1)) {
3902 SMB_ACL_TAG_T tagtype
;
3903 SMB_ACL_PERMSET_T permset
;
3904 unsigned char perms
= 0;
3905 unsigned int own_grp
;
3908 if (entry_id
== SMB_ACL_FIRST_ENTRY
) {
3909 entry_id
= SMB_ACL_NEXT_ENTRY
;
3912 if (sys_acl_get_tag_type(entry
, &tagtype
) == -1) {
3913 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3917 if (sys_acl_get_permset(entry
, &permset
) == -1) {
3918 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3922 perms
|= (sys_acl_get_perm(permset
, SMB_ACL_READ
) ? SMB_POSIX_ACL_READ
: 0);
3923 perms
|= (sys_acl_get_perm(permset
, SMB_ACL_WRITE
) ? SMB_POSIX_ACL_WRITE
: 0);
3924 perms
|= (sys_acl_get_perm(permset
, SMB_ACL_EXECUTE
) ? SMB_POSIX_ACL_EXECUTE
: 0);
3926 SCVAL(pdata
,1,perms
);
3929 case SMB_ACL_USER_OBJ
:
3930 SCVAL(pdata
,0,SMB_POSIX_ACL_USER_OBJ
);
3931 own_grp
= (unsigned int)pst
->st_ex_uid
;
3932 SIVAL(pdata
,2,own_grp
);
3937 uid_t
*puid
= (uid_t
*)sys_acl_get_qualifier(entry
);
3939 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3942 own_grp
= (unsigned int)*puid
;
3943 SCVAL(pdata
,0,SMB_POSIX_ACL_USER
);
3944 SIVAL(pdata
,2,own_grp
);
3948 case SMB_ACL_GROUP_OBJ
:
3949 SCVAL(pdata
,0,SMB_POSIX_ACL_GROUP_OBJ
);
3950 own_grp
= (unsigned int)pst
->st_ex_gid
;
3951 SIVAL(pdata
,2,own_grp
);
3956 gid_t
*pgid
= (gid_t
*)sys_acl_get_qualifier(entry
);
3958 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3961 own_grp
= (unsigned int)*pgid
;
3962 SCVAL(pdata
,0,SMB_POSIX_ACL_GROUP
);
3963 SIVAL(pdata
,2,own_grp
);
3968 SCVAL(pdata
,0,SMB_POSIX_ACL_MASK
);
3969 SIVAL(pdata
,2,0xFFFFFFFF);
3970 SIVAL(pdata
,6,0xFFFFFFFF);
3973 SCVAL(pdata
,0,SMB_POSIX_ACL_OTHER
);
3974 SIVAL(pdata
,2,0xFFFFFFFF);
3975 SIVAL(pdata
,6,0xFFFFFFFF);
3978 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3981 pdata
+= SMB_POSIX_ACL_ENTRY_SIZE
;
3988 /****************************************************************************
3989 Store the FILE_UNIX_BASIC info.
3990 ****************************************************************************/
3992 static char *store_file_unix_basic(connection_struct
*conn
,
3995 const SMB_STRUCT_STAT
*psbuf
)
3997 uint64_t file_index
= get_FileIndex(conn
, psbuf
);
4000 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
4001 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf
->st_ex_mode
));
4003 SOFF_T(pdata
,0,get_file_size_stat(psbuf
)); /* File size 64 Bit */
4006 SOFF_T(pdata
,0,SMB_VFS_GET_ALLOC_SIZE(conn
,fsp
,psbuf
)); /* Number of bytes used on disk - 64 Bit */
4009 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER
, pdata
, psbuf
->st_ex_ctime
); /* Change Time 64 Bit */
4010 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER
,pdata
+8, psbuf
->st_ex_atime
); /* Last access time 64 Bit */
4011 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER
, pdata
+16, psbuf
->st_ex_mtime
); /* Last modification time 64 Bit */
4014 SIVAL(pdata
,0,psbuf
->st_ex_uid
); /* user id for the owner */
4018 SIVAL(pdata
,0,psbuf
->st_ex_gid
); /* group id of owner */
4022 SIVAL(pdata
,0,unix_filetype(psbuf
->st_ex_mode
));
4025 if (S_ISBLK(psbuf
->st_ex_mode
) || S_ISCHR(psbuf
->st_ex_mode
)) {
4026 devno
= psbuf
->st_ex_rdev
;
4028 devno
= psbuf
->st_ex_dev
;
4031 SIVAL(pdata
,0,unix_dev_major(devno
)); /* Major device number if type is device */
4035 SIVAL(pdata
,0,unix_dev_minor(devno
)); /* Minor device number if type is device */
4039 SINO_T_VAL(pdata
,0,(SMB_INO_T
)file_index
); /* inode number */
4042 SIVAL(pdata
,0, unix_perms_to_wire(psbuf
->st_ex_mode
)); /* Standard UNIX file permissions */
4046 SIVAL(pdata
,0,psbuf
->st_ex_nlink
); /* number of hard links */
4053 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
4054 * the chflags(2) (or equivalent) flags.
4056 * XXX: this really should be behind the VFS interface. To do this, we would
4057 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
4058 * Each VFS module could then implement its own mapping as appropriate for the
4059 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
4061 static const struct {unsigned stat_fflag
; unsigned smb_fflag
;}
4065 { UF_NODUMP
, EXT_DO_NOT_BACKUP
},
4069 { UF_IMMUTABLE
, EXT_IMMUTABLE
},
4073 { UF_APPEND
, EXT_OPEN_APPEND_ONLY
},
4077 { UF_HIDDEN
, EXT_HIDDEN
},
4080 /* Do not remove. We need to guarantee that this array has at least one
4081 * entry to build on HP-UX.
4087 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT
*psbuf
,
4088 uint32
*smb_fflags
, uint32
*smb_fmask
)
4092 for (i
= 0; i
< ARRAY_SIZE(info2_flags_map
); ++i
) {
4093 *smb_fmask
|= info2_flags_map
[i
].smb_fflag
;
4094 if (psbuf
->st_ex_flags
& info2_flags_map
[i
].stat_fflag
) {
4095 *smb_fflags
|= info2_flags_map
[i
].smb_fflag
;
4100 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT
*psbuf
,
4101 const uint32 smb_fflags
,
4102 const uint32 smb_fmask
,
4105 uint32 max_fmask
= 0;
4108 *stat_fflags
= psbuf
->st_ex_flags
;
4110 /* For each flags requested in smb_fmask, check the state of the
4111 * corresponding flag in smb_fflags and set or clear the matching
4115 for (i
= 0; i
< ARRAY_SIZE(info2_flags_map
); ++i
) {
4116 max_fmask
|= info2_flags_map
[i
].smb_fflag
;
4117 if (smb_fmask
& info2_flags_map
[i
].smb_fflag
) {
4118 if (smb_fflags
& info2_flags_map
[i
].smb_fflag
) {
4119 *stat_fflags
|= info2_flags_map
[i
].stat_fflag
;
4121 *stat_fflags
&= ~info2_flags_map
[i
].stat_fflag
;
4126 /* If smb_fmask is asking to set any bits that are not supported by
4127 * our flag mappings, we should fail.
4129 if ((smb_fmask
& max_fmask
) != smb_fmask
) {
4137 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
4138 * of file flags and birth (create) time.
4140 static char *store_file_unix_basic_info2(connection_struct
*conn
,
4143 const SMB_STRUCT_STAT
*psbuf
)
4145 uint32 file_flags
= 0;
4146 uint32 flags_mask
= 0;
4148 pdata
= store_file_unix_basic(conn
, pdata
, fsp
, psbuf
);
4150 /* Create (birth) time 64 bit */
4151 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER
,pdata
, psbuf
->st_ex_btime
);
4154 map_info2_flags_from_sbuf(psbuf
, &file_flags
, &flags_mask
);
4155 SIVAL(pdata
, 0, file_flags
); /* flags */
4156 SIVAL(pdata
, 4, flags_mask
); /* mask */
4162 static NTSTATUS
marshall_stream_info(unsigned int num_streams
,
4163 const struct stream_struct
*streams
,
4165 unsigned int max_data_bytes
,
4166 unsigned int *data_size
)
4169 unsigned int ofs
= 0;
4171 for (i
= 0; i
< num_streams
&& ofs
<= max_data_bytes
; i
++) {
4172 unsigned int next_offset
;
4174 smb_ucs2_t
*namebuf
;
4176 if (!push_ucs2_talloc(talloc_tos(), &namebuf
,
4177 streams
[i
].name
, &namelen
) ||
4180 return NT_STATUS_INVALID_PARAMETER
;
4184 * name_buf is now null-terminated, we need to marshall as not
4190 SIVAL(data
, ofs
+4, namelen
);
4191 SOFF_T(data
, ofs
+8, streams
[i
].size
);
4192 SOFF_T(data
, ofs
+16, streams
[i
].alloc_size
);
4193 memcpy(data
+ofs
+24, namebuf
, namelen
);
4194 TALLOC_FREE(namebuf
);
4196 next_offset
= ofs
+ 24 + namelen
;
4198 if (i
== num_streams
-1) {
4199 SIVAL(data
, ofs
, 0);
4202 unsigned int align
= ndr_align_size(next_offset
, 8);
4204 memset(data
+next_offset
, 0, align
);
4205 next_offset
+= align
;
4207 SIVAL(data
, ofs
, next_offset
- ofs
);
4216 return NT_STATUS_OK
;
4219 /****************************************************************************
4220 Reply to a TRANSACT2_QFILEINFO on a PIPE !
4221 ****************************************************************************/
4223 static void call_trans2qpipeinfo(connection_struct
*conn
,
4224 struct smb_request
*req
,
4225 unsigned int tran_call
,
4226 char **pparams
, int total_params
,
4227 char **ppdata
, int total_data
,
4228 unsigned int max_data_bytes
)
4230 char *params
= *pparams
;
4231 char *pdata
= *ppdata
;
4232 unsigned int data_size
= 0;
4233 unsigned int param_size
= 2;
4238 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4242 if (total_params
< 4) {
4243 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4247 fsp
= file_fsp(req
, SVAL(params
,0));
4248 if (!fsp_is_np(fsp
)) {
4249 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
4253 info_level
= SVAL(params
,2);
4255 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
4256 if (*pparams
== NULL
) {
4257 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
4262 data_size
= max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
;
4263 *ppdata
= (char *)SMB_REALLOC(*ppdata
, data_size
);
4264 if (*ppdata
== NULL
) {
4265 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
4270 switch (info_level
) {
4271 case SMB_FILE_STANDARD_INFORMATION
:
4273 SOFF_T(pdata
,0,4096LL);
4280 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
4284 send_trans2_replies(conn
, req
, params
, param_size
, *ppdata
, data_size
,
4290 NTSTATUS
smbd_do_qfilepathinfo(connection_struct
*conn
,
4291 TALLOC_CTX
*mem_ctx
,
4292 uint16_t info_level
,
4294 struct smb_filename
*smb_fname
,
4295 bool delete_pending
,
4296 struct timespec write_time_ts
,
4297 struct ea_list
*ea_list
,
4298 int lock_data_count
,
4301 unsigned int max_data_bytes
,
4303 unsigned int *pdata_size
)
4305 char *pdata
= *ppdata
;
4306 char *dstart
, *dend
;
4307 unsigned int data_size
;
4308 struct timespec create_time_ts
, mtime_ts
, atime_ts
, ctime_ts
;
4309 time_t create_time
, mtime
, atime
, c_time
;
4310 SMB_STRUCT_STAT
*psbuf
= &smb_fname
->st
;
4317 uint64_t file_size
= 0;
4319 uint64_t allocation_size
= 0;
4320 uint64_t file_index
= 0;
4321 uint32_t access_mask
= 0;
4323 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
4324 return NT_STATUS_INVALID_LEVEL
;
4327 DEBUG(5,("smbd_do_qfilepathinfo: %s (%s) level=%d max_data=%u\n",
4328 smb_fname_str_dbg(smb_fname
),
4330 info_level
, max_data_bytes
));
4332 mode
= dos_mode(conn
, smb_fname
);
4333 nlink
= psbuf
->st_ex_nlink
;
4335 if (nlink
&& (mode
&FILE_ATTRIBUTE_DIRECTORY
)) {
4339 if ((nlink
> 0) && delete_pending
) {
4343 data_size
= max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
;
4344 *ppdata
= (char *)SMB_REALLOC(*ppdata
, data_size
);
4345 if (*ppdata
== NULL
) {
4346 return NT_STATUS_NO_MEMORY
;
4350 dend
= dstart
+ data_size
- 1;
4352 if (!null_timespec(write_time_ts
) && !INFO_LEVEL_IS_UNIX(info_level
)) {
4353 update_stat_ex_mtime(psbuf
, write_time_ts
);
4356 create_time_ts
= get_create_timespec(conn
, fsp
, smb_fname
);
4357 mtime_ts
= psbuf
->st_ex_mtime
;
4358 atime_ts
= psbuf
->st_ex_atime
;
4359 ctime_ts
= get_change_timespec(conn
, fsp
, smb_fname
);
4361 if (lp_dos_filetime_resolution(SNUM(conn
))) {
4362 dos_filetime_timespec(&create_time_ts
);
4363 dos_filetime_timespec(&mtime_ts
);
4364 dos_filetime_timespec(&atime_ts
);
4365 dos_filetime_timespec(&ctime_ts
);
4368 create_time
= convert_timespec_to_time_t(create_time_ts
);
4369 mtime
= convert_timespec_to_time_t(mtime_ts
);
4370 atime
= convert_timespec_to_time_t(atime_ts
);
4371 c_time
= convert_timespec_to_time_t(ctime_ts
);
4373 p
= strrchr_m(smb_fname
->base_name
,'/');
4375 base_name
= smb_fname
->base_name
;
4379 /* NT expects the name to be in an exact form of the *full*
4380 filename. See the trans2 torture test */
4381 if (ISDOT(base_name
)) {
4382 dos_fname
= talloc_strdup(mem_ctx
, "\\");
4384 return NT_STATUS_NO_MEMORY
;
4387 dos_fname
= talloc_asprintf(mem_ctx
,
4389 smb_fname
->base_name
);
4391 return NT_STATUS_NO_MEMORY
;
4393 if (is_ntfs_stream_smb_fname(smb_fname
)) {
4394 dos_fname
= talloc_asprintf(dos_fname
, "%s",
4395 smb_fname
->stream_name
);
4397 return NT_STATUS_NO_MEMORY
;
4401 string_replace(dos_fname
, '/', '\\');
4404 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
, fsp
, psbuf
);
4407 /* Do we have this path open ? */
4409 struct file_id fileid
= vfs_file_id_from_sbuf(conn
, psbuf
);
4410 fsp1
= file_find_di_first(conn
->sconn
, fileid
);
4411 if (fsp1
&& fsp1
->initial_allocation_size
) {
4412 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
, fsp1
, psbuf
);
4416 if (!(mode
& FILE_ATTRIBUTE_DIRECTORY
)) {
4417 file_size
= get_file_size_stat(psbuf
);
4421 pos
= fsp
->fh
->position_information
;
4425 access_mask
= fsp
->access_mask
;
4427 /* GENERIC_EXECUTE mapping from Windows */
4428 access_mask
= 0x12019F;
4431 /* This should be an index number - looks like
4434 I think this causes us to fail the IFSKIT
4435 BasicFileInformationTest. -tpot */
4436 file_index
= get_FileIndex(conn
, psbuf
);
4438 switch (info_level
) {
4439 case SMB_INFO_STANDARD
:
4440 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4442 srv_put_dos_date2(pdata
,l1_fdateCreation
,create_time
);
4443 srv_put_dos_date2(pdata
,l1_fdateLastAccess
,atime
);
4444 srv_put_dos_date2(pdata
,l1_fdateLastWrite
,mtime
); /* write time */
4445 SIVAL(pdata
,l1_cbFile
,(uint32
)file_size
);
4446 SIVAL(pdata
,l1_cbFileAlloc
,(uint32
)allocation_size
);
4447 SSVAL(pdata
,l1_attrFile
,mode
);
4450 case SMB_INFO_QUERY_EA_SIZE
:
4452 unsigned int ea_size
=
4453 estimate_ea_size(conn
, fsp
,
4455 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4457 srv_put_dos_date2(pdata
,0,create_time
);
4458 srv_put_dos_date2(pdata
,4,atime
);
4459 srv_put_dos_date2(pdata
,8,mtime
); /* write time */
4460 SIVAL(pdata
,12,(uint32
)file_size
);
4461 SIVAL(pdata
,16,(uint32
)allocation_size
);
4462 SSVAL(pdata
,20,mode
);
4463 SIVAL(pdata
,22,ea_size
);
4467 case SMB_INFO_IS_NAME_VALID
:
4468 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4470 /* os/2 needs this ? really ?*/
4471 return NT_STATUS_DOS(ERRDOS
, ERRbadfunc
);
4473 /* This is only reached for qpathinfo */
4477 case SMB_INFO_QUERY_EAS_FROM_LIST
:
4479 size_t total_ea_len
= 0;
4480 struct ea_list
*ea_file_list
= NULL
;
4481 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4484 get_ea_list_from_file(mem_ctx
, conn
, fsp
,
4486 &total_ea_len
, &ea_file_list
);
4487 if (!NT_STATUS_IS_OK(status
)) {
4491 ea_list
= ea_list_union(ea_list
, ea_file_list
, &total_ea_len
);
4493 if (!ea_list
|| (total_ea_len
> data_size
)) {
4495 SIVAL(pdata
,0,4); /* EA List Length must be set to 4 if no EA's. */
4499 data_size
= fill_ea_buffer(mem_ctx
, pdata
, data_size
, conn
, ea_list
);
4503 case SMB_INFO_QUERY_ALL_EAS
:
4505 /* We have data_size bytes to put EA's into. */
4506 size_t total_ea_len
= 0;
4507 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4509 status
= get_ea_list_from_file(mem_ctx
, conn
, fsp
,
4511 &total_ea_len
, &ea_list
);
4512 if (!NT_STATUS_IS_OK(status
)) {
4516 if (!ea_list
|| (total_ea_len
> data_size
)) {
4518 SIVAL(pdata
,0,4); /* EA List Length must be set to 4 if no EA's. */
4522 data_size
= fill_ea_buffer(mem_ctx
, pdata
, data_size
, conn
, ea_list
);
4526 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
4528 /* This is FileFullEaInformation - 0xF which maps to
4529 * 1015 (decimal) in smbd_do_setfilepathinfo. */
4531 /* We have data_size bytes to put EA's into. */
4532 size_t total_ea_len
= 0;
4533 struct ea_list
*ea_file_list
= NULL
;
4535 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
4537 /*TODO: add filtering and index handling */
4540 get_ea_list_from_file(mem_ctx
, conn
, fsp
,
4542 &total_ea_len
, &ea_file_list
);
4543 if (!NT_STATUS_IS_OK(status
)) {
4546 if (!ea_file_list
) {
4547 return NT_STATUS_NO_EAS_ON_FILE
;
4550 status
= fill_ea_chained_buffer(mem_ctx
,
4554 conn
, ea_file_list
);
4555 if (!NT_STATUS_IS_OK(status
)) {
4561 case SMB_FILE_BASIC_INFORMATION
:
4562 case SMB_QUERY_FILE_BASIC_INFO
:
4564 if (info_level
== SMB_QUERY_FILE_BASIC_INFO
) {
4565 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4566 data_size
= 36; /* w95 returns 40 bytes not 36 - why ?. */
4568 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4572 put_long_date_timespec(conn
->ts_res
,pdata
,create_time_ts
);
4573 put_long_date_timespec(conn
->ts_res
,pdata
+8,atime_ts
);
4574 put_long_date_timespec(conn
->ts_res
,pdata
+16,mtime_ts
); /* write time */
4575 put_long_date_timespec(conn
->ts_res
,pdata
+24,ctime_ts
); /* change time */
4576 SIVAL(pdata
,32,mode
);
4578 DEBUG(5,("SMB_QFBI - "));
4579 DEBUG(5,("create: %s ", ctime(&create_time
)));
4580 DEBUG(5,("access: %s ", ctime(&atime
)));
4581 DEBUG(5,("write: %s ", ctime(&mtime
)));
4582 DEBUG(5,("change: %s ", ctime(&c_time
)));
4583 DEBUG(5,("mode: %x\n", mode
));
4586 case SMB_FILE_STANDARD_INFORMATION
:
4587 case SMB_QUERY_FILE_STANDARD_INFO
:
4589 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4591 SOFF_T(pdata
,0,allocation_size
);
4592 SOFF_T(pdata
,8,file_size
);
4593 SIVAL(pdata
,16,nlink
);
4594 SCVAL(pdata
,20,delete_pending
?1:0);
4595 SCVAL(pdata
,21,(mode
&FILE_ATTRIBUTE_DIRECTORY
)?1:0);
4596 SSVAL(pdata
,22,0); /* Padding. */
4599 case SMB_FILE_EA_INFORMATION
:
4600 case SMB_QUERY_FILE_EA_INFO
:
4602 unsigned int ea_size
=
4603 estimate_ea_size(conn
, fsp
, smb_fname
);
4604 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4606 SIVAL(pdata
,0,ea_size
);
4610 /* Get the 8.3 name - used if NT SMB was negotiated. */
4611 case SMB_QUERY_FILE_ALT_NAME_INFO
:
4612 case SMB_FILE_ALTERNATE_NAME_INFORMATION
:
4615 char mangled_name
[13];
4616 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4617 if (!name_to_8_3(base_name
,mangled_name
,
4618 True
,conn
->params
)) {
4619 return NT_STATUS_NO_MEMORY
;
4621 len
= srvstr_push(dstart
, flags2
,
4622 pdata
+4, mangled_name
,
4623 PTR_DIFF(dend
, pdata
+4),
4625 data_size
= 4 + len
;
4630 case SMB_QUERY_FILE_NAME_INFO
:
4634 this must be *exactly* right for ACLs on mapped drives to work
4636 len
= srvstr_push(dstart
, flags2
,
4638 PTR_DIFF(dend
, pdata
+4),
4640 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4641 data_size
= 4 + len
;
4646 case SMB_FILE_ALLOCATION_INFORMATION
:
4647 case SMB_QUERY_FILE_ALLOCATION_INFO
:
4648 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4650 SOFF_T(pdata
,0,allocation_size
);
4653 case SMB_FILE_END_OF_FILE_INFORMATION
:
4654 case SMB_QUERY_FILE_END_OF_FILEINFO
:
4655 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4657 SOFF_T(pdata
,0,file_size
);
4660 case SMB_QUERY_FILE_ALL_INFO
:
4661 case SMB_FILE_ALL_INFORMATION
:
4664 unsigned int ea_size
=
4665 estimate_ea_size(conn
, fsp
, smb_fname
);
4666 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4667 put_long_date_timespec(conn
->ts_res
,pdata
,create_time_ts
);
4668 put_long_date_timespec(conn
->ts_res
,pdata
+8,atime_ts
);
4669 put_long_date_timespec(conn
->ts_res
,pdata
+16,mtime_ts
); /* write time */
4670 put_long_date_timespec(conn
->ts_res
,pdata
+24,ctime_ts
); /* change time */
4671 SIVAL(pdata
,32,mode
);
4672 SIVAL(pdata
,36,0); /* padding. */
4674 SOFF_T(pdata
,0,allocation_size
);
4675 SOFF_T(pdata
,8,file_size
);
4676 SIVAL(pdata
,16,nlink
);
4677 SCVAL(pdata
,20,delete_pending
);
4678 SCVAL(pdata
,21,(mode
&FILE_ATTRIBUTE_DIRECTORY
)?1:0);
4681 SIVAL(pdata
,0,ea_size
);
4682 pdata
+= 4; /* EA info */
4683 len
= srvstr_push(dstart
, flags2
,
4685 PTR_DIFF(dend
, pdata
+4),
4689 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4693 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
4696 unsigned int ea_size
=
4697 estimate_ea_size(conn
, fsp
, smb_fname
);
4698 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
4699 put_long_date_timespec(conn
->ts_res
,pdata
+0x00,create_time_ts
);
4700 put_long_date_timespec(conn
->ts_res
,pdata
+0x08,atime_ts
);
4701 put_long_date_timespec(conn
->ts_res
,pdata
+0x10,mtime_ts
); /* write time */
4702 put_long_date_timespec(conn
->ts_res
,pdata
+0x18,ctime_ts
); /* change time */
4703 SIVAL(pdata
, 0x20, mode
);
4704 SIVAL(pdata
, 0x24, 0); /* padding. */
4705 SBVAL(pdata
, 0x28, allocation_size
);
4706 SBVAL(pdata
, 0x30, file_size
);
4707 SIVAL(pdata
, 0x38, nlink
);
4708 SCVAL(pdata
, 0x3C, delete_pending
);
4709 SCVAL(pdata
, 0x3D, (mode
&FILE_ATTRIBUTE_DIRECTORY
)?1:0);
4710 SSVAL(pdata
, 0x3E, 0); /* padding */
4711 SBVAL(pdata
, 0x40, file_index
);
4712 SIVAL(pdata
, 0x48, ea_size
);
4713 SIVAL(pdata
, 0x4C, access_mask
);
4714 SBVAL(pdata
, 0x50, pos
);
4715 SIVAL(pdata
, 0x58, mode
); /*TODO: mode != mode fix this!!! */
4716 SIVAL(pdata
, 0x5C, 0); /* No alignment needed. */
4720 len
= srvstr_push(dstart
, flags2
,
4722 PTR_DIFF(dend
, pdata
+4),
4726 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4729 case SMB_FILE_INTERNAL_INFORMATION
:
4731 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4732 SBVAL(pdata
, 0, file_index
);
4736 case SMB_FILE_ACCESS_INFORMATION
:
4737 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4738 SIVAL(pdata
, 0, access_mask
);
4742 case SMB_FILE_NAME_INFORMATION
:
4743 /* Pathname with leading '\'. */
4746 byte_len
= dos_PutUniCode(pdata
+4,dos_fname
,(size_t)max_data_bytes
,False
);
4747 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4748 SIVAL(pdata
,0,byte_len
);
4749 data_size
= 4 + byte_len
;
4753 case SMB_FILE_DISPOSITION_INFORMATION
:
4754 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4756 SCVAL(pdata
,0,delete_pending
);
4759 case SMB_FILE_POSITION_INFORMATION
:
4760 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4762 SOFF_T(pdata
,0,pos
);
4765 case SMB_FILE_MODE_INFORMATION
:
4766 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4767 SIVAL(pdata
,0,mode
);
4771 case SMB_FILE_ALIGNMENT_INFORMATION
:
4772 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4773 SIVAL(pdata
,0,0); /* No alignment needed. */
4778 * NT4 server just returns "invalid query" to this - if we try
4779 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4782 /* The first statement above is false - verified using Thursby
4783 * client against NT4 -- gcolley.
4785 case SMB_QUERY_FILE_STREAM_INFO
:
4786 case SMB_FILE_STREAM_INFORMATION
: {
4787 unsigned int num_streams
= 0;
4788 struct stream_struct
*streams
= NULL
;
4790 DEBUG(10,("smbd_do_qfilepathinfo: "
4791 "SMB_FILE_STREAM_INFORMATION\n"));
4793 if (is_ntfs_stream_smb_fname(smb_fname
)) {
4794 return NT_STATUS_INVALID_PARAMETER
;
4797 status
= vfs_streaminfo(conn
, fsp
, smb_fname
->base_name
,
4798 talloc_tos(), &num_streams
, &streams
);
4800 if (!NT_STATUS_IS_OK(status
)) {
4801 DEBUG(10, ("could not get stream info: %s\n",
4802 nt_errstr(status
)));
4806 status
= marshall_stream_info(num_streams
, streams
,
4807 pdata
, max_data_bytes
,
4810 if (!NT_STATUS_IS_OK(status
)) {
4811 DEBUG(10, ("marshall_stream_info failed: %s\n",
4812 nt_errstr(status
)));
4816 TALLOC_FREE(streams
);
4820 case SMB_QUERY_COMPRESSION_INFO
:
4821 case SMB_FILE_COMPRESSION_INFORMATION
:
4822 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4823 SOFF_T(pdata
,0,file_size
);
4824 SIVAL(pdata
,8,0); /* ??? */
4825 SIVAL(pdata
,12,0); /* ??? */
4829 case SMB_FILE_NETWORK_OPEN_INFORMATION
:
4830 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4831 put_long_date_timespec(conn
->ts_res
,pdata
,create_time_ts
);
4832 put_long_date_timespec(conn
->ts_res
,pdata
+8,atime_ts
);
4833 put_long_date_timespec(conn
->ts_res
,pdata
+16,mtime_ts
); /* write time */
4834 put_long_date_timespec(conn
->ts_res
,pdata
+24,ctime_ts
); /* change time */
4835 SOFF_T(pdata
,32,allocation_size
);
4836 SOFF_T(pdata
,40,file_size
);
4837 SIVAL(pdata
,48,mode
);
4838 SIVAL(pdata
,52,0); /* ??? */
4842 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION
:
4843 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4844 SIVAL(pdata
,0,mode
);
4850 * CIFS UNIX Extensions.
4853 case SMB_QUERY_FILE_UNIX_BASIC
:
4855 pdata
= store_file_unix_basic(conn
, pdata
, fsp
, psbuf
);
4856 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4858 DEBUG(4,("smbd_do_qfilepathinfo: "
4859 "SMB_QUERY_FILE_UNIX_BASIC\n"));
4860 dump_data(4, (uint8_t *)(*ppdata
), data_size
);
4864 case SMB_QUERY_FILE_UNIX_INFO2
:
4866 pdata
= store_file_unix_basic_info2(conn
, pdata
, fsp
, psbuf
);
4867 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4871 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4873 for (i
=0; i
<100; i
++)
4874 DEBUG(4,("%d=%x, ",i
, (*ppdata
)[i
]));
4880 case SMB_QUERY_FILE_UNIX_LINK
:
4883 char *buffer
= talloc_array(mem_ctx
, char, PATH_MAX
+1);
4886 return NT_STATUS_NO_MEMORY
;
4889 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4891 if(!S_ISLNK(psbuf
->st_ex_mode
)) {
4892 return NT_STATUS_DOS(ERRSRV
, ERRbadlink
);
4895 return NT_STATUS_DOS(ERRDOS
, ERRbadlink
);
4897 len
= SMB_VFS_READLINK(conn
,
4898 smb_fname
->base_name
,
4901 return map_nt_error_from_unix(errno
);
4904 len
= srvstr_push(dstart
, flags2
,
4906 PTR_DIFF(dend
, pdata
),
4909 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4914 #if defined(HAVE_POSIX_ACLS)
4915 case SMB_QUERY_POSIX_ACL
:
4917 SMB_ACL_T file_acl
= NULL
;
4918 SMB_ACL_T def_acl
= NULL
;
4919 uint16 num_file_acls
= 0;
4920 uint16 num_def_acls
= 0;
4922 if (fsp
&& fsp
->fh
->fd
!= -1) {
4923 file_acl
= SMB_VFS_SYS_ACL_GET_FD(fsp
);
4926 SMB_VFS_SYS_ACL_GET_FILE(conn
,
4927 smb_fname
->base_name
,
4928 SMB_ACL_TYPE_ACCESS
);
4931 if (file_acl
== NULL
&& no_acl_syscall_error(errno
)) {
4932 DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
4933 "not implemented on "
4934 "filesystem containing %s\n",
4935 smb_fname
->base_name
));
4936 return NT_STATUS_NOT_IMPLEMENTED
;
4939 if (S_ISDIR(psbuf
->st_ex_mode
)) {
4940 if (fsp
&& fsp
->is_directory
) {
4942 SMB_VFS_SYS_ACL_GET_FILE(
4944 fsp
->fsp_name
->base_name
,
4945 SMB_ACL_TYPE_DEFAULT
);
4948 SMB_VFS_SYS_ACL_GET_FILE(
4950 smb_fname
->base_name
,
4951 SMB_ACL_TYPE_DEFAULT
);
4953 def_acl
= free_empty_sys_acl(conn
, def_acl
);
4956 num_file_acls
= count_acl_entries(conn
, file_acl
);
4957 num_def_acls
= count_acl_entries(conn
, def_acl
);
4959 if ( data_size
< (num_file_acls
+ num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
+ SMB_POSIX_ACL_HEADER_SIZE
) {
4960 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
4962 (unsigned int)((num_file_acls
+ num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
+
4963 SMB_POSIX_ACL_HEADER_SIZE
) ));
4965 TALLOC_FREE(file_acl
);
4968 TALLOC_FREE(def_acl
);
4970 return NT_STATUS_BUFFER_TOO_SMALL
;
4973 SSVAL(pdata
,0,SMB_POSIX_ACL_VERSION
);
4974 SSVAL(pdata
,2,num_file_acls
);
4975 SSVAL(pdata
,4,num_def_acls
);
4976 if (!marshall_posix_acl(conn
, pdata
+ SMB_POSIX_ACL_HEADER_SIZE
, psbuf
, file_acl
)) {
4978 TALLOC_FREE(file_acl
);
4981 TALLOC_FREE(def_acl
);
4983 return NT_STATUS_INTERNAL_ERROR
;
4985 if (!marshall_posix_acl(conn
, pdata
+ SMB_POSIX_ACL_HEADER_SIZE
+ (num_file_acls
*SMB_POSIX_ACL_ENTRY_SIZE
), psbuf
, def_acl
)) {
4987 TALLOC_FREE(file_acl
);
4990 TALLOC_FREE(def_acl
);
4992 return NT_STATUS_INTERNAL_ERROR
;
4996 TALLOC_FREE(file_acl
);
4999 TALLOC_FREE(def_acl
);
5001 data_size
= (num_file_acls
+ num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
+ SMB_POSIX_ACL_HEADER_SIZE
;
5007 case SMB_QUERY_POSIX_LOCK
:
5012 enum brl_type lock_type
;
5014 /* We need an open file with a real fd for this. */
5015 if (!fsp
|| fsp
->fh
->fd
== -1) {
5016 return NT_STATUS_INVALID_LEVEL
;
5019 if (lock_data_count
!= POSIX_LOCK_DATA_SIZE
) {
5020 return NT_STATUS_INVALID_PARAMETER
;
5023 switch (SVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
)) {
5024 case POSIX_LOCK_TYPE_READ
:
5025 lock_type
= READ_LOCK
;
5027 case POSIX_LOCK_TYPE_WRITE
:
5028 lock_type
= WRITE_LOCK
;
5030 case POSIX_LOCK_TYPE_UNLOCK
:
5032 /* There's no point in asking for an unlock... */
5033 return NT_STATUS_INVALID_PARAMETER
;
5036 smblctx
= (uint64_t)IVAL(pdata
, POSIX_LOCK_PID_OFFSET
);
5037 #if defined(HAVE_LONGLONG)
5038 offset
= (((uint64_t) IVAL(pdata
,(POSIX_LOCK_START_OFFSET
+4))) << 32) |
5039 ((uint64_t) IVAL(pdata
,POSIX_LOCK_START_OFFSET
));
5040 count
= (((uint64_t) IVAL(pdata
,(POSIX_LOCK_LEN_OFFSET
+4))) << 32) |
5041 ((uint64_t) IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
));
5042 #else /* HAVE_LONGLONG */
5043 offset
= (uint64_t)IVAL(pdata
,POSIX_LOCK_START_OFFSET
);
5044 count
= (uint64_t)IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
);
5045 #endif /* HAVE_LONGLONG */
5047 status
= query_lock(fsp
,
5054 if (ERROR_WAS_LOCK_DENIED(status
)) {
5055 /* Here we need to report who has it locked... */
5056 data_size
= POSIX_LOCK_DATA_SIZE
;
5058 SSVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
, lock_type
);
5059 SSVAL(pdata
, POSIX_LOCK_FLAGS_OFFSET
, 0);
5060 SIVAL(pdata
, POSIX_LOCK_PID_OFFSET
, (uint32_t)smblctx
);
5061 #if defined(HAVE_LONGLONG)
5062 SIVAL(pdata
, POSIX_LOCK_START_OFFSET
, (uint32
)(offset
& 0xFFFFFFFF));
5063 SIVAL(pdata
, POSIX_LOCK_START_OFFSET
+ 4, (uint32
)((offset
>> 32) & 0xFFFFFFFF));
5064 SIVAL(pdata
, POSIX_LOCK_LEN_OFFSET
, (uint32
)(count
& 0xFFFFFFFF));
5065 SIVAL(pdata
, POSIX_LOCK_LEN_OFFSET
+ 4, (uint32
)((count
>> 32) & 0xFFFFFFFF));
5066 #else /* HAVE_LONGLONG */
5067 SIVAL(pdata
, POSIX_LOCK_START_OFFSET
, offset
);
5068 SIVAL(pdata
, POSIX_LOCK_LEN_OFFSET
, count
);
5069 #endif /* HAVE_LONGLONG */
5071 } else if (NT_STATUS_IS_OK(status
)) {
5072 /* For success we just return a copy of what we sent
5073 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
5074 data_size
= POSIX_LOCK_DATA_SIZE
;
5075 memcpy(pdata
, lock_data
, POSIX_LOCK_DATA_SIZE
);
5076 SSVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
, POSIX_LOCK_TYPE_UNLOCK
);
5084 return NT_STATUS_INVALID_LEVEL
;
5087 *pdata_size
= data_size
;
5088 return NT_STATUS_OK
;
5091 /****************************************************************************
5092 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
5093 file name or file id).
5094 ****************************************************************************/
5096 static void call_trans2qfilepathinfo(connection_struct
*conn
,
5097 struct smb_request
*req
,
5098 unsigned int tran_call
,
5099 char **pparams
, int total_params
,
5100 char **ppdata
, int total_data
,
5101 unsigned int max_data_bytes
)
5103 char *params
= *pparams
;
5104 char *pdata
= *ppdata
;
5106 unsigned int data_size
= 0;
5107 unsigned int param_size
= 2;
5108 struct smb_filename
*smb_fname
= NULL
;
5109 bool delete_pending
= False
;
5110 struct timespec write_time_ts
;
5111 files_struct
*fsp
= NULL
;
5112 struct file_id fileid
;
5113 struct ea_list
*ea_list
= NULL
;
5114 int lock_data_count
= 0;
5115 char *lock_data
= NULL
;
5116 NTSTATUS status
= NT_STATUS_OK
;
5119 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5123 ZERO_STRUCT(write_time_ts
);
5125 if (tran_call
== TRANSACT2_QFILEINFO
) {
5126 if (total_params
< 4) {
5127 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5132 call_trans2qpipeinfo(conn
, req
, tran_call
,
5133 pparams
, total_params
,
5139 fsp
= file_fsp(req
, SVAL(params
,0));
5140 info_level
= SVAL(params
,2);
5142 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level
));
5144 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
5145 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
5149 /* Initial check for valid fsp ptr. */
5150 if (!check_fsp_open(conn
, req
, fsp
)) {
5154 status
= copy_smb_filename(talloc_tos(), fsp
->fsp_name
,
5156 if (!NT_STATUS_IS_OK(status
)) {
5157 reply_nterror(req
, status
);
5161 if(fsp
->fake_file_handle
) {
5163 * This is actually for the QUOTA_FAKE_FILE --metze
5166 /* We know this name is ok, it's already passed the checks. */
5168 } else if(fsp
->fh
->fd
== -1) {
5170 * This is actually a QFILEINFO on a directory
5171 * handle (returned from an NT SMB). NT5.0 seems
5172 * to do this call. JRA.
5175 if (INFO_LEVEL_IS_UNIX(info_level
)) {
5176 /* Always do lstat for UNIX calls. */
5177 if (SMB_VFS_LSTAT(conn
, smb_fname
)) {
5178 DEBUG(3,("call_trans2qfilepathinfo: "
5179 "SMB_VFS_LSTAT of %s failed "
5181 smb_fname_str_dbg(smb_fname
),
5184 map_nt_error_from_unix(errno
));
5187 } else if (SMB_VFS_STAT(conn
, smb_fname
)) {
5188 DEBUG(3,("call_trans2qfilepathinfo: "
5189 "SMB_VFS_STAT of %s failed (%s)\n",
5190 smb_fname_str_dbg(smb_fname
),
5193 map_nt_error_from_unix(errno
));
5197 fileid
= vfs_file_id_from_sbuf(conn
, &smb_fname
->st
);
5198 get_file_infos(fileid
, fsp
->name_hash
, &delete_pending
, &write_time_ts
);
5201 * Original code - this is an open file.
5203 if (SMB_VFS_FSTAT(fsp
, &smb_fname
->st
) != 0) {
5204 DEBUG(3, ("fstat of %s failed (%s)\n",
5205 fsp_fnum_dbg(fsp
), strerror(errno
)));
5207 map_nt_error_from_unix(errno
));
5210 fileid
= vfs_file_id_from_sbuf(conn
, &smb_fname
->st
);
5211 get_file_infos(fileid
, fsp
->name_hash
, &delete_pending
, &write_time_ts
);
5217 uint32_t ucf_flags
= 0;
5220 if (total_params
< 7) {
5221 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5225 info_level
= SVAL(params
,0);
5227 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level
));
5229 if (INFO_LEVEL_IS_UNIX(info_level
)) {
5230 if (!lp_unix_extensions()) {
5231 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
5234 if (info_level
== SMB_QUERY_FILE_UNIX_BASIC
||
5235 info_level
== SMB_QUERY_FILE_UNIX_INFO2
||
5236 info_level
== SMB_QUERY_FILE_UNIX_LINK
) {
5237 ucf_flags
|= UCF_UNIX_NAME_LOOKUP
;
5241 srvstr_get_path(req
, params
, req
->flags2
, &fname
, ¶ms
[6],
5243 STR_TERMINATE
, &status
);
5244 if (!NT_STATUS_IS_OK(status
)) {
5245 reply_nterror(req
, status
);
5249 status
= filename_convert(req
,
5251 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
5256 if (!NT_STATUS_IS_OK(status
)) {
5257 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
5258 reply_botherror(req
,
5259 NT_STATUS_PATH_NOT_COVERED
,
5260 ERRSRV
, ERRbadpath
);
5263 reply_nterror(req
, status
);
5267 /* If this is a stream, check if there is a delete_pending. */
5268 if ((conn
->fs_capabilities
& FILE_NAMED_STREAMS
)
5269 && is_ntfs_stream_smb_fname(smb_fname
)) {
5270 struct smb_filename
*smb_fname_base
= NULL
;
5272 /* Create an smb_filename with stream_name == NULL. */
5274 create_synthetic_smb_fname(talloc_tos(),
5275 smb_fname
->base_name
,
5278 if (!NT_STATUS_IS_OK(status
)) {
5279 reply_nterror(req
, status
);
5283 if (INFO_LEVEL_IS_UNIX(info_level
)) {
5284 /* Always do lstat for UNIX calls. */
5285 if (SMB_VFS_LSTAT(conn
, smb_fname_base
) != 0) {
5286 DEBUG(3,("call_trans2qfilepathinfo: "
5287 "SMB_VFS_LSTAT of %s failed "
5289 smb_fname_str_dbg(smb_fname_base
),
5291 TALLOC_FREE(smb_fname_base
);
5293 map_nt_error_from_unix(errno
));
5297 if (SMB_VFS_STAT(conn
, smb_fname_base
) != 0) {
5298 DEBUG(3,("call_trans2qfilepathinfo: "
5299 "fileinfo of %s failed "
5301 smb_fname_str_dbg(smb_fname_base
),
5303 TALLOC_FREE(smb_fname_base
);
5305 map_nt_error_from_unix(errno
));
5310 status
= file_name_hash(conn
,
5311 smb_fname_str_dbg(smb_fname_base
),
5313 if (!NT_STATUS_IS_OK(status
)) {
5314 TALLOC_FREE(smb_fname_base
);
5315 reply_nterror(req
, status
);
5319 fileid
= vfs_file_id_from_sbuf(conn
,
5320 &smb_fname_base
->st
);
5321 TALLOC_FREE(smb_fname_base
);
5322 get_file_infos(fileid
, name_hash
, &delete_pending
, NULL
);
5323 if (delete_pending
) {
5324 reply_nterror(req
, NT_STATUS_DELETE_PENDING
);
5329 if (INFO_LEVEL_IS_UNIX(info_level
)) {
5330 /* Always do lstat for UNIX calls. */
5331 if (SMB_VFS_LSTAT(conn
, smb_fname
)) {
5332 DEBUG(3,("call_trans2qfilepathinfo: "
5333 "SMB_VFS_LSTAT of %s failed (%s)\n",
5334 smb_fname_str_dbg(smb_fname
),
5337 map_nt_error_from_unix(errno
));
5342 if (SMB_VFS_STAT(conn
, smb_fname
) != 0) {
5343 DEBUG(3,("call_trans2qfilepathinfo: "
5344 "SMB_VFS_STAT of %s failed (%s)\n",
5345 smb_fname_str_dbg(smb_fname
),
5348 map_nt_error_from_unix(errno
));
5353 status
= file_name_hash(conn
,
5354 smb_fname_str_dbg(smb_fname
),
5356 if (!NT_STATUS_IS_OK(status
)) {
5357 reply_nterror(req
, status
);
5361 fileid
= vfs_file_id_from_sbuf(conn
, &smb_fname
->st
);
5362 get_file_infos(fileid
, name_hash
, &delete_pending
, &write_time_ts
);
5363 if (delete_pending
) {
5364 reply_nterror(req
, NT_STATUS_DELETE_PENDING
);
5369 DEBUG(3,("call_trans2qfilepathinfo %s (%s) level=%d call=%d "
5370 "total_data=%d\n", smb_fname_str_dbg(smb_fname
),
5372 info_level
,tran_call
,total_data
));
5374 /* Pull out any data sent here before we realloc. */
5375 switch (info_level
) {
5376 case SMB_INFO_QUERY_EAS_FROM_LIST
:
5378 /* Pull any EA list from the data portion. */
5381 if (total_data
< 4) {
5383 req
, NT_STATUS_INVALID_PARAMETER
);
5386 ea_size
= IVAL(pdata
,0);
5388 if (total_data
> 0 && ea_size
!= total_data
) {
5389 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5390 total_data=%u (should be %u)\n", (unsigned int)total_data
, (unsigned int)IVAL(pdata
,0) ));
5392 req
, NT_STATUS_INVALID_PARAMETER
);
5396 if (!lp_ea_support(SNUM(conn
))) {
5397 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
5401 /* Pull out the list of names. */
5402 ea_list
= read_ea_name_list(req
, pdata
+ 4, ea_size
- 4);
5405 req
, NT_STATUS_INVALID_PARAMETER
);
5411 case SMB_QUERY_POSIX_LOCK
:
5413 if (fsp
== NULL
|| fsp
->fh
->fd
== -1) {
5414 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
5418 if (total_data
!= POSIX_LOCK_DATA_SIZE
) {
5420 req
, NT_STATUS_INVALID_PARAMETER
);
5424 /* Copy the lock range data. */
5425 lock_data
= (char *)talloc_memdup(
5426 req
, pdata
, total_data
);
5428 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5431 lock_data_count
= total_data
;
5437 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
5438 if (*pparams
== NULL
) {
5439 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5446 * draft-leach-cifs-v1-spec-02.txt
5447 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
5450 * The requested information is placed in the Data portion of the
5451 * transaction response. For the information levels greater than 0x100,
5452 * the transaction response has 1 parameter word which should be
5453 * ignored by the client.
5455 * However Windows only follows this rule for the IS_NAME_VALID call.
5457 switch (info_level
) {
5458 case SMB_INFO_IS_NAME_VALID
:
5463 if ((info_level
& 0xFF00) == 0xFF00) {
5465 * We use levels that start with 0xFF00
5466 * internally to represent SMB2 specific levels
5468 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
5472 status
= smbd_do_qfilepathinfo(conn
, req
, info_level
,
5474 delete_pending
, write_time_ts
,
5476 lock_data_count
, lock_data
,
5477 req
->flags2
, max_data_bytes
,
5478 ppdata
, &data_size
);
5479 if (!NT_STATUS_IS_OK(status
)) {
5480 reply_nterror(req
, status
);
5484 send_trans2_replies(conn
, req
, params
, param_size
, *ppdata
, data_size
,
5490 /****************************************************************************
5491 Set a hard link (called by UNIX extensions and by NT rename with HARD link
5493 ****************************************************************************/
5495 NTSTATUS
hardlink_internals(TALLOC_CTX
*ctx
,
5496 connection_struct
*conn
,
5497 struct smb_request
*req
,
5498 bool overwrite_if_exists
,
5499 const struct smb_filename
*smb_fname_old
,
5500 struct smb_filename
*smb_fname_new
)
5502 NTSTATUS status
= NT_STATUS_OK
;
5504 /* source must already exist. */
5505 if (!VALID_STAT(smb_fname_old
->st
)) {
5506 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5509 if (VALID_STAT(smb_fname_new
->st
)) {
5510 if (overwrite_if_exists
) {
5511 if (S_ISDIR(smb_fname_new
->st
.st_ex_mode
)) {
5512 return NT_STATUS_FILE_IS_A_DIRECTORY
;
5514 status
= unlink_internals(conn
,
5516 FILE_ATTRIBUTE_NORMAL
,
5519 if (!NT_STATUS_IS_OK(status
)) {
5523 /* Disallow if newname already exists. */
5524 return NT_STATUS_OBJECT_NAME_COLLISION
;
5528 /* No links from a directory. */
5529 if (S_ISDIR(smb_fname_old
->st
.st_ex_mode
)) {
5530 return NT_STATUS_FILE_IS_A_DIRECTORY
;
5533 /* Setting a hardlink to/from a stream isn't currently supported. */
5534 if (is_ntfs_stream_smb_fname(smb_fname_old
) ||
5535 is_ntfs_stream_smb_fname(smb_fname_new
)) {
5536 return NT_STATUS_INVALID_PARAMETER
;
5539 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
5540 smb_fname_old
->base_name
, smb_fname_new
->base_name
));
5542 if (SMB_VFS_LINK(conn
, smb_fname_old
->base_name
,
5543 smb_fname_new
->base_name
) != 0) {
5544 status
= map_nt_error_from_unix(errno
);
5545 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
5546 nt_errstr(status
), smb_fname_old
->base_name
,
5547 smb_fname_new
->base_name
));
5552 /****************************************************************************
5553 Deal with setting the time from any of the setfilepathinfo functions.
5554 NOTE !!!! The check for FILE_WRITE_ATTRIBUTES access must be done *before*
5555 calling this function.
5556 ****************************************************************************/
5558 NTSTATUS
smb_set_file_time(connection_struct
*conn
,
5560 const struct smb_filename
*smb_fname
,
5561 struct smb_file_time
*ft
,
5562 bool setting_write_time
)
5564 struct smb_filename smb_fname_base
;
5566 FILE_NOTIFY_CHANGE_LAST_ACCESS
5567 |FILE_NOTIFY_CHANGE_LAST_WRITE
5568 |FILE_NOTIFY_CHANGE_CREATION
;
5570 if (!VALID_STAT(smb_fname
->st
)) {
5571 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5574 /* get some defaults (no modifications) if any info is zero or -1. */
5575 if (null_timespec(ft
->create_time
)) {
5576 action
&= ~FILE_NOTIFY_CHANGE_CREATION
;
5579 if (null_timespec(ft
->atime
)) {
5580 action
&= ~FILE_NOTIFY_CHANGE_LAST_ACCESS
;
5583 if (null_timespec(ft
->mtime
)) {
5584 action
&= ~FILE_NOTIFY_CHANGE_LAST_WRITE
;
5587 if (!setting_write_time
) {
5588 /* ft->mtime comes from change time, not write time. */
5589 action
&= ~FILE_NOTIFY_CHANGE_LAST_WRITE
;
5592 /* Ensure the resolution is the correct for
5593 * what we can store on this filesystem. */
5595 round_timespec(conn
->ts_res
, &ft
->create_time
);
5596 round_timespec(conn
->ts_res
, &ft
->ctime
);
5597 round_timespec(conn
->ts_res
, &ft
->atime
);
5598 round_timespec(conn
->ts_res
, &ft
->mtime
);
5600 DEBUG(5,("smb_set_filetime: actime: %s\n ",
5601 time_to_asc(convert_timespec_to_time_t(ft
->atime
))));
5602 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
5603 time_to_asc(convert_timespec_to_time_t(ft
->mtime
))));
5604 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
5605 time_to_asc(convert_timespec_to_time_t(ft
->ctime
))));
5606 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
5607 time_to_asc(convert_timespec_to_time_t(ft
->create_time
))));
5609 if (setting_write_time
) {
5611 * This was a Windows setfileinfo on an open file.
5612 * NT does this a lot. We also need to
5613 * set the time here, as it can be read by
5614 * FindFirst/FindNext and with the patch for bug #2045
5615 * in smbd/fileio.c it ensures that this timestamp is
5616 * kept sticky even after a write. We save the request
5617 * away and will set it on file close and after a write. JRA.
5620 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
5621 time_to_asc(convert_timespec_to_time_t(ft
->mtime
))));
5624 if (fsp
->base_fsp
) {
5625 set_sticky_write_time_fsp(fsp
->base_fsp
,
5628 set_sticky_write_time_fsp(fsp
, ft
->mtime
);
5631 set_sticky_write_time_path(
5632 vfs_file_id_from_sbuf(conn
, &smb_fname
->st
),
5637 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5639 /* Always call ntimes on the base, even if a stream was passed in. */
5640 smb_fname_base
= *smb_fname
;
5641 smb_fname_base
.stream_name
= NULL
;
5643 if(file_ntimes(conn
, &smb_fname_base
, ft
)!=0) {
5644 return map_nt_error_from_unix(errno
);
5647 notify_fname(conn
, NOTIFY_ACTION_MODIFIED
, action
,
5648 smb_fname
->base_name
);
5649 return NT_STATUS_OK
;
5652 /****************************************************************************
5653 Deal with setting the dosmode from any of the setfilepathinfo functions.
5654 NB. The check for FILE_WRITE_ATTRIBUTES access on this path must have been
5655 done before calling this function.
5656 ****************************************************************************/
5658 static NTSTATUS
smb_set_file_dosmode(connection_struct
*conn
,
5659 const struct smb_filename
*smb_fname
,
5662 struct smb_filename
*smb_fname_base
= NULL
;
5665 if (!VALID_STAT(smb_fname
->st
)) {
5666 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5669 /* Always operate on the base_name, even if a stream was passed in. */
5670 status
= create_synthetic_smb_fname(talloc_tos(), smb_fname
->base_name
,
5671 NULL
, &smb_fname
->st
,
5673 if (!NT_STATUS_IS_OK(status
)) {
5678 if (S_ISDIR(smb_fname_base
->st
.st_ex_mode
)) {
5679 dosmode
|= FILE_ATTRIBUTE_DIRECTORY
;
5681 dosmode
&= ~FILE_ATTRIBUTE_DIRECTORY
;
5685 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode
));
5687 /* check the mode isn't different, before changing it */
5688 if ((dosmode
!= 0) && (dosmode
!= dos_mode(conn
, smb_fname_base
))) {
5689 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
5690 "0x%x\n", smb_fname_str_dbg(smb_fname_base
),
5691 (unsigned int)dosmode
));
5693 if(file_set_dosmode(conn
, smb_fname_base
, dosmode
, NULL
,
5695 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
5697 smb_fname_str_dbg(smb_fname_base
),
5699 status
= map_nt_error_from_unix(errno
);
5703 status
= NT_STATUS_OK
;
5705 TALLOC_FREE(smb_fname_base
);
5709 /****************************************************************************
5710 Deal with setting the size from any of the setfilepathinfo functions.
5711 ****************************************************************************/
5713 static NTSTATUS
smb_set_file_size(connection_struct
*conn
,
5714 struct smb_request
*req
,
5716 const struct smb_filename
*smb_fname
,
5717 const SMB_STRUCT_STAT
*psbuf
,
5719 bool fail_after_createfile
)
5721 NTSTATUS status
= NT_STATUS_OK
;
5722 struct smb_filename
*smb_fname_tmp
= NULL
;
5723 files_struct
*new_fsp
= NULL
;
5725 if (!VALID_STAT(*psbuf
)) {
5726 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5729 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size
));
5731 if (size
== get_file_size_stat(psbuf
)) {
5732 return NT_STATUS_OK
;
5735 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5736 smb_fname_str_dbg(smb_fname
), (double)size
));
5738 if (fsp
&& fsp
->fh
->fd
!= -1) {
5739 /* Handle based call. */
5740 if (!(fsp
->access_mask
& FILE_WRITE_DATA
)) {
5741 return NT_STATUS_ACCESS_DENIED
;
5744 if (vfs_set_filelen(fsp
, size
) == -1) {
5745 return map_nt_error_from_unix(errno
);
5747 trigger_write_time_update_immediate(fsp
);
5748 return NT_STATUS_OK
;
5751 status
= copy_smb_filename(talloc_tos(), smb_fname
, &smb_fname_tmp
);
5752 if (!NT_STATUS_IS_OK(status
)) {
5756 smb_fname_tmp
->st
= *psbuf
;
5758 status
= SMB_VFS_CREATE_FILE(
5761 0, /* root_dir_fid */
5762 smb_fname_tmp
, /* fname */
5763 FILE_WRITE_DATA
, /* access_mask */
5764 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
5766 FILE_OPEN
, /* create_disposition*/
5767 0, /* create_options */
5768 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
5769 FORCE_OPLOCK_BREAK_TO_NONE
, /* oplock_request */
5770 0, /* allocation_size */
5771 0, /* private_flags */
5774 &new_fsp
, /* result */
5777 TALLOC_FREE(smb_fname_tmp
);
5779 if (!NT_STATUS_IS_OK(status
)) {
5780 /* NB. We check for open_was_deferred in the caller. */
5784 /* See RAW-SFILEINFO-END-OF-FILE */
5785 if (fail_after_createfile
) {
5786 close_file(req
, new_fsp
,NORMAL_CLOSE
);
5787 return NT_STATUS_INVALID_LEVEL
;
5790 if (vfs_set_filelen(new_fsp
, size
) == -1) {
5791 status
= map_nt_error_from_unix(errno
);
5792 close_file(req
, new_fsp
,NORMAL_CLOSE
);
5796 trigger_write_time_update_immediate(new_fsp
);
5797 close_file(req
, new_fsp
,NORMAL_CLOSE
);
5798 return NT_STATUS_OK
;
5801 /****************************************************************************
5802 Deal with SMB_INFO_SET_EA.
5803 ****************************************************************************/
5805 static NTSTATUS
smb_info_set_ea(connection_struct
*conn
,
5809 const struct smb_filename
*smb_fname
)
5811 struct ea_list
*ea_list
= NULL
;
5812 TALLOC_CTX
*ctx
= NULL
;
5813 NTSTATUS status
= NT_STATUS_OK
;
5815 if (total_data
< 10) {
5817 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5818 length. They seem to have no effect. Bug #3212. JRA */
5820 if ((total_data
== 4) && (IVAL(pdata
,0) == 4)) {
5821 /* We're done. We only get EA info in this call. */
5822 return NT_STATUS_OK
;
5825 return NT_STATUS_INVALID_PARAMETER
;
5828 if (IVAL(pdata
,0) > total_data
) {
5829 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5830 IVAL(pdata
,0), (unsigned int)total_data
));
5831 return NT_STATUS_INVALID_PARAMETER
;
5835 ea_list
= read_ea_list(ctx
, pdata
+ 4, total_data
- 4);
5837 return NT_STATUS_INVALID_PARAMETER
;
5840 status
= set_ea(conn
, fsp
, smb_fname
, ea_list
);
5845 /****************************************************************************
5846 Deal with SMB_FILE_FULL_EA_INFORMATION set.
5847 ****************************************************************************/
5849 static NTSTATUS
smb_set_file_full_ea_info(connection_struct
*conn
,
5854 struct ea_list
*ea_list
= NULL
;
5858 return NT_STATUS_INVALID_HANDLE
;
5861 if (!lp_ea_support(SNUM(conn
))) {
5862 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
5863 "EA's not supported.\n",
5864 (unsigned int)total_data
));
5865 return NT_STATUS_EAS_NOT_SUPPORTED
;
5868 if (total_data
< 10) {
5869 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
5871 (unsigned int)total_data
));
5872 return NT_STATUS_INVALID_PARAMETER
;
5875 ea_list
= read_nttrans_ea_list(talloc_tos(),
5880 return NT_STATUS_INVALID_PARAMETER
;
5883 status
= set_ea(conn
, fsp
, fsp
->fsp_name
, ea_list
);
5885 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
5886 smb_fname_str_dbg(fsp
->fsp_name
),
5887 nt_errstr(status
) ));
5893 /****************************************************************************
5894 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5895 ****************************************************************************/
5897 static NTSTATUS
smb_set_file_disposition_info(connection_struct
*conn
,
5901 struct smb_filename
*smb_fname
)
5903 NTSTATUS status
= NT_STATUS_OK
;
5904 bool delete_on_close
;
5907 if (total_data
< 1) {
5908 return NT_STATUS_INVALID_PARAMETER
;
5912 return NT_STATUS_INVALID_HANDLE
;
5915 delete_on_close
= (CVAL(pdata
,0) ? True
: False
);
5916 dosmode
= dos_mode(conn
, smb_fname
);
5918 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5919 "delete_on_close = %u\n",
5920 smb_fname_str_dbg(smb_fname
),
5921 (unsigned int)dosmode
,
5922 (unsigned int)delete_on_close
));
5924 if (delete_on_close
) {
5925 status
= can_set_delete_on_close(fsp
, dosmode
);
5926 if (!NT_STATUS_IS_OK(status
)) {
5931 /* The set is across all open files on this dev/inode pair. */
5932 if (!set_delete_on_close(fsp
, delete_on_close
,
5933 conn
->session_info
->security_token
,
5934 conn
->session_info
->unix_token
)) {
5935 return NT_STATUS_ACCESS_DENIED
;
5937 return NT_STATUS_OK
;
5940 /****************************************************************************
5941 Deal with SMB_FILE_POSITION_INFORMATION.
5942 ****************************************************************************/
5944 static NTSTATUS
smb_file_position_information(connection_struct
*conn
,
5949 uint64_t position_information
;
5951 if (total_data
< 8) {
5952 return NT_STATUS_INVALID_PARAMETER
;
5956 /* Ignore on pathname based set. */
5957 return NT_STATUS_OK
;
5960 position_information
= (uint64_t)IVAL(pdata
,0);
5961 position_information
|= (((uint64_t)IVAL(pdata
,4)) << 32);
5963 DEBUG(10,("smb_file_position_information: Set file position "
5964 "information for file %s to %.0f\n", fsp_str_dbg(fsp
),
5965 (double)position_information
));
5966 fsp
->fh
->position_information
= position_information
;
5967 return NT_STATUS_OK
;
5970 /****************************************************************************
5971 Deal with SMB_FILE_MODE_INFORMATION.
5972 ****************************************************************************/
5974 static NTSTATUS
smb_file_mode_information(connection_struct
*conn
,
5980 if (total_data
< 4) {
5981 return NT_STATUS_INVALID_PARAMETER
;
5983 mode
= IVAL(pdata
,0);
5984 if (mode
!= 0 && mode
!= 2 && mode
!= 4 && mode
!= 6) {
5985 return NT_STATUS_INVALID_PARAMETER
;
5987 return NT_STATUS_OK
;
5990 /****************************************************************************
5991 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
5992 ****************************************************************************/
5994 static NTSTATUS
smb_set_file_unix_link(connection_struct
*conn
,
5995 struct smb_request
*req
,
5998 const struct smb_filename
*smb_fname
)
6000 char *link_target
= NULL
;
6001 const char *newname
= smb_fname
->base_name
;
6002 TALLOC_CTX
*ctx
= talloc_tos();
6004 /* Set a symbolic link. */
6005 /* Don't allow this if follow links is false. */
6007 if (total_data
== 0) {
6008 return NT_STATUS_INVALID_PARAMETER
;
6011 if (!lp_symlinks(SNUM(conn
))) {
6012 return NT_STATUS_ACCESS_DENIED
;
6015 srvstr_pull_talloc(ctx
, pdata
, req
->flags2
, &link_target
, pdata
,
6016 total_data
, STR_TERMINATE
);
6019 return NT_STATUS_INVALID_PARAMETER
;
6022 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
6023 newname
, link_target
));
6025 if (SMB_VFS_SYMLINK(conn
,link_target
,newname
) != 0) {
6026 return map_nt_error_from_unix(errno
);
6029 return NT_STATUS_OK
;
6032 /****************************************************************************
6033 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
6034 ****************************************************************************/
6036 static NTSTATUS
smb_set_file_unix_hlink(connection_struct
*conn
,
6037 struct smb_request
*req
,
6038 const char *pdata
, int total_data
,
6039 struct smb_filename
*smb_fname_new
)
6041 char *oldname
= NULL
;
6042 struct smb_filename
*smb_fname_old
= NULL
;
6043 TALLOC_CTX
*ctx
= talloc_tos();
6044 NTSTATUS status
= NT_STATUS_OK
;
6046 /* Set a hard link. */
6047 if (total_data
== 0) {
6048 return NT_STATUS_INVALID_PARAMETER
;
6051 srvstr_get_path(ctx
, pdata
, req
->flags2
, &oldname
, pdata
,
6052 total_data
, STR_TERMINATE
, &status
);
6053 if (!NT_STATUS_IS_OK(status
)) {
6057 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
6058 smb_fname_str_dbg(smb_fname_new
), oldname
));
6060 status
= filename_convert(ctx
,
6062 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6067 if (!NT_STATUS_IS_OK(status
)) {
6071 return hardlink_internals(ctx
, conn
, req
, false,
6072 smb_fname_old
, smb_fname_new
);
6075 /****************************************************************************
6076 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
6077 ****************************************************************************/
6079 static NTSTATUS
smb2_file_rename_information(connection_struct
*conn
,
6080 struct smb_request
*req
,
6084 struct smb_filename
*smb_fname_src
)
6088 char *newname
= NULL
;
6089 struct smb_filename
*smb_fname_dst
= NULL
;
6090 NTSTATUS status
= NT_STATUS_OK
;
6091 TALLOC_CTX
*ctx
= talloc_tos();
6094 return NT_STATUS_INVALID_HANDLE
;
6097 if (total_data
< 20) {
6098 return NT_STATUS_INVALID_PARAMETER
;
6101 overwrite
= (CVAL(pdata
,0) ? True
: False
);
6102 len
= IVAL(pdata
,16);
6104 if (len
> (total_data
- 20) || (len
== 0)) {
6105 return NT_STATUS_INVALID_PARAMETER
;
6108 srvstr_get_path(ctx
, pdata
, req
->flags2
, &newname
,
6109 &pdata
[20], len
, STR_TERMINATE
,
6111 if (!NT_STATUS_IS_OK(status
)) {
6115 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
6118 status
= filename_convert(ctx
,
6120 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6125 if (!NT_STATUS_IS_OK(status
)) {
6129 if (fsp
->base_fsp
) {
6130 /* newname must be a stream name. */
6131 if (newname
[0] != ':') {
6132 return NT_STATUS_NOT_SUPPORTED
;
6135 /* Create an smb_fname to call rename_internals_fsp() with. */
6136 status
= create_synthetic_smb_fname(talloc_tos(),
6137 fsp
->base_fsp
->fsp_name
->base_name
, newname
, NULL
,
6139 if (!NT_STATUS_IS_OK(status
)) {
6144 * Set the original last component, since
6145 * rename_internals_fsp() requires it.
6147 smb_fname_dst
->original_lcomp
= talloc_strdup(smb_fname_dst
,
6149 if (smb_fname_dst
->original_lcomp
== NULL
) {
6150 status
= NT_STATUS_NO_MEMORY
;
6156 DEBUG(10,("smb2_file_rename_information: "
6157 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
6158 fsp_fnum_dbg(fsp
), fsp_str_dbg(fsp
),
6159 smb_fname_str_dbg(smb_fname_dst
)));
6160 status
= rename_internals_fsp(conn
, fsp
, smb_fname_dst
,
6161 (FILE_ATTRIBUTE_HIDDEN
|FILE_ATTRIBUTE_SYSTEM
),
6165 TALLOC_FREE(smb_fname_dst
);
6169 static NTSTATUS
smb_file_link_information(connection_struct
*conn
,
6170 struct smb_request
*req
,
6174 struct smb_filename
*smb_fname_src
)
6178 char *newname
= NULL
;
6179 struct smb_filename
*smb_fname_dst
= NULL
;
6180 NTSTATUS status
= NT_STATUS_OK
;
6181 TALLOC_CTX
*ctx
= talloc_tos();
6184 return NT_STATUS_INVALID_HANDLE
;
6187 if (total_data
< 20) {
6188 return NT_STATUS_INVALID_PARAMETER
;
6191 overwrite
= (CVAL(pdata
,0) ? true : false);
6192 len
= IVAL(pdata
,16);
6194 if (len
> (total_data
- 20) || (len
== 0)) {
6195 return NT_STATUS_INVALID_PARAMETER
;
6198 srvstr_get_path(ctx
, pdata
, req
->flags2
, &newname
,
6199 &pdata
[20], len
, STR_TERMINATE
,
6201 if (!NT_STATUS_IS_OK(status
)) {
6205 DEBUG(10,("smb_file_link_information: got name |%s|\n",
6208 status
= filename_convert(ctx
,
6210 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6215 if (!NT_STATUS_IS_OK(status
)) {
6219 if (fsp
->base_fsp
) {
6220 /* No stream names. */
6221 return NT_STATUS_NOT_SUPPORTED
;
6224 DEBUG(10,("smb_file_link_information: "
6225 "SMB_FILE_LINK_INFORMATION (%s) %s -> %s\n",
6226 fsp_fnum_dbg(fsp
), fsp_str_dbg(fsp
),
6227 smb_fname_str_dbg(smb_fname_dst
)));
6228 status
= hardlink_internals(ctx
,
6235 TALLOC_FREE(smb_fname_dst
);
6239 /****************************************************************************
6240 Deal with SMB_FILE_RENAME_INFORMATION.
6241 ****************************************************************************/
6243 static NTSTATUS
smb_file_rename_information(connection_struct
*conn
,
6244 struct smb_request
*req
,
6248 struct smb_filename
*smb_fname_src
)
6253 char *newname
= NULL
;
6254 struct smb_filename
*smb_fname_dst
= NULL
;
6255 bool dest_has_wcard
= False
;
6256 NTSTATUS status
= NT_STATUS_OK
;
6258 TALLOC_CTX
*ctx
= talloc_tos();
6260 if (total_data
< 13) {
6261 return NT_STATUS_INVALID_PARAMETER
;
6264 overwrite
= (CVAL(pdata
,0) ? True
: False
);
6265 root_fid
= IVAL(pdata
,4);
6266 len
= IVAL(pdata
,8);
6268 if (len
> (total_data
- 12) || (len
== 0) || (root_fid
!= 0)) {
6269 return NT_STATUS_INVALID_PARAMETER
;
6272 srvstr_get_path_wcard(ctx
, pdata
, req
->flags2
, &newname
, &pdata
[12],
6275 if (!NT_STATUS_IS_OK(status
)) {
6279 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
6282 status
= resolve_dfspath_wcard(ctx
, conn
,
6283 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6286 !conn
->sconn
->using_smb2
,
6289 if (!NT_STATUS_IS_OK(status
)) {
6293 /* Check the new name has no '/' characters. */
6294 if (strchr_m(newname
, '/')) {
6295 return NT_STATUS_NOT_SUPPORTED
;
6298 if (fsp
&& fsp
->base_fsp
) {
6299 /* newname must be a stream name. */
6300 if (newname
[0] != ':') {
6301 return NT_STATUS_NOT_SUPPORTED
;
6304 /* Create an smb_fname to call rename_internals_fsp() with. */
6305 status
= create_synthetic_smb_fname(talloc_tos(),
6306 fsp
->base_fsp
->fsp_name
->base_name
, newname
, NULL
,
6308 if (!NT_STATUS_IS_OK(status
)) {
6313 * Set the original last component, since
6314 * rename_internals_fsp() requires it.
6316 smb_fname_dst
->original_lcomp
= talloc_strdup(smb_fname_dst
,
6318 if (smb_fname_dst
->original_lcomp
== NULL
) {
6319 status
= NT_STATUS_NO_MEMORY
;
6325 * Build up an smb_fname_dst based on the filename passed in.
6326 * We basically just strip off the last component, and put on
6327 * the newname instead.
6329 char *base_name
= NULL
;
6331 /* newname must *not* be a stream name. */
6332 if (newname
[0] == ':') {
6333 return NT_STATUS_NOT_SUPPORTED
;
6337 * Strip off the last component (filename) of the path passed
6340 base_name
= talloc_strdup(ctx
, smb_fname_src
->base_name
);
6342 return NT_STATUS_NO_MEMORY
;
6344 p
= strrchr_m(base_name
, '/');
6348 base_name
= talloc_strdup(ctx
, "");
6350 return NT_STATUS_NO_MEMORY
;
6353 /* Append the new name. */
6354 base_name
= talloc_asprintf_append(base_name
,
6358 return NT_STATUS_NO_MEMORY
;
6361 status
= unix_convert(ctx
, conn
, base_name
, &smb_fname_dst
,
6364 UCF_ALWAYS_ALLOW_WCARD_LCOMP
:
6367 /* If an error we expect this to be
6368 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
6370 if (!NT_STATUS_IS_OK(status
)) {
6371 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND
,
6375 /* Create an smb_fname to call rename_internals_fsp() */
6376 status
= create_synthetic_smb_fname(ctx
,
6380 if (!NT_STATUS_IS_OK(status
)) {
6387 DEBUG(10,("smb_file_rename_information: "
6388 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
6389 fsp_fnum_dbg(fsp
), fsp_str_dbg(fsp
),
6390 smb_fname_str_dbg(smb_fname_dst
)));
6391 status
= rename_internals_fsp(conn
, fsp
, smb_fname_dst
, 0,
6394 DEBUG(10,("smb_file_rename_information: "
6395 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
6396 smb_fname_str_dbg(smb_fname_src
),
6397 smb_fname_str_dbg(smb_fname_dst
)));
6398 status
= rename_internals(ctx
, conn
, req
, smb_fname_src
,
6399 smb_fname_dst
, 0, overwrite
, false,
6401 FILE_WRITE_ATTRIBUTES
);
6404 TALLOC_FREE(smb_fname_dst
);
6408 /****************************************************************************
6409 Deal with SMB_SET_POSIX_ACL.
6410 ****************************************************************************/
6412 #if defined(HAVE_POSIX_ACLS)
6413 static NTSTATUS
smb_set_posix_acl(connection_struct
*conn
,
6417 const struct smb_filename
*smb_fname
)
6419 uint16 posix_acl_version
;
6420 uint16 num_file_acls
;
6421 uint16 num_def_acls
;
6422 bool valid_file_acls
= True
;
6423 bool valid_def_acls
= True
;
6425 if (total_data
< SMB_POSIX_ACL_HEADER_SIZE
) {
6426 return NT_STATUS_INVALID_PARAMETER
;
6428 posix_acl_version
= SVAL(pdata
,0);
6429 num_file_acls
= SVAL(pdata
,2);
6430 num_def_acls
= SVAL(pdata
,4);
6432 if (num_file_acls
== SMB_POSIX_IGNORE_ACE_ENTRIES
) {
6433 valid_file_acls
= False
;
6437 if (num_def_acls
== SMB_POSIX_IGNORE_ACE_ENTRIES
) {
6438 valid_def_acls
= False
;
6442 if (posix_acl_version
!= SMB_POSIX_ACL_VERSION
) {
6443 return NT_STATUS_INVALID_PARAMETER
;
6446 if (total_data
< SMB_POSIX_ACL_HEADER_SIZE
+
6447 (num_file_acls
+num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
) {
6448 return NT_STATUS_INVALID_PARAMETER
;
6451 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
6452 smb_fname
? smb_fname_str_dbg(smb_fname
) : fsp_str_dbg(fsp
),
6453 (unsigned int)num_file_acls
,
6454 (unsigned int)num_def_acls
));
6456 if (valid_file_acls
&& !set_unix_posix_acl(conn
, fsp
,
6457 smb_fname
->base_name
, num_file_acls
,
6458 pdata
+ SMB_POSIX_ACL_HEADER_SIZE
)) {
6459 return map_nt_error_from_unix(errno
);
6462 if (valid_def_acls
&& !set_unix_posix_default_acl(conn
,
6463 smb_fname
->base_name
, &smb_fname
->st
, num_def_acls
,
6464 pdata
+ SMB_POSIX_ACL_HEADER_SIZE
+
6465 (num_file_acls
*SMB_POSIX_ACL_ENTRY_SIZE
))) {
6466 return map_nt_error_from_unix(errno
);
6468 return NT_STATUS_OK
;
6472 /****************************************************************************
6473 Deal with SMB_SET_POSIX_LOCK.
6474 ****************************************************************************/
6476 static NTSTATUS
smb_set_posix_lock(connection_struct
*conn
,
6477 struct smb_request
*req
,
6485 bool blocking_lock
= False
;
6486 enum brl_type lock_type
;
6488 NTSTATUS status
= NT_STATUS_OK
;
6490 if (fsp
== NULL
|| fsp
->fh
->fd
== -1) {
6491 return NT_STATUS_INVALID_HANDLE
;
6494 if (total_data
!= POSIX_LOCK_DATA_SIZE
) {
6495 return NT_STATUS_INVALID_PARAMETER
;
6498 switch (SVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
)) {
6499 case POSIX_LOCK_TYPE_READ
:
6500 lock_type
= READ_LOCK
;
6502 case POSIX_LOCK_TYPE_WRITE
:
6503 /* Return the right POSIX-mappable error code for files opened read-only. */
6504 if (!fsp
->can_write
) {
6505 return NT_STATUS_INVALID_HANDLE
;
6507 lock_type
= WRITE_LOCK
;
6509 case POSIX_LOCK_TYPE_UNLOCK
:
6510 lock_type
= UNLOCK_LOCK
;
6513 return NT_STATUS_INVALID_PARAMETER
;
6516 if (SVAL(pdata
,POSIX_LOCK_FLAGS_OFFSET
) == POSIX_LOCK_FLAG_NOWAIT
) {
6517 blocking_lock
= False
;
6518 } else if (SVAL(pdata
,POSIX_LOCK_FLAGS_OFFSET
) == POSIX_LOCK_FLAG_WAIT
) {
6519 blocking_lock
= True
;
6521 return NT_STATUS_INVALID_PARAMETER
;
6524 if (!lp_blocking_locks(SNUM(conn
))) {
6525 blocking_lock
= False
;
6528 smblctx
= (uint64_t)IVAL(pdata
, POSIX_LOCK_PID_OFFSET
);
6529 #if defined(HAVE_LONGLONG)
6530 offset
= (((uint64_t) IVAL(pdata
,(POSIX_LOCK_START_OFFSET
+4))) << 32) |
6531 ((uint64_t) IVAL(pdata
,POSIX_LOCK_START_OFFSET
));
6532 count
= (((uint64_t) IVAL(pdata
,(POSIX_LOCK_LEN_OFFSET
+4))) << 32) |
6533 ((uint64_t) IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
));
6534 #else /* HAVE_LONGLONG */
6535 offset
= (uint64_t)IVAL(pdata
,POSIX_LOCK_START_OFFSET
);
6536 count
= (uint64_t)IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
);
6537 #endif /* HAVE_LONGLONG */
6539 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
6540 "smblctx = %llu, count = %.0f, offset = %.0f\n",
6542 (unsigned int)lock_type
,
6543 (unsigned long long)smblctx
,
6547 if (lock_type
== UNLOCK_LOCK
) {
6548 status
= do_unlock(req
->sconn
->msg_ctx
,
6555 uint64_t block_smblctx
;
6557 struct byte_range_lock
*br_lck
= do_lock(req
->sconn
->msg_ctx
,
6569 if (br_lck
&& blocking_lock
&& ERROR_WAS_LOCK_DENIED(status
)) {
6571 * A blocking lock was requested. Package up
6572 * this smb into a queued request and push it
6573 * onto the blocking lock queue.
6575 if(push_blocking_lock_request(br_lck
,
6578 -1, /* infinite timeout. */
6586 TALLOC_FREE(br_lck
);
6590 TALLOC_FREE(br_lck
);
6596 /****************************************************************************
6597 Deal with SMB_SET_FILE_BASIC_INFO.
6598 ****************************************************************************/
6600 static NTSTATUS
smb_set_file_basic_info(connection_struct
*conn
,
6604 const struct smb_filename
*smb_fname
)
6606 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
6607 struct smb_file_time ft
;
6609 NTSTATUS status
= NT_STATUS_OK
;
6613 if (total_data
< 36) {
6614 return NT_STATUS_INVALID_PARAMETER
;
6617 status
= check_access(conn
, fsp
, smb_fname
, FILE_WRITE_ATTRIBUTES
);
6618 if (!NT_STATUS_IS_OK(status
)) {
6622 /* Set the attributes */
6623 dosmode
= IVAL(pdata
,32);
6624 status
= smb_set_file_dosmode(conn
, smb_fname
, dosmode
);
6625 if (!NT_STATUS_IS_OK(status
)) {
6630 ft
.create_time
= interpret_long_date(pdata
);
6633 ft
.atime
= interpret_long_date(pdata
+8);
6636 ft
.mtime
= interpret_long_date(pdata
+16);
6639 ft
.ctime
= interpret_long_date(pdata
+24);
6641 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
6642 smb_fname_str_dbg(smb_fname
)));
6644 return smb_set_file_time(conn
, fsp
, smb_fname
, &ft
,
6648 /****************************************************************************
6649 Deal with SMB_INFO_STANDARD.
6650 ****************************************************************************/
6652 static NTSTATUS
smb_set_info_standard(connection_struct
*conn
,
6656 const struct smb_filename
*smb_fname
)
6659 struct smb_file_time ft
;
6663 if (total_data
< 12) {
6664 return NT_STATUS_INVALID_PARAMETER
;
6668 ft
.create_time
= convert_time_t_to_timespec(srv_make_unix_date2(pdata
));
6670 ft
.atime
= convert_time_t_to_timespec(srv_make_unix_date2(pdata
+4));
6672 ft
.mtime
= convert_time_t_to_timespec(srv_make_unix_date2(pdata
+8));
6674 DEBUG(10,("smb_set_info_standard: file %s\n",
6675 smb_fname_str_dbg(smb_fname
)));
6677 status
= check_access(conn
, fsp
, smb_fname
, FILE_WRITE_ATTRIBUTES
);
6678 if (!NT_STATUS_IS_OK(status
)) {
6682 return smb_set_file_time(conn
,
6689 /****************************************************************************
6690 Deal with SMB_SET_FILE_ALLOCATION_INFO.
6691 ****************************************************************************/
6693 static NTSTATUS
smb_set_file_allocation_info(connection_struct
*conn
,
6694 struct smb_request
*req
,
6698 struct smb_filename
*smb_fname
)
6700 uint64_t allocation_size
= 0;
6701 NTSTATUS status
= NT_STATUS_OK
;
6702 files_struct
*new_fsp
= NULL
;
6704 if (!VALID_STAT(smb_fname
->st
)) {
6705 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
6708 if (total_data
< 8) {
6709 return NT_STATUS_INVALID_PARAMETER
;
6712 allocation_size
= (uint64_t)IVAL(pdata
,0);
6713 allocation_size
|= (((uint64_t)IVAL(pdata
,4)) << 32);
6714 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
6715 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname
),
6716 (double)allocation_size
));
6718 if (allocation_size
) {
6719 allocation_size
= smb_roundup(conn
, allocation_size
);
6722 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
6723 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname
),
6724 (double)allocation_size
));
6726 if (fsp
&& fsp
->fh
->fd
!= -1) {
6727 /* Open file handle. */
6728 if (!(fsp
->access_mask
& FILE_WRITE_DATA
)) {
6729 return NT_STATUS_ACCESS_DENIED
;
6732 /* Only change if needed. */
6733 if (allocation_size
!= get_file_size_stat(&smb_fname
->st
)) {
6734 if (vfs_allocate_file_space(fsp
, allocation_size
) == -1) {
6735 return map_nt_error_from_unix(errno
);
6738 /* But always update the time. */
6740 * This is equivalent to a write. Ensure it's seen immediately
6741 * if there are no pending writes.
6743 trigger_write_time_update_immediate(fsp
);
6744 return NT_STATUS_OK
;
6747 /* Pathname or stat or directory file. */
6748 status
= SMB_VFS_CREATE_FILE(
6751 0, /* root_dir_fid */
6752 smb_fname
, /* fname */
6753 FILE_WRITE_DATA
, /* access_mask */
6754 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
6756 FILE_OPEN
, /* create_disposition*/
6757 0, /* create_options */
6758 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
6759 FORCE_OPLOCK_BREAK_TO_NONE
, /* oplock_request */
6760 0, /* allocation_size */
6761 0, /* private_flags */
6764 &new_fsp
, /* result */
6767 if (!NT_STATUS_IS_OK(status
)) {
6768 /* NB. We check for open_was_deferred in the caller. */
6772 /* Only change if needed. */
6773 if (allocation_size
!= get_file_size_stat(&smb_fname
->st
)) {
6774 if (vfs_allocate_file_space(new_fsp
, allocation_size
) == -1) {
6775 status
= map_nt_error_from_unix(errno
);
6776 close_file(req
, new_fsp
, NORMAL_CLOSE
);
6781 /* Changing the allocation size should set the last mod time. */
6783 * This is equivalent to a write. Ensure it's seen immediately
6784 * if there are no pending writes.
6786 trigger_write_time_update_immediate(new_fsp
);
6788 close_file(req
, new_fsp
, NORMAL_CLOSE
);
6789 return NT_STATUS_OK
;
6792 /****************************************************************************
6793 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
6794 ****************************************************************************/
6796 static NTSTATUS
smb_set_file_end_of_file_info(connection_struct
*conn
,
6797 struct smb_request
*req
,
6801 const struct smb_filename
*smb_fname
,
6802 bool fail_after_createfile
)
6806 if (total_data
< 8) {
6807 return NT_STATUS_INVALID_PARAMETER
;
6810 size
= IVAL(pdata
,0);
6811 size
|= (((off_t
)IVAL(pdata
,4)) << 32);
6812 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
6813 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname
),
6816 return smb_set_file_size(conn
, req
,
6821 fail_after_createfile
);
6824 /****************************************************************************
6825 Allow a UNIX info mknod.
6826 ****************************************************************************/
6828 static NTSTATUS
smb_unix_mknod(connection_struct
*conn
,
6831 const struct smb_filename
*smb_fname
)
6833 uint32 file_type
= IVAL(pdata
,56);
6834 #if defined(HAVE_MAKEDEV)
6835 uint32 dev_major
= IVAL(pdata
,60);
6836 uint32 dev_minor
= IVAL(pdata
,68);
6838 SMB_DEV_T dev
= (SMB_DEV_T
)0;
6839 uint32 raw_unixmode
= IVAL(pdata
,84);
6843 if (total_data
< 100) {
6844 return NT_STATUS_INVALID_PARAMETER
;
6847 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
6848 PERM_NEW_FILE
, &unixmode
);
6849 if (!NT_STATUS_IS_OK(status
)) {
6853 #if defined(HAVE_MAKEDEV)
6854 dev
= makedev(dev_major
, dev_minor
);
6857 switch (file_type
) {
6858 #if defined(S_IFIFO)
6859 case UNIX_TYPE_FIFO
:
6860 unixmode
|= S_IFIFO
;
6863 #if defined(S_IFSOCK)
6864 case UNIX_TYPE_SOCKET
:
6865 unixmode
|= S_IFSOCK
;
6868 #if defined(S_IFCHR)
6869 case UNIX_TYPE_CHARDEV
:
6870 unixmode
|= S_IFCHR
;
6873 #if defined(S_IFBLK)
6874 case UNIX_TYPE_BLKDEV
:
6875 unixmode
|= S_IFBLK
;
6879 return NT_STATUS_INVALID_PARAMETER
;
6882 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
6883 "%.0f mode 0%o for file %s\n", (double)dev
,
6884 (unsigned int)unixmode
, smb_fname_str_dbg(smb_fname
)));
6886 /* Ok - do the mknod. */
6887 if (SMB_VFS_MKNOD(conn
, smb_fname
->base_name
, unixmode
, dev
) != 0) {
6888 return map_nt_error_from_unix(errno
);
6891 /* If any of the other "set" calls fail we
6892 * don't want to end up with a half-constructed mknod.
6895 if (lp_inherit_perms(SNUM(conn
))) {
6897 if (!parent_dirname(talloc_tos(), smb_fname
->base_name
,
6899 return NT_STATUS_NO_MEMORY
;
6901 inherit_access_posix_acl(conn
, parent
, smb_fname
->base_name
,
6903 TALLOC_FREE(parent
);
6906 return NT_STATUS_OK
;
6909 /****************************************************************************
6910 Deal with SMB_SET_FILE_UNIX_BASIC.
6911 ****************************************************************************/
6913 static NTSTATUS
smb_set_file_unix_basic(connection_struct
*conn
,
6914 struct smb_request
*req
,
6918 const struct smb_filename
*smb_fname
)
6920 struct smb_file_time ft
;
6921 uint32 raw_unixmode
;
6924 uid_t set_owner
= (uid_t
)SMB_UID_NO_CHANGE
;
6925 gid_t set_grp
= (uid_t
)SMB_GID_NO_CHANGE
;
6926 NTSTATUS status
= NT_STATUS_OK
;
6927 bool delete_on_fail
= False
;
6928 enum perm_type ptype
;
6929 files_struct
*all_fsps
= NULL
;
6930 bool modify_mtime
= true;
6932 struct smb_filename
*smb_fname_tmp
= NULL
;
6933 SMB_STRUCT_STAT sbuf
;
6937 if (total_data
< 100) {
6938 return NT_STATUS_INVALID_PARAMETER
;
6941 if(IVAL(pdata
, 0) != SMB_SIZE_NO_CHANGE_LO
&&
6942 IVAL(pdata
, 4) != SMB_SIZE_NO_CHANGE_HI
) {
6943 size
=IVAL(pdata
,0); /* first 8 Bytes are size */
6944 size
|= (((off_t
)IVAL(pdata
,4)) << 32);
6947 ft
.atime
= interpret_long_date(pdata
+24); /* access_time */
6948 ft
.mtime
= interpret_long_date(pdata
+32); /* modification_time */
6949 set_owner
= (uid_t
)IVAL(pdata
,40);
6950 set_grp
= (gid_t
)IVAL(pdata
,48);
6951 raw_unixmode
= IVAL(pdata
,84);
6953 if (VALID_STAT(smb_fname
->st
)) {
6954 if (S_ISDIR(smb_fname
->st
.st_ex_mode
)) {
6955 ptype
= PERM_EXISTING_DIR
;
6957 ptype
= PERM_EXISTING_FILE
;
6960 ptype
= PERM_NEW_FILE
;
6963 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
6965 if (!NT_STATUS_IS_OK(status
)) {
6969 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
6970 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
6971 smb_fname_str_dbg(smb_fname
), (double)size
,
6972 (unsigned int)set_owner
, (unsigned int)set_grp
,
6973 (int)raw_unixmode
));
6975 sbuf
= smb_fname
->st
;
6977 if (!VALID_STAT(sbuf
)) {
6979 * The only valid use of this is to create character and block
6980 * devices, and named pipes. This is deprecated (IMHO) and
6981 * a new info level should be used for mknod. JRA.
6984 status
= smb_unix_mknod(conn
,
6988 if (!NT_STATUS_IS_OK(status
)) {
6992 status
= copy_smb_filename(talloc_tos(), smb_fname
,
6994 if (!NT_STATUS_IS_OK(status
)) {
6998 if (SMB_VFS_STAT(conn
, smb_fname_tmp
) != 0) {
6999 status
= map_nt_error_from_unix(errno
);
7000 TALLOC_FREE(smb_fname_tmp
);
7001 SMB_VFS_UNLINK(conn
, smb_fname
);
7005 sbuf
= smb_fname_tmp
->st
;
7006 smb_fname
= smb_fname_tmp
;
7008 /* Ensure we don't try and change anything else. */
7009 raw_unixmode
= SMB_MODE_NO_CHANGE
;
7010 size
= get_file_size_stat(&sbuf
);
7011 ft
.atime
= sbuf
.st_ex_atime
;
7012 ft
.mtime
= sbuf
.st_ex_mtime
;
7014 * We continue here as we might want to change the
7017 delete_on_fail
= True
;
7021 /* Horrible backwards compatibility hack as an old server bug
7022 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
7026 size
= get_file_size_stat(&sbuf
);
7031 * Deal with the UNIX specific mode set.
7034 if (raw_unixmode
!= SMB_MODE_NO_CHANGE
) {
7035 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7036 "setting mode 0%o for file %s\n",
7037 (unsigned int)unixmode
,
7038 smb_fname_str_dbg(smb_fname
)));
7039 if (SMB_VFS_CHMOD(conn
, smb_fname
->base_name
, unixmode
) != 0) {
7040 return map_nt_error_from_unix(errno
);
7045 * Deal with the UNIX specific uid set.
7048 if ((set_owner
!= (uid_t
)SMB_UID_NO_CHANGE
) &&
7049 (sbuf
.st_ex_uid
!= set_owner
)) {
7052 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7053 "changing owner %u for path %s\n",
7054 (unsigned int)set_owner
,
7055 smb_fname_str_dbg(smb_fname
)));
7057 if (S_ISLNK(sbuf
.st_ex_mode
)) {
7058 ret
= SMB_VFS_LCHOWN(conn
, smb_fname
->base_name
,
7059 set_owner
, (gid_t
)-1);
7061 ret
= SMB_VFS_CHOWN(conn
, smb_fname
->base_name
,
7062 set_owner
, (gid_t
)-1);
7066 status
= map_nt_error_from_unix(errno
);
7067 if (delete_on_fail
) {
7068 SMB_VFS_UNLINK(conn
, smb_fname
);
7075 * Deal with the UNIX specific gid set.
7078 if ((set_grp
!= (uid_t
)SMB_GID_NO_CHANGE
) &&
7079 (sbuf
.st_ex_gid
!= set_grp
)) {
7080 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7081 "changing group %u for file %s\n",
7082 (unsigned int)set_owner
,
7083 smb_fname_str_dbg(smb_fname
)));
7084 if (SMB_VFS_CHOWN(conn
, smb_fname
->base_name
, (uid_t
)-1,
7086 status
= map_nt_error_from_unix(errno
);
7087 if (delete_on_fail
) {
7088 SMB_VFS_UNLINK(conn
, smb_fname
);
7094 /* Deal with any size changes. */
7096 status
= smb_set_file_size(conn
, req
,
7102 if (!NT_STATUS_IS_OK(status
)) {
7106 /* Deal with any time changes. */
7107 if (null_timespec(ft
.mtime
) && null_timespec(ft
.atime
)) {
7108 /* No change, don't cancel anything. */
7112 id
= vfs_file_id_from_sbuf(conn
, &sbuf
);
7113 for(all_fsps
= file_find_di_first(conn
->sconn
, id
); all_fsps
;
7114 all_fsps
= file_find_di_next(all_fsps
)) {
7116 * We're setting the time explicitly for UNIX.
7117 * Cancel any pending changes over all handles.
7119 all_fsps
->update_write_time_on_close
= false;
7120 TALLOC_FREE(all_fsps
->update_write_time_event
);
7124 * Override the "setting_write_time"
7125 * parameter here as it almost does what
7126 * we need. Just remember if we modified
7127 * mtime and send the notify ourselves.
7129 if (null_timespec(ft
.mtime
)) {
7130 modify_mtime
= false;
7133 status
= smb_set_file_time(conn
,
7139 notify_fname(conn
, NOTIFY_ACTION_MODIFIED
,
7140 FILE_NOTIFY_CHANGE_LAST_WRITE
, smb_fname
->base_name
);
7145 /****************************************************************************
7146 Deal with SMB_SET_FILE_UNIX_INFO2.
7147 ****************************************************************************/
7149 static NTSTATUS
smb_set_file_unix_info2(connection_struct
*conn
,
7150 struct smb_request
*req
,
7154 const struct smb_filename
*smb_fname
)
7160 if (total_data
< 116) {
7161 return NT_STATUS_INVALID_PARAMETER
;
7164 /* Start by setting all the fields that are common between UNIX_BASIC
7167 status
= smb_set_file_unix_basic(conn
, req
, pdata
, total_data
,
7169 if (!NT_STATUS_IS_OK(status
)) {
7173 smb_fflags
= IVAL(pdata
, 108);
7174 smb_fmask
= IVAL(pdata
, 112);
7176 /* NB: We should only attempt to alter the file flags if the client
7177 * sends a non-zero mask.
7179 if (smb_fmask
!= 0) {
7180 int stat_fflags
= 0;
7182 if (!map_info2_flags_to_sbuf(&smb_fname
->st
, smb_fflags
,
7183 smb_fmask
, &stat_fflags
)) {
7184 /* Client asked to alter a flag we don't understand. */
7185 return NT_STATUS_INVALID_PARAMETER
;
7188 if (fsp
&& fsp
->fh
->fd
!= -1) {
7189 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
7190 return NT_STATUS_NOT_SUPPORTED
;
7192 if (SMB_VFS_CHFLAGS(conn
, smb_fname
->base_name
,
7193 stat_fflags
) != 0) {
7194 return map_nt_error_from_unix(errno
);
7199 /* XXX: need to add support for changing the create_time here. You
7200 * can do this for paths on Darwin with setattrlist(2). The right way
7201 * to hook this up is probably by extending the VFS utimes interface.
7204 return NT_STATUS_OK
;
7207 /****************************************************************************
7208 Create a directory with POSIX semantics.
7209 ****************************************************************************/
7211 static NTSTATUS
smb_posix_mkdir(connection_struct
*conn
,
7212 struct smb_request
*req
,
7215 struct smb_filename
*smb_fname
,
7216 int *pdata_return_size
)
7218 NTSTATUS status
= NT_STATUS_OK
;
7219 uint32 raw_unixmode
= 0;
7220 uint32 mod_unixmode
= 0;
7221 mode_t unixmode
= (mode_t
)0;
7222 files_struct
*fsp
= NULL
;
7223 uint16 info_level_return
= 0;
7225 char *pdata
= *ppdata
;
7227 if (total_data
< 18) {
7228 return NT_STATUS_INVALID_PARAMETER
;
7231 raw_unixmode
= IVAL(pdata
,8);
7232 /* Next 4 bytes are not yet defined. */
7234 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
7235 PERM_NEW_DIR
, &unixmode
);
7236 if (!NT_STATUS_IS_OK(status
)) {
7240 mod_unixmode
= (uint32
)unixmode
| FILE_FLAG_POSIX_SEMANTICS
;
7242 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
7243 smb_fname_str_dbg(smb_fname
), (unsigned int)unixmode
));
7245 status
= SMB_VFS_CREATE_FILE(
7248 0, /* root_dir_fid */
7249 smb_fname
, /* fname */
7250 FILE_READ_ATTRIBUTES
, /* access_mask */
7251 FILE_SHARE_NONE
, /* share_access */
7252 FILE_CREATE
, /* create_disposition*/
7253 FILE_DIRECTORY_FILE
, /* create_options */
7254 mod_unixmode
, /* file_attributes */
7255 0, /* oplock_request */
7256 0, /* allocation_size */
7257 0, /* private_flags */
7263 if (NT_STATUS_IS_OK(status
)) {
7264 close_file(req
, fsp
, NORMAL_CLOSE
);
7267 info_level_return
= SVAL(pdata
,16);
7269 if (info_level_return
== SMB_QUERY_FILE_UNIX_BASIC
) {
7270 *pdata_return_size
= 12 + SMB_FILE_UNIX_BASIC_SIZE
;
7271 } else if (info_level_return
== SMB_QUERY_FILE_UNIX_INFO2
) {
7272 *pdata_return_size
= 12 + SMB_FILE_UNIX_INFO2_SIZE
;
7274 *pdata_return_size
= 12;
7277 /* Realloc the data size */
7278 *ppdata
= (char *)SMB_REALLOC(*ppdata
,*pdata_return_size
);
7279 if (*ppdata
== NULL
) {
7280 *pdata_return_size
= 0;
7281 return NT_STATUS_NO_MEMORY
;
7285 SSVAL(pdata
,0,NO_OPLOCK_RETURN
);
7286 SSVAL(pdata
,2,0); /* No fnum. */
7287 SIVAL(pdata
,4,info
); /* Was directory created. */
7289 switch (info_level_return
) {
7290 case SMB_QUERY_FILE_UNIX_BASIC
:
7291 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_BASIC
);
7292 SSVAL(pdata
,10,0); /* Padding. */
7293 store_file_unix_basic(conn
, pdata
+ 12, fsp
,
7296 case SMB_QUERY_FILE_UNIX_INFO2
:
7297 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_INFO2
);
7298 SSVAL(pdata
,10,0); /* Padding. */
7299 store_file_unix_basic_info2(conn
, pdata
+ 12, fsp
,
7303 SSVAL(pdata
,8,SMB_NO_INFO_LEVEL_RETURNED
);
7304 SSVAL(pdata
,10,0); /* Padding. */
7311 /****************************************************************************
7312 Open/Create a file with POSIX semantics.
7313 ****************************************************************************/
7315 #define SMB_O_RDONLY_MAPPING (FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA)
7316 #define SMB_O_WRONLY_MAPPING (FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA)
7318 static NTSTATUS
smb_posix_open(connection_struct
*conn
,
7319 struct smb_request
*req
,
7322 struct smb_filename
*smb_fname
,
7323 int *pdata_return_size
)
7325 bool extended_oplock_granted
= False
;
7326 char *pdata
= *ppdata
;
7328 uint32 wire_open_mode
= 0;
7329 uint32 raw_unixmode
= 0;
7330 uint32 mod_unixmode
= 0;
7331 uint32 create_disp
= 0;
7332 uint32 access_mask
= 0;
7333 uint32 create_options
= FILE_NON_DIRECTORY_FILE
;
7334 NTSTATUS status
= NT_STATUS_OK
;
7335 mode_t unixmode
= (mode_t
)0;
7336 files_struct
*fsp
= NULL
;
7337 int oplock_request
= 0;
7339 uint16 info_level_return
= 0;
7341 if (total_data
< 18) {
7342 return NT_STATUS_INVALID_PARAMETER
;
7345 flags
= IVAL(pdata
,0);
7346 oplock_request
= (flags
& REQUEST_OPLOCK
) ? EXCLUSIVE_OPLOCK
: 0;
7347 if (oplock_request
) {
7348 oplock_request
|= (flags
& REQUEST_BATCH_OPLOCK
) ? BATCH_OPLOCK
: 0;
7351 wire_open_mode
= IVAL(pdata
,4);
7353 if (wire_open_mode
== (SMB_O_CREAT
|SMB_O_DIRECTORY
)) {
7354 return smb_posix_mkdir(conn
, req
,
7361 switch (wire_open_mode
& SMB_ACCMODE
) {
7363 access_mask
= SMB_O_RDONLY_MAPPING
;
7366 access_mask
= SMB_O_WRONLY_MAPPING
;
7369 access_mask
= (SMB_O_RDONLY_MAPPING
|
7370 SMB_O_WRONLY_MAPPING
);
7373 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
7374 (unsigned int)wire_open_mode
));
7375 return NT_STATUS_INVALID_PARAMETER
;
7378 wire_open_mode
&= ~SMB_ACCMODE
;
7380 /* First take care of O_CREAT|O_EXCL interactions. */
7381 switch (wire_open_mode
& (SMB_O_CREAT
| SMB_O_EXCL
)) {
7382 case (SMB_O_CREAT
| SMB_O_EXCL
):
7383 /* File exists fail. File not exist create. */
7384 create_disp
= FILE_CREATE
;
7387 /* File exists open. File not exist create. */
7388 create_disp
= FILE_OPEN_IF
;
7391 /* File exists open. File not exist fail. */
7392 create_disp
= FILE_OPEN
;
7395 /* O_EXCL on its own without O_CREAT is undefined. */
7397 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
7398 (unsigned int)wire_open_mode
));
7399 return NT_STATUS_INVALID_PARAMETER
;
7402 /* Next factor in the effects of O_TRUNC. */
7403 wire_open_mode
&= ~(SMB_O_CREAT
| SMB_O_EXCL
);
7405 if (wire_open_mode
& SMB_O_TRUNC
) {
7406 switch (create_disp
) {
7408 /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
7409 /* Leave create_disp alone as
7410 (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
7412 /* File exists fail. File not exist create. */
7415 /* SMB_O_CREAT | SMB_O_TRUNC */
7416 /* File exists overwrite. File not exist create. */
7417 create_disp
= FILE_OVERWRITE_IF
;
7421 /* File exists overwrite. File not exist fail. */
7422 create_disp
= FILE_OVERWRITE
;
7425 /* Cannot get here. */
7426 smb_panic("smb_posix_open: logic error");
7427 return NT_STATUS_INVALID_PARAMETER
;
7431 raw_unixmode
= IVAL(pdata
,8);
7432 /* Next 4 bytes are not yet defined. */
7434 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
7435 (VALID_STAT(smb_fname
->st
) ?
7436 PERM_EXISTING_FILE
: PERM_NEW_FILE
),
7439 if (!NT_STATUS_IS_OK(status
)) {
7443 mod_unixmode
= (uint32
)unixmode
| FILE_FLAG_POSIX_SEMANTICS
;
7445 if (wire_open_mode
& SMB_O_SYNC
) {
7446 create_options
|= FILE_WRITE_THROUGH
;
7448 if (wire_open_mode
& SMB_O_APPEND
) {
7449 access_mask
|= FILE_APPEND_DATA
;
7451 if (wire_open_mode
& SMB_O_DIRECT
) {
7452 mod_unixmode
|= FILE_FLAG_NO_BUFFERING
;
7455 if ((wire_open_mode
& SMB_O_DIRECTORY
) ||
7456 VALID_STAT_OF_DIR(smb_fname
->st
)) {
7457 if (access_mask
!= SMB_O_RDONLY_MAPPING
) {
7458 return NT_STATUS_FILE_IS_A_DIRECTORY
;
7460 create_options
&= ~FILE_NON_DIRECTORY_FILE
;
7461 create_options
|= FILE_DIRECTORY_FILE
;
7464 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
7465 smb_fname_str_dbg(smb_fname
),
7466 (unsigned int)wire_open_mode
,
7467 (unsigned int)unixmode
));
7469 status
= SMB_VFS_CREATE_FILE(
7472 0, /* root_dir_fid */
7473 smb_fname
, /* fname */
7474 access_mask
, /* access_mask */
7475 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
7477 create_disp
, /* create_disposition*/
7478 create_options
, /* create_options */
7479 mod_unixmode
, /* file_attributes */
7480 oplock_request
, /* oplock_request */
7481 0, /* allocation_size */
7482 0, /* private_flags */
7488 if (!NT_STATUS_IS_OK(status
)) {
7492 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
7493 extended_oplock_granted
= True
;
7496 if(oplock_request
&& EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
7497 extended_oplock_granted
= True
;
7500 info_level_return
= SVAL(pdata
,16);
7502 /* Allocate the correct return size. */
7504 if (info_level_return
== SMB_QUERY_FILE_UNIX_BASIC
) {
7505 *pdata_return_size
= 12 + SMB_FILE_UNIX_BASIC_SIZE
;
7506 } else if (info_level_return
== SMB_QUERY_FILE_UNIX_INFO2
) {
7507 *pdata_return_size
= 12 + SMB_FILE_UNIX_INFO2_SIZE
;
7509 *pdata_return_size
= 12;
7512 /* Realloc the data size */
7513 *ppdata
= (char *)SMB_REALLOC(*ppdata
,*pdata_return_size
);
7514 if (*ppdata
== NULL
) {
7515 close_file(req
, fsp
, ERROR_CLOSE
);
7516 *pdata_return_size
= 0;
7517 return NT_STATUS_NO_MEMORY
;
7521 if (extended_oplock_granted
) {
7522 if (flags
& REQUEST_BATCH_OPLOCK
) {
7523 SSVAL(pdata
,0, BATCH_OPLOCK_RETURN
);
7525 SSVAL(pdata
,0, EXCLUSIVE_OPLOCK_RETURN
);
7527 } else if (fsp
->oplock_type
== LEVEL_II_OPLOCK
) {
7528 SSVAL(pdata
,0, LEVEL_II_OPLOCK_RETURN
);
7530 SSVAL(pdata
,0,NO_OPLOCK_RETURN
);
7533 SSVAL(pdata
,2,fsp
->fnum
);
7534 SIVAL(pdata
,4,info
); /* Was file created etc. */
7536 switch (info_level_return
) {
7537 case SMB_QUERY_FILE_UNIX_BASIC
:
7538 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_BASIC
);
7539 SSVAL(pdata
,10,0); /* padding. */
7540 store_file_unix_basic(conn
, pdata
+ 12, fsp
,
7543 case SMB_QUERY_FILE_UNIX_INFO2
:
7544 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_INFO2
);
7545 SSVAL(pdata
,10,0); /* padding. */
7546 store_file_unix_basic_info2(conn
, pdata
+ 12, fsp
,
7550 SSVAL(pdata
,8,SMB_NO_INFO_LEVEL_RETURNED
);
7551 SSVAL(pdata
,10,0); /* padding. */
7554 return NT_STATUS_OK
;
7557 /****************************************************************************
7558 Delete a file with POSIX semantics.
7559 ****************************************************************************/
7561 static NTSTATUS
smb_posix_unlink(connection_struct
*conn
,
7562 struct smb_request
*req
,
7565 struct smb_filename
*smb_fname
)
7567 NTSTATUS status
= NT_STATUS_OK
;
7568 files_struct
*fsp
= NULL
;
7572 int create_options
= 0;
7574 struct share_mode_lock
*lck
= NULL
;
7576 if (total_data
< 2) {
7577 return NT_STATUS_INVALID_PARAMETER
;
7580 flags
= SVAL(pdata
,0);
7582 if (!VALID_STAT(smb_fname
->st
)) {
7583 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
7586 if ((flags
== SMB_POSIX_UNLINK_DIRECTORY_TARGET
) &&
7587 !VALID_STAT_OF_DIR(smb_fname
->st
)) {
7588 return NT_STATUS_NOT_A_DIRECTORY
;
7591 DEBUG(10,("smb_posix_unlink: %s %s\n",
7592 (flags
== SMB_POSIX_UNLINK_DIRECTORY_TARGET
) ? "directory" : "file",
7593 smb_fname_str_dbg(smb_fname
)));
7595 if (VALID_STAT_OF_DIR(smb_fname
->st
)) {
7596 create_options
|= FILE_DIRECTORY_FILE
;
7599 status
= SMB_VFS_CREATE_FILE(
7602 0, /* root_dir_fid */
7603 smb_fname
, /* fname */
7604 DELETE_ACCESS
, /* access_mask */
7605 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
7607 FILE_OPEN
, /* create_disposition*/
7608 create_options
, /* create_options */
7609 FILE_FLAG_POSIX_SEMANTICS
|0777, /* file_attributes */
7610 0, /* oplock_request */
7611 0, /* allocation_size */
7612 0, /* private_flags */
7618 if (!NT_STATUS_IS_OK(status
)) {
7623 * Don't lie to client. If we can't really delete due to
7624 * non-POSIX opens return SHARING_VIOLATION.
7627 lck
= get_existing_share_mode_lock(talloc_tos(), fsp
->file_id
);
7629 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
7630 "lock for file %s\n", fsp_str_dbg(fsp
)));
7631 close_file(req
, fsp
, NORMAL_CLOSE
);
7632 return NT_STATUS_INVALID_PARAMETER
;
7636 * See if others still have the file open. If this is the case, then
7637 * don't delete. If all opens are POSIX delete we can set the delete
7638 * on close disposition.
7640 for (i
=0; i
<lck
->data
->num_share_modes
; i
++) {
7641 struct share_mode_entry
*e
= &lck
->data
->share_modes
[i
];
7642 if (is_valid_share_mode_entry(e
)) {
7643 if (e
->flags
& SHARE_MODE_FLAG_POSIX_OPEN
) {
7646 if (share_mode_stale_pid(lck
->data
, i
)) {
7649 /* Fail with sharing violation. */
7650 close_file(req
, fsp
, NORMAL_CLOSE
);
7652 return NT_STATUS_SHARING_VIOLATION
;
7657 * Set the delete on close.
7659 status
= smb_set_file_disposition_info(conn
,
7665 if (!NT_STATUS_IS_OK(status
)) {
7666 close_file(req
, fsp
, NORMAL_CLOSE
);
7671 return close_file(req
, fsp
, NORMAL_CLOSE
);
7674 NTSTATUS
smbd_do_setfilepathinfo(connection_struct
*conn
,
7675 struct smb_request
*req
,
7676 TALLOC_CTX
*mem_ctx
,
7677 uint16_t info_level
,
7679 struct smb_filename
*smb_fname
,
7680 char **ppdata
, int total_data
,
7683 char *pdata
= *ppdata
;
7684 NTSTATUS status
= NT_STATUS_OK
;
7685 int data_return_size
= 0;
7689 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
7690 return NT_STATUS_INVALID_LEVEL
;
7693 if (!CAN_WRITE(conn
)) {
7694 /* Allow POSIX opens. The open path will deny
7695 * any non-readonly opens. */
7696 if (info_level
!= SMB_POSIX_PATH_OPEN
) {
7697 return NT_STATUS_DOS(ERRSRV
, ERRaccess
);
7701 DEBUG(3,("smbd_do_setfilepathinfo: %s (%s) info_level=%d "
7702 "totdata=%d\n", smb_fname_str_dbg(smb_fname
),
7704 info_level
, total_data
));
7706 switch (info_level
) {
7708 case SMB_INFO_STANDARD
:
7710 status
= smb_set_info_standard(conn
,
7718 case SMB_INFO_SET_EA
:
7720 status
= smb_info_set_ea(conn
,
7728 case SMB_SET_FILE_BASIC_INFO
:
7729 case SMB_FILE_BASIC_INFORMATION
:
7731 status
= smb_set_file_basic_info(conn
,
7739 case SMB_FILE_ALLOCATION_INFORMATION
:
7740 case SMB_SET_FILE_ALLOCATION_INFO
:
7742 status
= smb_set_file_allocation_info(conn
, req
,
7750 case SMB_FILE_END_OF_FILE_INFORMATION
:
7751 case SMB_SET_FILE_END_OF_FILE_INFO
:
7754 * XP/Win7 both fail after the createfile with
7755 * SMB_SET_FILE_END_OF_FILE_INFO but not
7756 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
7757 * The level is known here, so pass it down
7761 (info_level
== SMB_SET_FILE_END_OF_FILE_INFO
);
7763 status
= smb_set_file_end_of_file_info(conn
, req
,
7772 case SMB_FILE_DISPOSITION_INFORMATION
:
7773 case SMB_SET_FILE_DISPOSITION_INFO
: /* Set delete on close for open file. */
7776 /* JRA - We used to just ignore this on a path ?
7777 * Shouldn't this be invalid level on a pathname
7780 if (tran_call
!= TRANSACT2_SETFILEINFO
) {
7781 return ERROR_NT(NT_STATUS_INVALID_LEVEL
);
7784 status
= smb_set_file_disposition_info(conn
,
7792 case SMB_FILE_POSITION_INFORMATION
:
7794 status
= smb_file_position_information(conn
,
7801 case SMB_FILE_FULL_EA_INFORMATION
:
7803 status
= smb_set_file_full_ea_info(conn
,
7810 /* From tridge Samba4 :
7811 * MODE_INFORMATION in setfileinfo (I have no
7812 * idea what "mode information" on a file is - it takes a value of 0,
7813 * 2, 4 or 6. What could it be?).
7816 case SMB_FILE_MODE_INFORMATION
:
7818 status
= smb_file_mode_information(conn
,
7825 * CIFS UNIX extensions.
7828 case SMB_SET_FILE_UNIX_BASIC
:
7830 status
= smb_set_file_unix_basic(conn
, req
,
7838 case SMB_SET_FILE_UNIX_INFO2
:
7840 status
= smb_set_file_unix_info2(conn
, req
,
7848 case SMB_SET_FILE_UNIX_LINK
:
7851 /* We must have a pathname for this. */
7852 return NT_STATUS_INVALID_LEVEL
;
7854 status
= smb_set_file_unix_link(conn
, req
, pdata
,
7855 total_data
, smb_fname
);
7859 case SMB_SET_FILE_UNIX_HLINK
:
7862 /* We must have a pathname for this. */
7863 return NT_STATUS_INVALID_LEVEL
;
7865 status
= smb_set_file_unix_hlink(conn
, req
,
7871 case SMB_FILE_RENAME_INFORMATION
:
7873 status
= smb_file_rename_information(conn
, req
,
7879 case SMB2_FILE_RENAME_INFORMATION_INTERNAL
:
7881 /* SMB2 rename information. */
7882 status
= smb2_file_rename_information(conn
, req
,
7888 case SMB_FILE_LINK_INFORMATION
:
7890 status
= smb_file_link_information(conn
, req
,
7896 #if defined(HAVE_POSIX_ACLS)
7897 case SMB_SET_POSIX_ACL
:
7899 status
= smb_set_posix_acl(conn
,
7908 case SMB_SET_POSIX_LOCK
:
7911 return NT_STATUS_INVALID_LEVEL
;
7913 status
= smb_set_posix_lock(conn
, req
,
7914 pdata
, total_data
, fsp
);
7918 case SMB_POSIX_PATH_OPEN
:
7921 /* We must have a pathname for this. */
7922 return NT_STATUS_INVALID_LEVEL
;
7925 status
= smb_posix_open(conn
, req
,
7933 case SMB_POSIX_PATH_UNLINK
:
7936 /* We must have a pathname for this. */
7937 return NT_STATUS_INVALID_LEVEL
;
7940 status
= smb_posix_unlink(conn
, req
,
7948 return NT_STATUS_INVALID_LEVEL
;
7951 if (!NT_STATUS_IS_OK(status
)) {
7955 *ret_data_size
= data_return_size
;
7956 return NT_STATUS_OK
;
7959 /****************************************************************************
7960 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
7961 ****************************************************************************/
7963 static void call_trans2setfilepathinfo(connection_struct
*conn
,
7964 struct smb_request
*req
,
7965 unsigned int tran_call
,
7966 char **pparams
, int total_params
,
7967 char **ppdata
, int total_data
,
7968 unsigned int max_data_bytes
)
7970 char *params
= *pparams
;
7971 char *pdata
= *ppdata
;
7973 struct smb_filename
*smb_fname
= NULL
;
7974 files_struct
*fsp
= NULL
;
7975 NTSTATUS status
= NT_STATUS_OK
;
7976 int data_return_size
= 0;
7979 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7983 if (tran_call
== TRANSACT2_SETFILEINFO
) {
7984 if (total_params
< 4) {
7985 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7989 fsp
= file_fsp(req
, SVAL(params
,0));
7990 /* Basic check for non-null fsp. */
7991 if (!check_fsp_open(conn
, req
, fsp
)) {
7994 info_level
= SVAL(params
,2);
7996 status
= copy_smb_filename(talloc_tos(), fsp
->fsp_name
,
7998 if (!NT_STATUS_IS_OK(status
)) {
7999 reply_nterror(req
, status
);
8003 if(fsp
->fh
->fd
== -1) {
8005 * This is actually a SETFILEINFO on a directory
8006 * handle (returned from an NT SMB). NT5.0 seems
8007 * to do this call. JRA.
8009 if (INFO_LEVEL_IS_UNIX(info_level
)) {
8010 /* Always do lstat for UNIX calls. */
8011 if (SMB_VFS_LSTAT(conn
, smb_fname
)) {
8012 DEBUG(3,("call_trans2setfilepathinfo: "
8013 "SMB_VFS_LSTAT of %s failed "
8015 smb_fname_str_dbg(smb_fname
),
8017 reply_nterror(req
, map_nt_error_from_unix(errno
));
8021 if (SMB_VFS_STAT(conn
, smb_fname
) != 0) {
8022 DEBUG(3,("call_trans2setfilepathinfo: "
8023 "fileinfo of %s failed (%s)\n",
8024 smb_fname_str_dbg(smb_fname
),
8026 reply_nterror(req
, map_nt_error_from_unix(errno
));
8030 } else if (fsp
->print_file
) {
8032 * Doing a DELETE_ON_CLOSE should cancel a print job.
8034 if ((info_level
== SMB_SET_FILE_DISPOSITION_INFO
) && CVAL(pdata
,0)) {
8035 fsp
->fh
->private_options
|= NTCREATEX_OPTIONS_PRIVATE_DELETE_ON_CLOSE
;
8037 DEBUG(3,("call_trans2setfilepathinfo: "
8038 "Cancelling print job (%s)\n",
8042 send_trans2_replies(conn
, req
, params
, 2,
8048 NT_STATUS_OBJECT_PATH_NOT_FOUND
);
8053 * Original code - this is an open file.
8055 if (SMB_VFS_FSTAT(fsp
, &smb_fname
->st
) != 0) {
8056 DEBUG(3,("call_trans2setfilepathinfo: fstat "
8057 "of %s failed (%s)\n", fsp_fnum_dbg(fsp
),
8059 reply_nterror(req
, map_nt_error_from_unix(errno
));
8065 uint32_t ucf_flags
= 0;
8068 if (total_params
< 7) {
8069 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8073 info_level
= SVAL(params
,0);
8074 srvstr_get_path(req
, params
, req
->flags2
, &fname
, ¶ms
[6],
8075 total_params
- 6, STR_TERMINATE
,
8077 if (!NT_STATUS_IS_OK(status
)) {
8078 reply_nterror(req
, status
);
8082 if (info_level
== SMB_SET_FILE_UNIX_BASIC
||
8083 info_level
== SMB_SET_FILE_UNIX_INFO2
||
8084 info_level
== SMB_FILE_RENAME_INFORMATION
||
8085 info_level
== SMB_POSIX_PATH_UNLINK
) {
8086 ucf_flags
|= UCF_UNIX_NAME_LOOKUP
;
8089 status
= filename_convert(req
, conn
,
8090 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
8095 if (!NT_STATUS_IS_OK(status
)) {
8096 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
8097 reply_botherror(req
,
8098 NT_STATUS_PATH_NOT_COVERED
,
8099 ERRSRV
, ERRbadpath
);
8102 reply_nterror(req
, status
);
8106 if (INFO_LEVEL_IS_UNIX(info_level
)) {
8108 * For CIFS UNIX extensions the target name may not exist.
8111 /* Always do lstat for UNIX calls. */
8112 SMB_VFS_LSTAT(conn
, smb_fname
);
8114 } else if (!VALID_STAT(smb_fname
->st
) &&
8115 SMB_VFS_STAT(conn
, smb_fname
)) {
8116 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
8118 smb_fname_str_dbg(smb_fname
),
8120 reply_nterror(req
, map_nt_error_from_unix(errno
));
8125 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (%s) info_level=%d "
8126 "totdata=%d\n", tran_call
, smb_fname_str_dbg(smb_fname
),
8128 info_level
,total_data
));
8130 /* Realloc the parameter size */
8131 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
8132 if (*pparams
== NULL
) {
8133 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8140 status
= smbd_do_setfilepathinfo(conn
, req
, req
,
8146 if (!NT_STATUS_IS_OK(status
)) {
8147 if (open_was_deferred(req
->sconn
, req
->mid
)) {
8148 /* We have re-scheduled this call. */
8151 if (blocking_lock_was_deferred_smb1(req
->sconn
, req
->mid
)) {
8152 /* We have re-scheduled this call. */
8155 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
8156 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
8157 ERRSRV
, ERRbadpath
);
8160 if (info_level
== SMB_POSIX_PATH_OPEN
) {
8161 reply_openerror(req
, status
);
8165 reply_nterror(req
, status
);
8169 send_trans2_replies(conn
, req
, params
, 2, *ppdata
, data_return_size
,
8175 /****************************************************************************
8176 Reply to a TRANS2_MKDIR (make directory with extended attributes).
8177 ****************************************************************************/
8179 static void call_trans2mkdir(connection_struct
*conn
, struct smb_request
*req
,
8180 char **pparams
, int total_params
,
8181 char **ppdata
, int total_data
,
8182 unsigned int max_data_bytes
)
8184 struct smb_filename
*smb_dname
= NULL
;
8185 char *params
= *pparams
;
8186 char *pdata
= *ppdata
;
8187 char *directory
= NULL
;
8188 NTSTATUS status
= NT_STATUS_OK
;
8189 struct ea_list
*ea_list
= NULL
;
8190 TALLOC_CTX
*ctx
= talloc_tos();
8192 if (!CAN_WRITE(conn
)) {
8193 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
8197 if (total_params
< 5) {
8198 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8202 srvstr_get_path(ctx
, params
, req
->flags2
, &directory
, ¶ms
[4],
8203 total_params
- 4, STR_TERMINATE
,
8205 if (!NT_STATUS_IS_OK(status
)) {
8206 reply_nterror(req
, status
);
8210 DEBUG(3,("call_trans2mkdir : name = %s\n", directory
));
8212 status
= filename_convert(ctx
,
8214 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
8220 if (!NT_STATUS_IS_OK(status
)) {
8221 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
8222 reply_botherror(req
,
8223 NT_STATUS_PATH_NOT_COVERED
,
8224 ERRSRV
, ERRbadpath
);
8227 reply_nterror(req
, status
);
8232 * OS/2 workplace shell seems to send SET_EA requests of "null"
8233 * length (4 bytes containing IVAL 4).
8234 * They seem to have no effect. Bug #3212. JRA.
8237 if (total_data
&& (total_data
!= 4)) {
8238 /* Any data in this call is an EA list. */
8239 if (total_data
< 10) {
8240 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8244 if (IVAL(pdata
,0) > total_data
) {
8245 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
8246 IVAL(pdata
,0), (unsigned int)total_data
));
8247 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8251 ea_list
= read_ea_list(talloc_tos(), pdata
+ 4,
8254 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8258 if (!lp_ea_support(SNUM(conn
))) {
8259 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
8263 /* If total_data == 4 Windows doesn't care what values
8264 * are placed in that field, it just ignores them.
8265 * The System i QNTC IBM SMB client puts bad values here,
8266 * so ignore them. */
8268 status
= create_directory(conn
, req
, smb_dname
);
8270 if (!NT_STATUS_IS_OK(status
)) {
8271 reply_nterror(req
, status
);
8275 /* Try and set any given EA. */
8277 status
= set_ea(conn
, NULL
, smb_dname
, ea_list
);
8278 if (!NT_STATUS_IS_OK(status
)) {
8279 reply_nterror(req
, status
);
8284 /* Realloc the parameter and data sizes */
8285 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
8286 if(*pparams
== NULL
) {
8287 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8294 send_trans2_replies(conn
, req
, params
, 2, *ppdata
, 0, max_data_bytes
);
8297 TALLOC_FREE(smb_dname
);
8301 /****************************************************************************
8302 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
8303 We don't actually do this - we just send a null response.
8304 ****************************************************************************/
8306 static void call_trans2findnotifyfirst(connection_struct
*conn
,
8307 struct smb_request
*req
,
8308 char **pparams
, int total_params
,
8309 char **ppdata
, int total_data
,
8310 unsigned int max_data_bytes
)
8312 char *params
= *pparams
;
8315 if (total_params
< 6) {
8316 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8320 info_level
= SVAL(params
,4);
8321 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level
));
8323 switch (info_level
) {
8328 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
8332 /* Realloc the parameter and data sizes */
8333 *pparams
= (char *)SMB_REALLOC(*pparams
,6);
8334 if (*pparams
== NULL
) {
8335 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8340 SSVAL(params
,0,fnf_handle
);
8341 SSVAL(params
,2,0); /* No changes */
8342 SSVAL(params
,4,0); /* No EA errors */
8349 send_trans2_replies(conn
, req
, params
, 6, *ppdata
, 0, max_data_bytes
);
8354 /****************************************************************************
8355 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
8356 changes). Currently this does nothing.
8357 ****************************************************************************/
8359 static void call_trans2findnotifynext(connection_struct
*conn
,
8360 struct smb_request
*req
,
8361 char **pparams
, int total_params
,
8362 char **ppdata
, int total_data
,
8363 unsigned int max_data_bytes
)
8365 char *params
= *pparams
;
8367 DEBUG(3,("call_trans2findnotifynext\n"));
8369 /* Realloc the parameter and data sizes */
8370 *pparams
= (char *)SMB_REALLOC(*pparams
,4);
8371 if (*pparams
== NULL
) {
8372 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8377 SSVAL(params
,0,0); /* No changes */
8378 SSVAL(params
,2,0); /* No EA errors */
8380 send_trans2_replies(conn
, req
, params
, 4, *ppdata
, 0, max_data_bytes
);
8385 /****************************************************************************
8386 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
8387 ****************************************************************************/
8389 static void call_trans2getdfsreferral(connection_struct
*conn
,
8390 struct smb_request
*req
,
8391 char **pparams
, int total_params
,
8392 char **ppdata
, int total_data
,
8393 unsigned int max_data_bytes
)
8395 char *params
= *pparams
;
8396 char *pathname
= NULL
;
8398 int max_referral_level
;
8399 NTSTATUS status
= NT_STATUS_OK
;
8400 TALLOC_CTX
*ctx
= talloc_tos();
8402 DEBUG(10,("call_trans2getdfsreferral\n"));
8404 if (total_params
< 3) {
8405 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8409 max_referral_level
= SVAL(params
,0);
8411 if(!lp_host_msdfs()) {
8412 reply_nterror(req
, NT_STATUS_NOT_IMPLEMENTED
);
8416 srvstr_pull_talloc(ctx
, params
, req
->flags2
, &pathname
, ¶ms
[2],
8417 total_params
- 2, STR_TERMINATE
);
8419 reply_nterror(req
, NT_STATUS_NOT_FOUND
);
8422 if((reply_size
= setup_dfs_referral(conn
, pathname
, max_referral_level
,
8423 ppdata
,&status
)) < 0) {
8424 reply_nterror(req
, status
);
8428 SSVAL((discard_const_p(uint8_t, req
->inbuf
)), smb_flg2
,
8429 SVAL(req
->inbuf
,smb_flg2
) | FLAGS2_DFS_PATHNAMES
);
8430 send_trans2_replies(conn
, req
,0,0,*ppdata
,reply_size
, max_data_bytes
);
8435 #define LMCAT_SPL 0x53
8436 #define LMFUNC_GETJOBID 0x60
8438 /****************************************************************************
8439 Reply to a TRANS2_IOCTL - used for OS/2 printing.
8440 ****************************************************************************/
8442 static void call_trans2ioctl(connection_struct
*conn
,
8443 struct smb_request
*req
,
8444 char **pparams
, int total_params
,
8445 char **ppdata
, int total_data
,
8446 unsigned int max_data_bytes
)
8448 char *pdata
= *ppdata
;
8449 files_struct
*fsp
= file_fsp(req
, SVAL(req
->vwv
+15, 0));
8451 /* check for an invalid fid before proceeding */
8454 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
8458 if ((SVAL(req
->vwv
+16, 0) == LMCAT_SPL
)
8459 && (SVAL(req
->vwv
+17, 0) == LMFUNC_GETJOBID
)) {
8460 *ppdata
= (char *)SMB_REALLOC(*ppdata
, 32);
8461 if (*ppdata
== NULL
) {
8462 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8467 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
8468 CAN ACCEPT THIS IN UNICODE. JRA. */
8471 SSVAL(pdata
, 0, print_spool_rap_jobid(fsp
->print_file
));
8473 srvstr_push(pdata
, req
->flags2
, pdata
+ 2,
8474 lp_netbios_name(), 15,
8475 STR_ASCII
|STR_TERMINATE
); /* Our NetBIOS name */
8476 srvstr_push(pdata
, req
->flags2
, pdata
+18,
8477 lp_servicename(talloc_tos(), SNUM(conn
)), 13,
8478 STR_ASCII
|STR_TERMINATE
); /* Service name */
8479 send_trans2_replies(conn
, req
, *pparams
, 0, *ppdata
, 32,
8484 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
8485 reply_nterror(req
, NT_STATUS_NOT_IMPLEMENTED
);
8488 /****************************************************************************
8489 Reply to a SMBfindclose (stop trans2 directory search).
8490 ****************************************************************************/
8492 void reply_findclose(struct smb_request
*req
)
8495 struct smbd_server_connection
*sconn
= req
->sconn
;
8497 START_PROFILE(SMBfindclose
);
8500 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8501 END_PROFILE(SMBfindclose
);
8505 dptr_num
= SVALS(req
->vwv
+0, 0);
8507 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num
));
8509 dptr_close(sconn
, &dptr_num
);
8511 reply_outbuf(req
, 0, 0);
8513 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num
));
8515 END_PROFILE(SMBfindclose
);
8519 /****************************************************************************
8520 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
8521 ****************************************************************************/
8523 void reply_findnclose(struct smb_request
*req
)
8527 START_PROFILE(SMBfindnclose
);
8530 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8531 END_PROFILE(SMBfindnclose
);
8535 dptr_num
= SVAL(req
->vwv
+0, 0);
8537 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num
));
8539 /* We never give out valid handles for a
8540 findnotifyfirst - so any dptr_num is ok here.
8543 reply_outbuf(req
, 0, 0);
8545 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num
));
8547 END_PROFILE(SMBfindnclose
);
8551 static void handle_trans2(connection_struct
*conn
, struct smb_request
*req
,
8552 struct trans_state
*state
)
8554 if (get_Protocol() >= PROTOCOL_NT1
) {
8555 req
->flags2
|= 0x40; /* IS_LONG_NAME */
8556 SSVAL((discard_const_p(uint8_t, req
->inbuf
)),smb_flg2
,req
->flags2
);
8559 if (ENCRYPTION_REQUIRED(conn
) && !req
->encrypted
) {
8560 if (state
->call
!= TRANSACT2_QFSINFO
&&
8561 state
->call
!= TRANSACT2_SETFSINFO
) {
8562 DEBUG(0,("handle_trans2: encryption required "
8564 (unsigned int)state
->call
));
8565 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
8570 SMB_PERFCOUNT_SET_SUBOP(&req
->pcd
, state
->call
);
8572 /* Now we must call the relevant TRANS2 function */
8573 switch(state
->call
) {
8574 case TRANSACT2_OPEN
:
8576 START_PROFILE(Trans2_open
);
8577 call_trans2open(conn
, req
,
8578 &state
->param
, state
->total_param
,
8579 &state
->data
, state
->total_data
,
8580 state
->max_data_return
);
8581 END_PROFILE(Trans2_open
);
8585 case TRANSACT2_FINDFIRST
:
8587 START_PROFILE(Trans2_findfirst
);
8588 call_trans2findfirst(conn
, req
,
8589 &state
->param
, state
->total_param
,
8590 &state
->data
, state
->total_data
,
8591 state
->max_data_return
);
8592 END_PROFILE(Trans2_findfirst
);
8596 case TRANSACT2_FINDNEXT
:
8598 START_PROFILE(Trans2_findnext
);
8599 call_trans2findnext(conn
, req
,
8600 &state
->param
, state
->total_param
,
8601 &state
->data
, state
->total_data
,
8602 state
->max_data_return
);
8603 END_PROFILE(Trans2_findnext
);
8607 case TRANSACT2_QFSINFO
:
8609 START_PROFILE(Trans2_qfsinfo
);
8610 call_trans2qfsinfo(conn
, req
,
8611 &state
->param
, state
->total_param
,
8612 &state
->data
, state
->total_data
,
8613 state
->max_data_return
);
8614 END_PROFILE(Trans2_qfsinfo
);
8618 case TRANSACT2_SETFSINFO
:
8620 START_PROFILE(Trans2_setfsinfo
);
8621 call_trans2setfsinfo(conn
, req
,
8622 &state
->param
, state
->total_param
,
8623 &state
->data
, state
->total_data
,
8624 state
->max_data_return
);
8625 END_PROFILE(Trans2_setfsinfo
);
8629 case TRANSACT2_QPATHINFO
:
8630 case TRANSACT2_QFILEINFO
:
8632 START_PROFILE(Trans2_qpathinfo
);
8633 call_trans2qfilepathinfo(conn
, req
, state
->call
,
8634 &state
->param
, state
->total_param
,
8635 &state
->data
, state
->total_data
,
8636 state
->max_data_return
);
8637 END_PROFILE(Trans2_qpathinfo
);
8641 case TRANSACT2_SETPATHINFO
:
8642 case TRANSACT2_SETFILEINFO
:
8644 START_PROFILE(Trans2_setpathinfo
);
8645 call_trans2setfilepathinfo(conn
, req
, state
->call
,
8646 &state
->param
, state
->total_param
,
8647 &state
->data
, state
->total_data
,
8648 state
->max_data_return
);
8649 END_PROFILE(Trans2_setpathinfo
);
8653 case TRANSACT2_FINDNOTIFYFIRST
:
8655 START_PROFILE(Trans2_findnotifyfirst
);
8656 call_trans2findnotifyfirst(conn
, req
,
8657 &state
->param
, state
->total_param
,
8658 &state
->data
, state
->total_data
,
8659 state
->max_data_return
);
8660 END_PROFILE(Trans2_findnotifyfirst
);
8664 case TRANSACT2_FINDNOTIFYNEXT
:
8666 START_PROFILE(Trans2_findnotifynext
);
8667 call_trans2findnotifynext(conn
, req
,
8668 &state
->param
, state
->total_param
,
8669 &state
->data
, state
->total_data
,
8670 state
->max_data_return
);
8671 END_PROFILE(Trans2_findnotifynext
);
8675 case TRANSACT2_MKDIR
:
8677 START_PROFILE(Trans2_mkdir
);
8678 call_trans2mkdir(conn
, req
,
8679 &state
->param
, state
->total_param
,
8680 &state
->data
, state
->total_data
,
8681 state
->max_data_return
);
8682 END_PROFILE(Trans2_mkdir
);
8686 case TRANSACT2_GET_DFS_REFERRAL
:
8688 START_PROFILE(Trans2_get_dfs_referral
);
8689 call_trans2getdfsreferral(conn
, req
,
8690 &state
->param
, state
->total_param
,
8691 &state
->data
, state
->total_data
,
8692 state
->max_data_return
);
8693 END_PROFILE(Trans2_get_dfs_referral
);
8697 case TRANSACT2_IOCTL
:
8699 START_PROFILE(Trans2_ioctl
);
8700 call_trans2ioctl(conn
, req
,
8701 &state
->param
, state
->total_param
,
8702 &state
->data
, state
->total_data
,
8703 state
->max_data_return
);
8704 END_PROFILE(Trans2_ioctl
);
8709 /* Error in request */
8710 DEBUG(2,("Unknown request %d in trans2 call\n", state
->call
));
8711 reply_nterror(req
, NT_STATUS_NOT_IMPLEMENTED
);
8715 /****************************************************************************
8716 Reply to a SMBtrans2.
8717 ****************************************************************************/
8719 void reply_trans2(struct smb_request
*req
)
8721 connection_struct
*conn
= req
->conn
;
8726 unsigned int tran_call
;
8727 struct trans_state
*state
;
8730 START_PROFILE(SMBtrans2
);
8732 if (req
->wct
< 14) {
8733 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8734 END_PROFILE(SMBtrans2
);
8738 dsoff
= SVAL(req
->vwv
+12, 0);
8739 dscnt
= SVAL(req
->vwv
+11, 0);
8740 psoff
= SVAL(req
->vwv
+10, 0);
8741 pscnt
= SVAL(req
->vwv
+9, 0);
8742 tran_call
= SVAL(req
->vwv
+14, 0);
8744 result
= allow_new_trans(conn
->pending_trans
, req
->mid
);
8745 if (!NT_STATUS_IS_OK(result
)) {
8746 DEBUG(2, ("Got invalid trans2 request: %s\n",
8747 nt_errstr(result
)));
8748 reply_nterror(req
, result
);
8749 END_PROFILE(SMBtrans2
);
8754 switch (tran_call
) {
8755 /* List the allowed trans2 calls on IPC$ */
8756 case TRANSACT2_OPEN
:
8757 case TRANSACT2_GET_DFS_REFERRAL
:
8758 case TRANSACT2_QFILEINFO
:
8759 case TRANSACT2_QFSINFO
:
8760 case TRANSACT2_SETFSINFO
:
8763 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
8764 END_PROFILE(SMBtrans2
);
8769 if ((state
= talloc(conn
, struct trans_state
)) == NULL
) {
8770 DEBUG(0, ("talloc failed\n"));
8771 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8772 END_PROFILE(SMBtrans2
);
8776 state
->cmd
= SMBtrans2
;
8778 state
->mid
= req
->mid
;
8779 state
->vuid
= req
->vuid
;
8780 state
->setup_count
= SVAL(req
->vwv
+13, 0);
8781 state
->setup
= NULL
;
8782 state
->total_param
= SVAL(req
->vwv
+0, 0);
8783 state
->param
= NULL
;
8784 state
->total_data
= SVAL(req
->vwv
+1, 0);
8786 state
->max_param_return
= SVAL(req
->vwv
+2, 0);
8787 state
->max_data_return
= SVAL(req
->vwv
+3, 0);
8788 state
->max_setup_return
= SVAL(req
->vwv
+4, 0);
8789 state
->close_on_completion
= BITSETW(req
->vwv
+5, 0);
8790 state
->one_way
= BITSETW(req
->vwv
+5, 1);
8792 state
->call
= tran_call
;
8794 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
8795 is so as a sanity check */
8796 if (state
->setup_count
!= 1) {
8798 * Need to have rc=0 for ioctl to get job id for OS/2.
8799 * Network printing will fail if function is not successful.
8800 * Similar function in reply.c will be used if protocol
8801 * is LANMAN1.0 instead of LM1.2X002.
8802 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
8803 * outbuf doesn't have to be set(only job id is used).
8805 if ( (state
->setup_count
== 4)
8806 && (tran_call
== TRANSACT2_IOCTL
)
8807 && (SVAL(req
->vwv
+16, 0) == LMCAT_SPL
)
8808 && (SVAL(req
->vwv
+17, 0) == LMFUNC_GETJOBID
)) {
8809 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
8811 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state
->setup_count
));
8812 DEBUG(2,("Transaction is %d\n",tran_call
));
8814 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8815 END_PROFILE(SMBtrans2
);
8820 if ((dscnt
> state
->total_data
) || (pscnt
> state
->total_param
))
8823 if (state
->total_data
) {
8825 if (trans_oob(state
->total_data
, 0, dscnt
)
8826 || trans_oob(smb_len(req
->inbuf
), dsoff
, dscnt
)) {
8830 /* Can't use talloc here, the core routines do realloc on the
8831 * params and data. */
8832 state
->data
= (char *)SMB_MALLOC(state
->total_data
);
8833 if (state
->data
== NULL
) {
8834 DEBUG(0,("reply_trans2: data malloc fail for %u "
8835 "bytes !\n", (unsigned int)state
->total_data
));
8837 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8838 END_PROFILE(SMBtrans2
);
8842 memcpy(state
->data
,smb_base(req
->inbuf
)+dsoff
,dscnt
);
8845 if (state
->total_param
) {
8847 if (trans_oob(state
->total_param
, 0, pscnt
)
8848 || trans_oob(smb_len(req
->inbuf
), psoff
, pscnt
)) {
8852 /* Can't use talloc here, the core routines do realloc on the
8853 * params and data. */
8854 state
->param
= (char *)SMB_MALLOC(state
->total_param
);
8855 if (state
->param
== NULL
) {
8856 DEBUG(0,("reply_trans: param malloc fail for %u "
8857 "bytes !\n", (unsigned int)state
->total_param
));
8858 SAFE_FREE(state
->data
);
8860 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8861 END_PROFILE(SMBtrans2
);
8865 memcpy(state
->param
,smb_base(req
->inbuf
)+psoff
,pscnt
);
8868 state
->received_data
= dscnt
;
8869 state
->received_param
= pscnt
;
8871 if ((state
->received_param
== state
->total_param
) &&
8872 (state
->received_data
== state
->total_data
)) {
8874 handle_trans2(conn
, req
, state
);
8876 SAFE_FREE(state
->data
);
8877 SAFE_FREE(state
->param
);
8879 END_PROFILE(SMBtrans2
);
8883 DLIST_ADD(conn
->pending_trans
, state
);
8885 /* We need to send an interim response then receive the rest
8886 of the parameter/data bytes */
8887 reply_outbuf(req
, 0, 0);
8888 show_msg((char *)req
->outbuf
);
8889 END_PROFILE(SMBtrans2
);
8894 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
8895 SAFE_FREE(state
->data
);
8896 SAFE_FREE(state
->param
);
8898 END_PROFILE(SMBtrans2
);
8899 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8903 /****************************************************************************
8904 Reply to a SMBtranss2
8905 ****************************************************************************/
8907 void reply_transs2(struct smb_request
*req
)
8909 connection_struct
*conn
= req
->conn
;
8910 unsigned int pcnt
,poff
,dcnt
,doff
,pdisp
,ddisp
;
8911 struct trans_state
*state
;
8913 START_PROFILE(SMBtranss2
);
8915 show_msg((const char *)req
->inbuf
);
8917 /* Windows clients expect all replies to
8918 a transact secondary (SMBtranss2 0x33)
8919 to have a command code of transact
8920 (SMBtrans2 0x32). See bug #8989
8921 and also [MS-CIFS] section 2.2.4.47.2
8924 req
->cmd
= SMBtrans2
;
8927 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8928 END_PROFILE(SMBtranss2
);
8932 for (state
= conn
->pending_trans
; state
!= NULL
;
8933 state
= state
->next
) {
8934 if (state
->mid
== req
->mid
) {
8939 if ((state
== NULL
) || (state
->cmd
!= SMBtrans2
)) {
8940 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8941 END_PROFILE(SMBtranss2
);
8945 /* Revise state->total_param and state->total_data in case they have
8946 changed downwards */
8948 if (SVAL(req
->vwv
+0, 0) < state
->total_param
)
8949 state
->total_param
= SVAL(req
->vwv
+0, 0);
8950 if (SVAL(req
->vwv
+1, 0) < state
->total_data
)
8951 state
->total_data
= SVAL(req
->vwv
+1, 0);
8953 pcnt
= SVAL(req
->vwv
+2, 0);
8954 poff
= SVAL(req
->vwv
+3, 0);
8955 pdisp
= SVAL(req
->vwv
+4, 0);
8957 dcnt
= SVAL(req
->vwv
+5, 0);
8958 doff
= SVAL(req
->vwv
+6, 0);
8959 ddisp
= SVAL(req
->vwv
+7, 0);
8961 state
->received_param
+= pcnt
;
8962 state
->received_data
+= dcnt
;
8964 if ((state
->received_data
> state
->total_data
) ||
8965 (state
->received_param
> state
->total_param
))
8969 if (trans_oob(state
->total_param
, pdisp
, pcnt
)
8970 || trans_oob(smb_len(req
->inbuf
), poff
, pcnt
)) {
8973 memcpy(state
->param
+pdisp
,smb_base(req
->inbuf
)+poff
,pcnt
);
8977 if (trans_oob(state
->total_data
, ddisp
, dcnt
)
8978 || trans_oob(smb_len(req
->inbuf
), doff
, dcnt
)) {
8981 memcpy(state
->data
+ddisp
, smb_base(req
->inbuf
)+doff
,dcnt
);
8984 if ((state
->received_param
< state
->total_param
) ||
8985 (state
->received_data
< state
->total_data
)) {
8986 END_PROFILE(SMBtranss2
);
8990 handle_trans2(conn
, req
, state
);
8992 DLIST_REMOVE(conn
->pending_trans
, state
);
8993 SAFE_FREE(state
->data
);
8994 SAFE_FREE(state
->param
);
8997 END_PROFILE(SMBtranss2
);
9002 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
9003 DLIST_REMOVE(conn
->pending_trans
, state
);
9004 SAFE_FREE(state
->data
);
9005 SAFE_FREE(state
->param
);
9007 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
9008 END_PROFILE(SMBtranss2
);