2 Unix SMB/CIFS implementation.
3 SMB transaction2 handling
4 Copyright (C) Jeremy Allison 1994-2007
5 Copyright (C) Stefan (metze) Metzmacher 2003
6 Copyright (C) Volker Lendecke 2005-2007
7 Copyright (C) Steve French 2005
8 Copyright (C) James Peach 2006-2007
10 Extensively modified by Andrew Tridgell, 1995
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 3 of the License, or
15 (at your option) any later version.
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with this program. If not, see <http://www.gnu.org/licenses/>.
28 #include "system/filesys.h"
30 #include "smbd/smbd.h"
31 #include "smbd/globals.h"
32 #include "../libcli/auth/libcli_auth.h"
33 #include "../librpc/gen_ndr/xattr.h"
34 #include "../librpc/gen_ndr/ndr_security.h"
35 #include "../librpc/gen_ndr/open_files.h"
36 #include "libcli/security/security.h"
39 #include "smbprofile.h"
40 #include "rpc_server/srv_pipe_hnd.h"
42 #include "lib/util_ea.h"
44 #define DIR_ENTRY_SAFETY_MARGIN 4096
46 static char *store_file_unix_basic(connection_struct
*conn
,
49 const SMB_STRUCT_STAT
*psbuf
);
51 static char *store_file_unix_basic_info2(connection_struct
*conn
,
54 const SMB_STRUCT_STAT
*psbuf
);
56 /********************************************************************
57 The canonical "check access" based on object handle or path function.
58 ********************************************************************/
60 NTSTATUS
check_access(connection_struct
*conn
,
62 const struct smb_filename
*smb_fname
,
66 if (!(fsp
->access_mask
& access_mask
)) {
67 return NT_STATUS_ACCESS_DENIED
;
70 NTSTATUS status
= smbd_check_access_rights(conn
,
74 if (!NT_STATUS_IS_OK(status
)) {
81 /********************************************************************
82 Roundup a value to the nearest allocation roundup size boundary.
83 Only do this for Windows clients.
84 ********************************************************************/
86 uint64_t smb_roundup(connection_struct
*conn
, uint64_t val
)
88 uint64_t rval
= lp_allocation_roundup_size(SNUM(conn
));
90 /* Only roundup for Windows clients. */
91 enum remote_arch_types ra_type
= get_remote_arch();
92 if (rval
&& (ra_type
!= RA_SAMBA
) && (ra_type
!= RA_CIFSFS
)) {
93 val
= SMB_ROUNDUP(val
,rval
);
98 /********************************************************************
99 Create a 64 bit FileIndex. If the file is on the same device as
100 the root of the share, just return the 64-bit inode. If it isn't,
101 mangle as we used to do.
102 ********************************************************************/
104 uint64_t get_FileIndex(connection_struct
*conn
, const SMB_STRUCT_STAT
*psbuf
)
107 if (conn
->base_share_dev
== psbuf
->st_ex_dev
) {
108 return (uint64_t)psbuf
->st_ex_ino
;
110 file_index
= ((psbuf
->st_ex_ino
) & UINT32_MAX
); /* FileIndexLow */
111 file_index
|= ((uint64_t)((psbuf
->st_ex_dev
) & UINT32_MAX
)) << 32; /* FileIndexHigh */
115 /****************************************************************************
116 Utility functions for dealing with extended attributes.
117 ****************************************************************************/
119 /****************************************************************************
120 Refuse to allow clients to overwrite our private xattrs.
121 ****************************************************************************/
123 static bool samba_private_attr_name(const char *unix_ea_name
)
125 static const char * const prohibited_ea_names
[] = {
126 SAMBA_POSIX_INHERITANCE_EA_NAME
,
127 SAMBA_XATTR_DOS_ATTRIB
,
135 for (i
= 0; prohibited_ea_names
[i
]; i
++) {
136 if (strequal( prohibited_ea_names
[i
], unix_ea_name
))
139 if (strncasecmp_m(unix_ea_name
, SAMBA_XATTR_DOSSTREAM_PREFIX
,
140 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX
)) == 0) {
146 /****************************************************************************
147 Get one EA value. Fill in a struct ea_struct.
148 ****************************************************************************/
150 NTSTATUS
get_ea_value(TALLOC_CTX
*mem_ctx
, connection_struct
*conn
,
151 files_struct
*fsp
, const char *fname
,
152 const char *ea_name
, struct ea_struct
*pea
)
154 /* Get the value of this xattr. Max size is 64k. */
155 size_t attr_size
= 256;
161 val
= talloc_realloc(mem_ctx
, val
, char, attr_size
);
163 return NT_STATUS_NO_MEMORY
;
166 if (fsp
&& fsp
->fh
->fd
!= -1) {
167 sizeret
= SMB_VFS_FGETXATTR(fsp
, ea_name
, val
, attr_size
);
169 sizeret
= SMB_VFS_GETXATTR(conn
, fname
, ea_name
, val
, attr_size
);
172 if (sizeret
== -1 && errno
== ERANGE
&& attr_size
!= 65536) {
178 return map_nt_error_from_unix(errno
);
181 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name
, (unsigned int)sizeret
));
182 dump_data(10, (uint8
*)val
, sizeret
);
185 if (strnequal(ea_name
, "user.", 5)) {
186 pea
->name
= talloc_strdup(mem_ctx
, &ea_name
[5]);
188 pea
->name
= talloc_strdup(mem_ctx
, ea_name
);
190 if (pea
->name
== NULL
) {
192 return NT_STATUS_NO_MEMORY
;
194 pea
->value
.data
= (unsigned char *)val
;
195 pea
->value
.length
= (size_t)sizeret
;
199 NTSTATUS
get_ea_names_from_file(TALLOC_CTX
*mem_ctx
, connection_struct
*conn
,
200 files_struct
*fsp
, const char *fname
,
201 char ***pnames
, size_t *pnum_names
)
203 /* Get a list of all xattrs. Max namesize is 64k. */
204 size_t ea_namelist_size
= 1024;
205 char *ea_namelist
= NULL
;
210 ssize_t sizeret
= -1;
212 if (!lp_ea_support(SNUM(conn
))) {
221 * TALLOC the result early to get the talloc hierarchy right.
224 names
= talloc_array(mem_ctx
, char *, 1);
226 DEBUG(0, ("talloc failed\n"));
227 return NT_STATUS_NO_MEMORY
;
230 while (ea_namelist_size
<= 65536) {
232 ea_namelist
= talloc_realloc(
233 names
, ea_namelist
, char, ea_namelist_size
);
234 if (ea_namelist
== NULL
) {
235 DEBUG(0, ("talloc failed\n"));
237 return NT_STATUS_NO_MEMORY
;
240 if (fsp
&& fsp
->fh
->fd
!= -1) {
241 sizeret
= SMB_VFS_FLISTXATTR(fsp
, ea_namelist
,
244 sizeret
= SMB_VFS_LISTXATTR(conn
, fname
, ea_namelist
,
248 if ((sizeret
== -1) && (errno
== ERANGE
)) {
249 ea_namelist_size
*= 2;
258 return map_nt_error_from_unix(errno
);
261 DEBUG(10, ("get_ea_list_from_file: ea_namelist size = %u\n",
262 (unsigned int)sizeret
));
274 * Ensure the result is 0-terminated
277 if (ea_namelist
[sizeret
-1] != '\0') {
279 return NT_STATUS_INTERNAL_ERROR
;
287 for (p
= ea_namelist
; p
- ea_namelist
< sizeret
; p
+= strlen(p
)+1) {
291 tmp
= talloc_realloc(mem_ctx
, names
, char *, num_names
);
293 DEBUG(0, ("talloc failed\n"));
295 return NT_STATUS_NO_MEMORY
;
301 for (p
= ea_namelist
; p
- ea_namelist
< sizeret
; p
+= strlen(p
)+1) {
302 names
[num_names
++] = p
;
310 *pnum_names
= num_names
;
314 /****************************************************************************
315 Return a linked list of the total EA's. Plus the total size
316 ****************************************************************************/
318 static NTSTATUS
get_ea_list_from_file_path(TALLOC_CTX
*mem_ctx
, connection_struct
*conn
, files_struct
*fsp
,
319 const char *fname
, size_t *pea_total_len
, struct ea_list
**ea_list
)
321 /* Get a list of all xattrs. Max namesize is 64k. */
324 struct ea_list
*ea_list_head
= NULL
;
330 status
= get_ea_names_from_file(talloc_tos(), conn
, fsp
, fname
,
333 if (!NT_STATUS_IS_OK(status
)) {
337 if (num_names
== 0) {
342 for (i
=0; i
<num_names
; i
++) {
343 struct ea_list
*listp
;
346 if (strnequal(names
[i
], "system.", 7)
347 || samba_private_attr_name(names
[i
]))
351 * Filter out any underlying POSIX EA names
352 * that a Windows client can't handle.
354 if (!lp_posix_pathnames() &&
355 is_invalid_windows_ea_name(names
[i
])) {
359 listp
= talloc(mem_ctx
, struct ea_list
);
361 return NT_STATUS_NO_MEMORY
;
364 status
= get_ea_value(listp
, conn
, fsp
,
368 if (!NT_STATUS_IS_OK(status
)) {
373 if (listp
->ea
.value
.length
== 0) {
375 * We can never return a zero length EA.
376 * Windows reports the EA's as corrupted.
382 push_ascii_fstring(dos_ea_name
, listp
->ea
.name
);
385 4 + strlen(dos_ea_name
) + 1 + listp
->ea
.value
.length
;
387 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
388 "= %u\n", (unsigned int)*pea_total_len
, dos_ea_name
,
389 (unsigned int)listp
->ea
.value
.length
));
391 DLIST_ADD_END(ea_list_head
, listp
, struct ea_list
*);
395 /* Add on 4 for total length. */
396 if (*pea_total_len
) {
400 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
401 (unsigned int)*pea_total_len
));
403 *ea_list
= ea_list_head
;
407 static NTSTATUS
get_ea_list_from_file(TALLOC_CTX
*mem_ctx
, connection_struct
*conn
, files_struct
*fsp
,
408 const struct smb_filename
*smb_fname
, size_t *pea_total_len
, struct ea_list
**ea_list
)
413 if (!lp_ea_support(SNUM(conn
))) {
417 if (is_ntfs_stream_smb_fname(smb_fname
)) {
418 return NT_STATUS_INVALID_PARAMETER
;
421 return get_ea_list_from_file_path(mem_ctx
, conn
, fsp
, smb_fname
->base_name
, pea_total_len
, ea_list
);
424 /****************************************************************************
425 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
427 ****************************************************************************/
429 static unsigned int fill_ea_buffer(TALLOC_CTX
*mem_ctx
, char *pdata
, unsigned int total_data_size
,
430 connection_struct
*conn
, struct ea_list
*ea_list
)
432 unsigned int ret_data_size
= 4;
435 SMB_ASSERT(total_data_size
>= 4);
437 if (!lp_ea_support(SNUM(conn
))) {
442 for (p
= pdata
+ 4; ea_list
; ea_list
= ea_list
->next
) {
445 push_ascii_fstring(dos_ea_name
, ea_list
->ea
.name
);
446 dos_namelen
= strlen(dos_ea_name
);
447 if (dos_namelen
> 255 || dos_namelen
== 0) {
450 if (ea_list
->ea
.value
.length
> 65535) {
453 if (4 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
> total_data_size
) {
457 /* We know we have room. */
458 SCVAL(p
,0,ea_list
->ea
.flags
);
459 SCVAL(p
,1,dos_namelen
);
460 SSVAL(p
,2,ea_list
->ea
.value
.length
);
461 strlcpy(p
+4, dos_ea_name
, dos_namelen
+1);
462 memcpy( p
+ 4 + dos_namelen
+ 1, ea_list
->ea
.value
.data
, ea_list
->ea
.value
.length
);
464 total_data_size
-= 4 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
;
465 p
+= 4 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
;
468 ret_data_size
= PTR_DIFF(p
, pdata
);
469 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size
));
470 SIVAL(pdata
,0,ret_data_size
);
471 return ret_data_size
;
474 static NTSTATUS
fill_ea_chained_buffer(TALLOC_CTX
*mem_ctx
,
476 unsigned int total_data_size
,
477 unsigned int *ret_data_size
,
478 connection_struct
*conn
,
479 struct ea_list
*ea_list
)
481 uint8_t *p
= (uint8_t *)pdata
;
482 uint8_t *last_start
= NULL
;
483 bool do_store_data
= (pdata
!= NULL
);
487 if (!lp_ea_support(SNUM(conn
))) {
488 return NT_STATUS_NO_EAS_ON_FILE
;
491 for (; ea_list
; ea_list
= ea_list
->next
) {
497 if (last_start
!= NULL
&& do_store_data
) {
498 SIVAL(last_start
, 0, PTR_DIFF(p
, last_start
));
502 push_ascii_fstring(dos_ea_name
, ea_list
->ea
.name
);
503 dos_namelen
= strlen(dos_ea_name
);
504 if (dos_namelen
> 255 || dos_namelen
== 0) {
505 return NT_STATUS_INTERNAL_ERROR
;
507 if (ea_list
->ea
.value
.length
> 65535) {
508 return NT_STATUS_INTERNAL_ERROR
;
511 this_size
= 0x08 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
;
514 pad
= (4 - (this_size
% 4)) % 4;
519 if (this_size
> total_data_size
) {
520 return NT_STATUS_INFO_LENGTH_MISMATCH
;
523 /* We know we have room. */
524 SIVAL(p
, 0x00, 0); /* next offset */
525 SCVAL(p
, 0x04, ea_list
->ea
.flags
);
526 SCVAL(p
, 0x05, dos_namelen
);
527 SSVAL(p
, 0x06, ea_list
->ea
.value
.length
);
528 strlcpy((char *)(p
+0x08), dos_ea_name
, dos_namelen
+1);
529 memcpy(p
+ 0x08 + dos_namelen
+ 1, ea_list
->ea
.value
.data
, ea_list
->ea
.value
.length
);
531 memset(p
+ 0x08 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
,
535 total_data_size
-= this_size
;
541 *ret_data_size
= PTR_DIFF(p
, pdata
);
542 DEBUG(10,("fill_ea_chained_buffer: data_size = %u\n", *ret_data_size
));
546 static unsigned int estimate_ea_size(connection_struct
*conn
, files_struct
*fsp
, const struct smb_filename
*smb_fname
)
548 size_t total_ea_len
= 0;
550 struct ea_list
*ea_list
= NULL
;
552 if (!lp_ea_support(SNUM(conn
))) {
555 mem_ctx
= talloc_stackframe();
557 /* If this is a stream fsp, then we need to instead find the
558 * estimated ea len from the main file, not the stream
559 * (streams cannot have EAs), but the estimate isn't just 0 in
561 if (is_ntfs_stream_smb_fname(smb_fname
)) {
564 (void)get_ea_list_from_file_path(mem_ctx
, conn
, fsp
, smb_fname
->base_name
, &total_ea_len
, &ea_list
);
565 if(conn
->sconn
->using_smb2
) {
567 unsigned int ret_data_size
;
569 * We're going to be using fill_ea_chained_buffer() to
570 * marshall EA's - this size is significantly larger
571 * than the SMB1 buffer. Re-calculate the size without
574 status
= fill_ea_chained_buffer(mem_ctx
,
580 if (!NT_STATUS_IS_OK(status
)) {
583 total_ea_len
= ret_data_size
;
585 TALLOC_FREE(mem_ctx
);
589 /****************************************************************************
590 Ensure the EA name is case insensitive by matching any existing EA name.
591 ****************************************************************************/
593 static void canonicalize_ea_name(connection_struct
*conn
, files_struct
*fsp
, const char *fname
, fstring unix_ea_name
)
596 TALLOC_CTX
*mem_ctx
= talloc_tos();
597 struct ea_list
*ea_list
;
598 NTSTATUS status
= get_ea_list_from_file_path(mem_ctx
, conn
, fsp
, fname
, &total_ea_len
, &ea_list
);
599 if (!NT_STATUS_IS_OK(status
)) {
603 for (; ea_list
; ea_list
= ea_list
->next
) {
604 if (strequal(&unix_ea_name
[5], ea_list
->ea
.name
)) {
605 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
606 &unix_ea_name
[5], ea_list
->ea
.name
));
607 strlcpy(&unix_ea_name
[5], ea_list
->ea
.name
, sizeof(fstring
)-5);
613 /****************************************************************************
614 Set or delete an extended attribute.
615 ****************************************************************************/
617 NTSTATUS
set_ea(connection_struct
*conn
, files_struct
*fsp
,
618 const struct smb_filename
*smb_fname
, struct ea_list
*ea_list
)
623 if (!lp_ea_support(SNUM(conn
))) {
624 return NT_STATUS_EAS_NOT_SUPPORTED
;
627 status
= check_access(conn
, fsp
, smb_fname
, FILE_WRITE_EA
);
628 if (!NT_STATUS_IS_OK(status
)) {
632 /* Setting EAs on streams isn't supported. */
633 if (is_ntfs_stream_smb_fname(smb_fname
)) {
634 return NT_STATUS_INVALID_PARAMETER
;
638 * Filter out invalid Windows EA names - before
639 * we set *any* of them.
642 if (ea_list_has_invalid_name(ea_list
)) {
643 return STATUS_INVALID_EA_NAME
;
646 fname
= smb_fname
->base_name
;
648 for (;ea_list
; ea_list
= ea_list
->next
) {
650 fstring unix_ea_name
;
652 fstrcpy(unix_ea_name
, "user."); /* All EA's must start with user. */
653 fstrcat(unix_ea_name
, ea_list
->ea
.name
);
655 canonicalize_ea_name(conn
, fsp
, fname
, unix_ea_name
);
657 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name
, (unsigned int)ea_list
->ea
.value
.length
));
659 if (samba_private_attr_name(unix_ea_name
)) {
660 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name
));
661 return NT_STATUS_ACCESS_DENIED
;
664 if (ea_list
->ea
.value
.length
== 0) {
665 /* Remove the attribute. */
666 if (fsp
&& (fsp
->fh
->fd
!= -1)) {
667 DEBUG(10,("set_ea: deleting ea name %s on "
668 "file %s by file descriptor.\n",
669 unix_ea_name
, fsp_str_dbg(fsp
)));
670 ret
= SMB_VFS_FREMOVEXATTR(fsp
, unix_ea_name
);
672 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
673 unix_ea_name
, fname
));
674 ret
= SMB_VFS_REMOVEXATTR(conn
, fname
, unix_ea_name
);
677 /* Removing a non existent attribute always succeeds. */
678 if (ret
== -1 && errno
== ENOATTR
) {
679 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
685 if (fsp
&& (fsp
->fh
->fd
!= -1)) {
686 DEBUG(10,("set_ea: setting ea name %s on file "
687 "%s by file descriptor.\n",
688 unix_ea_name
, fsp_str_dbg(fsp
)));
689 ret
= SMB_VFS_FSETXATTR(fsp
, unix_ea_name
,
690 ea_list
->ea
.value
.data
, ea_list
->ea
.value
.length
, 0);
692 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
693 unix_ea_name
, fname
));
694 ret
= SMB_VFS_SETXATTR(conn
, fname
, unix_ea_name
,
695 ea_list
->ea
.value
.data
, ea_list
->ea
.value
.length
, 0);
701 if (errno
== ENOTSUP
) {
702 return NT_STATUS_EAS_NOT_SUPPORTED
;
705 return map_nt_error_from_unix(errno
);
711 /****************************************************************************
712 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
713 ****************************************************************************/
715 static struct ea_list
*read_ea_name_list(TALLOC_CTX
*ctx
, const char *pdata
, size_t data_size
)
717 struct ea_list
*ea_list_head
= NULL
;
718 size_t converted_size
, offset
= 0;
720 while (offset
+ 2 < data_size
) {
721 struct ea_list
*eal
= talloc_zero(ctx
, struct ea_list
);
722 unsigned int namelen
= CVAL(pdata
,offset
);
724 offset
++; /* Go past the namelen byte. */
726 /* integer wrap paranioa. */
727 if ((offset
+ namelen
< offset
) || (offset
+ namelen
< namelen
) ||
728 (offset
> data_size
) || (namelen
> data_size
) ||
729 (offset
+ namelen
>= data_size
)) {
732 /* Ensure the name is null terminated. */
733 if (pdata
[offset
+ namelen
] != '\0') {
736 if (!pull_ascii_talloc(ctx
, &eal
->ea
.name
, &pdata
[offset
],
738 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
739 "failed: %s", strerror(errno
)));
745 offset
+= (namelen
+ 1); /* Go past the name + terminating zero. */
746 DLIST_ADD_END(ea_list_head
, eal
, struct ea_list
*);
747 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal
->ea
.name
));
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
,
847 /* As we are using a protocol > LANMAN1 then the max_send
848 variable must have been set in the sessetupX call.
849 This takes precedence over the max_xmit field in the
850 global struct. These different max_xmit variables should
851 be merged as this is now too confusing */
853 int data_to_send
= datasize
;
854 int params_to_send
= paramsize
;
856 const char *pp
= params
;
857 const char *pd
= pdata
;
858 int params_sent_thistime
, data_sent_thistime
, total_sent_thistime
;
859 int alignment_offset
= 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
860 int data_alignment_offset
= 0;
861 bool overflow
= False
;
862 struct smbd_server_connection
*sconn
= req
->sconn
;
863 int max_send
= sconn
->smb1
.sessions
.max_send
;
865 /* Modify the data_to_send and datasize and set the error if
866 we're trying to send more than max_data_bytes. We still send
867 the part of the packet(s) that fit. Strange, but needed
870 if (max_data_bytes
> 0 && datasize
> max_data_bytes
) {
871 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
872 max_data_bytes
, datasize
));
873 datasize
= data_to_send
= max_data_bytes
;
877 /* If there genuinely are no parameters or data to send just send the empty packet */
879 if(params_to_send
== 0 && data_to_send
== 0) {
880 reply_outbuf(req
, 10, 0);
881 if (NT_STATUS_V(status
)) {
884 ntstatus_to_dos(status
, &eclass
, &ecode
);
885 error_packet_set((char *)req
->outbuf
,
886 eclass
, ecode
, status
,
889 show_msg((char *)req
->outbuf
);
890 if (!srv_send_smb(sconn
,
893 IS_CONN_ENCRYPTED(conn
),
895 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
897 TALLOC_FREE(req
->outbuf
);
901 /* When sending params and data ensure that both are nicely aligned */
902 /* Only do this alignment when there is also data to send - else
903 can cause NT redirector problems. */
905 if (((params_to_send
% 4) != 0) && (data_to_send
!= 0))
906 data_alignment_offset
= 4 - (params_to_send
% 4);
908 /* Space is bufsize minus Netbios over TCP header minus SMB header */
909 /* The alignment_offset is to align the param bytes on an even byte
910 boundary. NT 4.0 Beta needs this to work correctly. */
912 useable_space
= max_send
- (smb_size
915 + data_alignment_offset
);
917 if (useable_space
< 0) {
918 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
919 "= %d!!!", useable_space
));
920 exit_server_cleanly("send_trans2_replies: Not enough space");
923 while (params_to_send
|| data_to_send
) {
924 /* Calculate whether we will totally or partially fill this packet */
926 total_sent_thistime
= params_to_send
+ data_to_send
;
928 /* We can never send more than useable_space */
930 * Note that 'useable_space' does not include the alignment offsets,
931 * but we must include the alignment offsets in the calculation of
932 * the length of the data we send over the wire, as the alignment offsets
933 * are sent here. Fix from Marc_Jacobsen@hp.com.
936 total_sent_thistime
= MIN(total_sent_thistime
, useable_space
);
938 reply_outbuf(req
, 10, total_sent_thistime
+ alignment_offset
939 + data_alignment_offset
);
941 /* Set total params and data to be sent */
942 SSVAL(req
->outbuf
,smb_tprcnt
,paramsize
);
943 SSVAL(req
->outbuf
,smb_tdrcnt
,datasize
);
945 /* Calculate how many parameters and data we can fit into
946 * this packet. Parameters get precedence
949 params_sent_thistime
= MIN(params_to_send
,useable_space
);
950 data_sent_thistime
= useable_space
- params_sent_thistime
;
951 data_sent_thistime
= MIN(data_sent_thistime
,data_to_send
);
953 SSVAL(req
->outbuf
,smb_prcnt
, params_sent_thistime
);
955 /* smb_proff is the offset from the start of the SMB header to the
956 parameter bytes, however the first 4 bytes of outbuf are
957 the Netbios over TCP header. Thus use smb_base() to subtract
958 them from the calculation */
960 SSVAL(req
->outbuf
,smb_proff
,
961 ((smb_buf(req
->outbuf
)+alignment_offset
)
962 - smb_base(req
->outbuf
)));
964 if(params_sent_thistime
== 0)
965 SSVAL(req
->outbuf
,smb_prdisp
,0);
967 /* Absolute displacement of param bytes sent in this packet */
968 SSVAL(req
->outbuf
,smb_prdisp
,pp
- params
);
970 SSVAL(req
->outbuf
,smb_drcnt
, data_sent_thistime
);
971 if(data_sent_thistime
== 0) {
972 SSVAL(req
->outbuf
,smb_droff
,0);
973 SSVAL(req
->outbuf
,smb_drdisp
, 0);
975 /* The offset of the data bytes is the offset of the
976 parameter bytes plus the number of parameters being sent this time */
977 SSVAL(req
->outbuf
, smb_droff
,
978 ((smb_buf(req
->outbuf
)+alignment_offset
)
979 - smb_base(req
->outbuf
))
980 + params_sent_thistime
+ data_alignment_offset
);
981 SSVAL(req
->outbuf
,smb_drdisp
, pd
- pdata
);
984 /* Initialize the padding for alignment */
986 if (alignment_offset
!= 0) {
987 memset(smb_buf(req
->outbuf
), 0, alignment_offset
);
990 /* Copy the param bytes into the packet */
992 if(params_sent_thistime
) {
993 memcpy((smb_buf(req
->outbuf
)+alignment_offset
), pp
,
994 params_sent_thistime
);
997 /* Copy in the data bytes */
998 if(data_sent_thistime
) {
999 if (data_alignment_offset
!= 0) {
1000 memset((smb_buf(req
->outbuf
)+alignment_offset
+
1001 params_sent_thistime
), 0,
1002 data_alignment_offset
);
1004 memcpy(smb_buf(req
->outbuf
)+alignment_offset
1005 +params_sent_thistime
+data_alignment_offset
,
1006 pd
,data_sent_thistime
);
1009 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
1010 params_sent_thistime
, data_sent_thistime
, useable_space
));
1011 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
1012 params_to_send
, data_to_send
, paramsize
, datasize
));
1015 error_packet_set((char *)req
->outbuf
,
1016 ERRDOS
,ERRbufferoverflow
,
1017 STATUS_BUFFER_OVERFLOW
,
1019 } else if (NT_STATUS_V(status
)) {
1022 ntstatus_to_dos(status
, &eclass
, &ecode
);
1023 error_packet_set((char *)req
->outbuf
,
1024 eclass
, ecode
, status
,
1028 /* Send the packet */
1029 show_msg((char *)req
->outbuf
);
1030 if (!srv_send_smb(sconn
,
1031 (char *)req
->outbuf
,
1032 true, req
->seqnum
+1,
1033 IS_CONN_ENCRYPTED(conn
),
1035 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
1037 TALLOC_FREE(req
->outbuf
);
1039 pp
+= params_sent_thistime
;
1040 pd
+= data_sent_thistime
;
1042 params_to_send
-= params_sent_thistime
;
1043 data_to_send
-= data_sent_thistime
;
1046 if(params_to_send
< 0 || data_to_send
< 0) {
1047 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
1048 params_to_send
, data_to_send
));
1056 /****************************************************************************
1057 Reply to a TRANSACT2_OPEN.
1058 ****************************************************************************/
1060 static void call_trans2open(connection_struct
*conn
,
1061 struct smb_request
*req
,
1062 char **pparams
, int total_params
,
1063 char **ppdata
, int total_data
,
1064 unsigned int max_data_bytes
)
1066 struct smb_filename
*smb_fname
= NULL
;
1067 char *params
= *pparams
;
1068 char *pdata
= *ppdata
;
1071 bool oplock_request
;
1073 bool return_additional_info
;
1082 int fattr
=0,mtime
=0;
1083 SMB_INO_T inode
= 0;
1086 struct ea_list
*ea_list
= NULL
;
1091 uint32 create_disposition
;
1092 uint32 create_options
= 0;
1093 uint32_t private_flags
= 0;
1094 TALLOC_CTX
*ctx
= talloc_tos();
1097 * Ensure we have enough parameters to perform the operation.
1100 if (total_params
< 29) {
1101 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1105 flags
= SVAL(params
, 0);
1106 deny_mode
= SVAL(params
, 2);
1107 open_attr
= SVAL(params
,6);
1108 oplock_request
= (flags
& REQUEST_OPLOCK
) ? EXCLUSIVE_OPLOCK
: 0;
1109 if (oplock_request
) {
1110 oplock_request
|= (flags
& REQUEST_BATCH_OPLOCK
) ? BATCH_OPLOCK
: 0;
1114 return_additional_info
= BITSETW(params
,0);
1115 open_sattr
= SVAL(params
, 4);
1116 open_time
= make_unix_date3(params
+8);
1118 open_ofun
= SVAL(params
,12);
1119 open_size
= IVAL(params
,14);
1120 pname
= ¶ms
[28];
1123 reply_nterror(req
, NT_STATUS_NETWORK_ACCESS_DENIED
);
1127 srvstr_get_path(ctx
, params
, req
->flags2
, &fname
, pname
,
1128 total_params
- 28, STR_TERMINATE
,
1130 if (!NT_STATUS_IS_OK(status
)) {
1131 reply_nterror(req
, status
);
1135 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
1136 fname
, (unsigned int)deny_mode
, (unsigned int)open_attr
,
1137 (unsigned int)open_ofun
, open_size
));
1139 status
= filename_convert(ctx
,
1141 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
1146 if (!NT_STATUS_IS_OK(status
)) {
1147 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
1148 reply_botherror(req
,
1149 NT_STATUS_PATH_NOT_COVERED
,
1150 ERRSRV
, ERRbadpath
);
1153 reply_nterror(req
, status
);
1157 if (open_ofun
== 0) {
1158 reply_nterror(req
, NT_STATUS_OBJECT_NAME_COLLISION
);
1162 if (!map_open_params_to_ntcreate(smb_fname
->base_name
, deny_mode
,
1164 &access_mask
, &share_mode
,
1165 &create_disposition
,
1168 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
1172 /* Any data in this call is an EA list. */
1173 if (total_data
&& (total_data
!= 4)) {
1174 if (total_data
< 10) {
1175 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1179 if (IVAL(pdata
,0) > total_data
) {
1180 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
1181 IVAL(pdata
,0), (unsigned int)total_data
));
1182 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1186 ea_list
= read_ea_list(talloc_tos(), pdata
+ 4,
1189 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1193 if (!lp_ea_support(SNUM(conn
))) {
1194 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
1198 if (ea_list_has_invalid_name(ea_list
)) {
1200 *pparams
= (char *)SMB_REALLOC(*pparams
, param_len
);
1201 if(*pparams
== NULL
) {
1202 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1206 memset(params
, '\0', param_len
);
1207 send_trans2_replies(conn
, req
, STATUS_INVALID_EA_NAME
,
1208 params
, param_len
, NULL
, 0, max_data_bytes
);
1213 status
= SMB_VFS_CREATE_FILE(
1216 0, /* root_dir_fid */
1217 smb_fname
, /* fname */
1218 access_mask
, /* access_mask */
1219 share_mode
, /* share_access */
1220 create_disposition
, /* create_disposition*/
1221 create_options
, /* create_options */
1222 open_attr
, /* file_attributes */
1223 oplock_request
, /* oplock_request */
1224 open_size
, /* allocation_size */
1227 ea_list
, /* ea_list */
1229 &smb_action
); /* psbuf */
1231 if (!NT_STATUS_IS_OK(status
)) {
1232 if (open_was_deferred(req
->sconn
, req
->mid
)) {
1233 /* We have re-scheduled this call. */
1236 reply_openerror(req
, status
);
1240 size
= get_file_size_stat(&smb_fname
->st
);
1241 fattr
= dos_mode(conn
, smb_fname
);
1242 mtime
= convert_timespec_to_time_t(smb_fname
->st
.st_ex_mtime
);
1243 inode
= smb_fname
->st
.st_ex_ino
;
1244 if (fattr
& FILE_ATTRIBUTE_DIRECTORY
) {
1245 close_file(req
, fsp
, ERROR_CLOSE
);
1246 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
1250 /* Realloc the size of parameters and data we will return */
1251 *pparams
= (char *)SMB_REALLOC(*pparams
, 30);
1252 if(*pparams
== NULL
) {
1253 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1258 SSVAL(params
,0,fsp
->fnum
);
1259 SSVAL(params
,2,fattr
);
1260 srv_put_dos_date2(params
,4, mtime
);
1261 SIVAL(params
,8, (uint32
)size
);
1262 SSVAL(params
,12,deny_mode
);
1263 SSVAL(params
,14,0); /* open_type - file or directory. */
1264 SSVAL(params
,16,0); /* open_state - only valid for IPC device. */
1266 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
1267 smb_action
|= EXTENDED_OPLOCK_GRANTED
;
1270 SSVAL(params
,18,smb_action
);
1273 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1275 SIVAL(params
,20,inode
);
1276 SSVAL(params
,24,0); /* Padding. */
1278 uint32 ea_size
= estimate_ea_size(conn
, fsp
,
1280 SIVAL(params
, 26, ea_size
);
1282 SIVAL(params
, 26, 0);
1285 /* Send the required number of replies */
1286 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 30, *ppdata
, 0, max_data_bytes
);
1288 TALLOC_FREE(smb_fname
);
1291 /*********************************************************
1292 Routine to check if a given string matches exactly.
1293 as a special case a mask of "." does NOT match. That
1294 is required for correct wildcard semantics
1295 Case can be significant or not.
1296 **********************************************************/
1298 static bool exact_match(bool has_wild
,
1299 bool case_sensitive
,
1303 if (mask
[0] == '.' && mask
[1] == 0) {
1311 if (case_sensitive
) {
1312 return strcmp(str
,mask
)==0;
1314 return strcasecmp_m(str
,mask
) == 0;
1318 /****************************************************************************
1319 Return the filetype for UNIX extensions.
1320 ****************************************************************************/
1322 static uint32
unix_filetype(mode_t mode
)
1325 return UNIX_TYPE_FILE
;
1326 else if(S_ISDIR(mode
))
1327 return UNIX_TYPE_DIR
;
1329 else if(S_ISLNK(mode
))
1330 return UNIX_TYPE_SYMLINK
;
1333 else if(S_ISCHR(mode
))
1334 return UNIX_TYPE_CHARDEV
;
1337 else if(S_ISBLK(mode
))
1338 return UNIX_TYPE_BLKDEV
;
1341 else if(S_ISFIFO(mode
))
1342 return UNIX_TYPE_FIFO
;
1345 else if(S_ISSOCK(mode
))
1346 return UNIX_TYPE_SOCKET
;
1349 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode
));
1350 return UNIX_TYPE_UNKNOWN
;
1353 /****************************************************************************
1354 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1355 ****************************************************************************/
1357 enum perm_type
{ PERM_NEW_FILE
, PERM_NEW_DIR
, PERM_EXISTING_FILE
, PERM_EXISTING_DIR
};
1359 static NTSTATUS
unix_perms_from_wire( connection_struct
*conn
,
1360 const SMB_STRUCT_STAT
*psbuf
,
1362 enum perm_type ptype
,
1367 if (perms
== SMB_MODE_NO_CHANGE
) {
1368 if (!VALID_STAT(*psbuf
)) {
1369 return NT_STATUS_INVALID_PARAMETER
;
1371 *ret_perms
= psbuf
->st_ex_mode
;
1372 return NT_STATUS_OK
;
1376 ret
|= ((perms
& UNIX_X_OTH
) ? S_IXOTH
: 0);
1377 ret
|= ((perms
& UNIX_W_OTH
) ? S_IWOTH
: 0);
1378 ret
|= ((perms
& UNIX_R_OTH
) ? S_IROTH
: 0);
1379 ret
|= ((perms
& UNIX_X_GRP
) ? S_IXGRP
: 0);
1380 ret
|= ((perms
& UNIX_W_GRP
) ? S_IWGRP
: 0);
1381 ret
|= ((perms
& UNIX_R_GRP
) ? S_IRGRP
: 0);
1382 ret
|= ((perms
& UNIX_X_USR
) ? S_IXUSR
: 0);
1383 ret
|= ((perms
& UNIX_W_USR
) ? S_IWUSR
: 0);
1384 ret
|= ((perms
& UNIX_R_USR
) ? S_IRUSR
: 0);
1386 ret
|= ((perms
& UNIX_STICKY
) ? S_ISVTX
: 0);
1389 ret
|= ((perms
& UNIX_SET_GID
) ? S_ISGID
: 0);
1392 ret
|= ((perms
& UNIX_SET_UID
) ? S_ISUID
: 0);
1395 if (ptype
== PERM_NEW_FILE
) {
1397 * "create mask"/"force create mode" are
1398 * only applied to new files, not existing ones.
1400 ret
&= lp_create_mask(SNUM(conn
));
1401 /* Add in force bits */
1402 ret
|= lp_force_create_mode(SNUM(conn
));
1403 } else if (ptype
== PERM_NEW_DIR
) {
1405 * "directory mask"/"force directory mode" are
1406 * only applied to new directories, not existing ones.
1408 ret
&= lp_dir_mask(SNUM(conn
));
1409 /* Add in force bits */
1410 ret
|= lp_force_dir_mode(SNUM(conn
));
1414 return NT_STATUS_OK
;
1417 /****************************************************************************
1418 Needed to show the msdfs symlinks as directories. Modifies psbuf
1419 to be a directory if it's a msdfs link.
1420 ****************************************************************************/
1422 static bool check_msdfs_link(connection_struct
*conn
,
1423 const char *pathname
,
1424 SMB_STRUCT_STAT
*psbuf
)
1426 int saved_errno
= errno
;
1427 if(lp_host_msdfs() &&
1428 lp_msdfs_root(SNUM(conn
)) &&
1429 is_msdfs_link(conn
, pathname
, psbuf
)) {
1431 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1434 psbuf
->st_ex_mode
= (psbuf
->st_ex_mode
& 0xFFF) | S_IFDIR
;
1435 errno
= saved_errno
;
1438 errno
= saved_errno
;
1443 /****************************************************************************
1444 Get a level dependent lanman2 dir entry.
1445 ****************************************************************************/
1447 struct smbd_dirptr_lanman2_state
{
1448 connection_struct
*conn
;
1449 uint32_t info_level
;
1450 bool check_mangled_names
;
1452 bool got_exact_match
;
1455 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX
*ctx
,
1461 struct smbd_dirptr_lanman2_state
*state
=
1462 (struct smbd_dirptr_lanman2_state
*)private_data
;
1464 char mangled_name
[13]; /* mangled 8.3 name. */
1468 /* Mangle fname if it's an illegal name. */
1469 if (mangle_must_mangle(dname
, state
->conn
->params
)) {
1470 ok
= name_to_8_3(dname
, mangled_name
,
1471 true, state
->conn
->params
);
1475 fname
= mangled_name
;
1480 got_match
= exact_match(state
->has_wild
,
1481 state
->conn
->case_sensitive
,
1483 state
->got_exact_match
= got_match
;
1485 got_match
= mask_match(fname
, mask
,
1486 state
->conn
->case_sensitive
);
1489 if(!got_match
&& state
->check_mangled_names
&&
1490 !mangle_is_8_3(fname
, false, state
->conn
->params
)) {
1492 * It turns out that NT matches wildcards against
1493 * both long *and* short names. This may explain some
1494 * of the wildcard wierdness from old DOS clients
1495 * that some people have been seeing.... JRA.
1497 /* Force the mangling into 8.3. */
1498 ok
= name_to_8_3(fname
, mangled_name
,
1499 false, state
->conn
->params
);
1504 got_match
= exact_match(state
->has_wild
,
1505 state
->conn
->case_sensitive
,
1506 mangled_name
, mask
);
1507 state
->got_exact_match
= got_match
;
1509 got_match
= mask_match(mangled_name
, mask
,
1510 state
->conn
->case_sensitive
);
1518 *_fname
= talloc_strdup(ctx
, fname
);
1519 if (*_fname
== NULL
) {
1526 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX
*ctx
,
1528 struct smb_filename
*smb_fname
,
1531 struct smbd_dirptr_lanman2_state
*state
=
1532 (struct smbd_dirptr_lanman2_state
*)private_data
;
1533 bool ms_dfs_link
= false;
1536 if (INFO_LEVEL_IS_UNIX(state
->info_level
)) {
1537 if (SMB_VFS_LSTAT(state
->conn
, smb_fname
) != 0) {
1538 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1539 "Couldn't lstat [%s] (%s)\n",
1540 smb_fname_str_dbg(smb_fname
),
1544 } else if (!VALID_STAT(smb_fname
->st
) &&
1545 SMB_VFS_STAT(state
->conn
, smb_fname
) != 0) {
1546 /* Needed to show the msdfs symlinks as
1549 ms_dfs_link
= check_msdfs_link(state
->conn
,
1550 smb_fname
->base_name
,
1553 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1554 "Couldn't stat [%s] (%s)\n",
1555 smb_fname_str_dbg(smb_fname
),
1562 mode
= dos_mode_msdfs(state
->conn
, smb_fname
);
1564 mode
= dos_mode(state
->conn
, smb_fname
);
1571 static bool smbd_marshall_dir_entry(TALLOC_CTX
*ctx
,
1572 connection_struct
*conn
,
1574 uint32_t info_level
,
1575 struct ea_list
*name_list
,
1576 bool check_mangled_names
,
1577 bool requires_resume_key
,
1580 const struct smb_filename
*smb_fname
,
1581 int space_remaining
,
1588 uint64_t *last_entry_off
)
1590 char *p
, *q
, *pdata
= *ppdata
;
1592 uint64_t file_size
= 0;
1593 uint64_t allocation_size
= 0;
1594 uint64_t file_index
= 0;
1596 struct timespec mdate_ts
, adate_ts
, cdate_ts
, create_date_ts
;
1597 time_t mdate
= (time_t)0, adate
= (time_t)0, create_date
= (time_t)0;
1599 char *last_entry_ptr
;
1604 *out_of_space
= false;
1606 ZERO_STRUCT(mdate_ts
);
1607 ZERO_STRUCT(adate_ts
);
1608 ZERO_STRUCT(create_date_ts
);
1609 ZERO_STRUCT(cdate_ts
);
1611 if (!(mode
& FILE_ATTRIBUTE_DIRECTORY
)) {
1612 file_size
= get_file_size_stat(&smb_fname
->st
);
1614 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
, NULL
, &smb_fname
->st
);
1616 file_index
= get_FileIndex(conn
, &smb_fname
->st
);
1618 mdate_ts
= smb_fname
->st
.st_ex_mtime
;
1619 adate_ts
= smb_fname
->st
.st_ex_atime
;
1620 create_date_ts
= get_create_timespec(conn
, NULL
, smb_fname
);
1621 cdate_ts
= get_change_timespec(conn
, NULL
, smb_fname
);
1623 if (lp_dos_filetime_resolution(SNUM(conn
))) {
1624 dos_filetime_timespec(&create_date_ts
);
1625 dos_filetime_timespec(&mdate_ts
);
1626 dos_filetime_timespec(&adate_ts
);
1627 dos_filetime_timespec(&cdate_ts
);
1630 create_date
= convert_timespec_to_time_t(create_date_ts
);
1631 mdate
= convert_timespec_to_time_t(mdate_ts
);
1632 adate
= convert_timespec_to_time_t(adate_ts
);
1634 /* align the record */
1635 SMB_ASSERT(align
>= 1);
1637 off
= (int)PTR_DIFF(pdata
, base_data
);
1638 pad
= (off
+ (align
-1)) & ~(align
-1);
1641 if (pad
&& pad
> space_remaining
) {
1642 *out_of_space
= true;
1643 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1644 "for padding (wanted %u, had %d)\n",
1647 return false; /* Not finished - just out of space */
1651 /* initialize padding to 0 */
1653 memset(pdata
, 0, pad
);
1655 space_remaining
-= pad
;
1657 DEBUG(10,("smbd_marshall_dir_entry: space_remaining = %d\n",
1667 switch (info_level
) {
1668 case SMB_FIND_INFO_STANDARD
:
1669 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1670 if(requires_resume_key
) {
1674 srv_put_dos_date2(p
,0,create_date
);
1675 srv_put_dos_date2(p
,4,adate
);
1676 srv_put_dos_date2(p
,8,mdate
);
1677 SIVAL(p
,12,(uint32
)file_size
);
1678 SIVAL(p
,16,(uint32
)allocation_size
);
1682 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1683 p
+= ucs2_align(base_data
, p
, 0);
1685 len
= srvstr_push(base_data
, flags2
, p
,
1686 fname
, PTR_DIFF(end_data
, p
),
1688 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1690 SCVAL(nameptr
, -1, len
- 2);
1692 SCVAL(nameptr
, -1, 0);
1696 SCVAL(nameptr
, -1, len
- 1);
1698 SCVAL(nameptr
, -1, 0);
1704 case SMB_FIND_EA_SIZE
:
1705 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
1706 if (requires_resume_key
) {
1710 srv_put_dos_date2(p
,0,create_date
);
1711 srv_put_dos_date2(p
,4,adate
);
1712 srv_put_dos_date2(p
,8,mdate
);
1713 SIVAL(p
,12,(uint32
)file_size
);
1714 SIVAL(p
,16,(uint32
)allocation_size
);
1717 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
1719 SIVAL(p
,22,ea_size
); /* Extended attributes */
1723 len
= srvstr_push(base_data
, flags2
,
1724 p
, fname
, PTR_DIFF(end_data
, p
),
1725 STR_TERMINATE
| STR_NOALIGN
);
1726 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1739 SCVAL(nameptr
,0,len
);
1741 SCVAL(p
,0,0); p
+= 1; /* Extra zero byte ? - why.. */
1744 case SMB_FIND_EA_LIST
:
1746 struct ea_list
*file_list
= NULL
;
1750 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
1754 if (requires_resume_key
) {
1758 srv_put_dos_date2(p
,0,create_date
);
1759 srv_put_dos_date2(p
,4,adate
);
1760 srv_put_dos_date2(p
,8,mdate
);
1761 SIVAL(p
,12,(uint32
)file_size
);
1762 SIVAL(p
,16,(uint32
)allocation_size
);
1764 p
+= 22; /* p now points to the EA area. */
1766 status
= get_ea_list_from_file(ctx
, conn
, NULL
,
1768 &ea_len
, &file_list
);
1769 if (!NT_STATUS_IS_OK(status
)) {
1772 name_list
= ea_list_union(name_list
, file_list
, &ea_len
);
1774 /* We need to determine if this entry will fit in the space available. */
1775 /* Max string size is 255 bytes. */
1776 if (PTR_DIFF(p
+ 255 + ea_len
,pdata
) > space_remaining
) {
1777 *out_of_space
= true;
1778 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1779 "(wanted %u, had %d)\n",
1780 (unsigned int)PTR_DIFF(p
+ 255 + ea_len
,pdata
),
1782 return False
; /* Not finished - just out of space */
1785 /* Push the ea_data followed by the name. */
1786 p
+= fill_ea_buffer(ctx
, p
, space_remaining
, conn
, name_list
);
1788 len
= srvstr_push(base_data
, flags2
,
1789 p
+ 1, fname
, PTR_DIFF(end_data
, p
+1),
1790 STR_TERMINATE
| STR_NOALIGN
);
1791 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1804 SCVAL(nameptr
,0,len
);
1806 SCVAL(p
,0,0); p
+= 1; /* Extra zero byte ? - why.. */
1810 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
1811 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1812 was_8_3
= mangle_is_8_3(fname
, True
, conn
->params
);
1814 SIVAL(p
,0,reskey
); p
+= 4;
1815 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
1816 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
1817 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
1818 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
1819 SOFF_T(p
,0,file_size
); p
+= 8;
1820 SOFF_T(p
,0,allocation_size
); p
+= 8;
1821 SIVAL(p
,0,mode
); p
+= 4;
1822 q
= p
; p
+= 4; /* q is placeholder for name length. */
1823 if (mode
& FILE_ATTRIBUTE_REPARSE_POINT
) {
1824 SIVAL(p
, 0, IO_REPARSE_TAG_DFS
);
1826 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
1828 SIVAL(p
,0,ea_size
); /* Extended attributes */
1831 /* Clear the short name buffer. This is
1832 * IMPORTANT as not doing so will trigger
1833 * a Win2k client bug. JRA.
1835 if (!was_8_3
&& check_mangled_names
) {
1836 char mangled_name
[13]; /* mangled 8.3 name. */
1837 if (!name_to_8_3(fname
,mangled_name
,True
,
1839 /* Error - mangle failed ! */
1840 memset(mangled_name
,'\0',12);
1842 mangled_name
[12] = 0;
1843 len
= srvstr_push(base_data
, flags2
,
1844 p
+2, mangled_name
, 24,
1845 STR_UPPER
|STR_UNICODE
);
1847 memset(p
+ 2 + len
,'\0',24 - len
);
1854 len
= srvstr_push(base_data
, flags2
, p
,
1855 fname
, PTR_DIFF(end_data
, p
),
1856 STR_TERMINATE_ASCII
);
1860 len
= PTR_DIFF(p
, pdata
);
1861 pad
= (len
+ (align
-1)) & ~(align
-1);
1863 * offset to the next entry, the caller
1864 * will overwrite it for the last entry
1865 * that's why we always include the padding
1869 * set padding to zero
1872 memset(p
, 0, pad
- len
);
1879 case SMB_FIND_FILE_DIRECTORY_INFO
:
1880 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1882 SIVAL(p
,0,reskey
); p
+= 4;
1883 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
1884 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
1885 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
1886 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
1887 SOFF_T(p
,0,file_size
); p
+= 8;
1888 SOFF_T(p
,0,allocation_size
); p
+= 8;
1889 SIVAL(p
,0,mode
); p
+= 4;
1890 len
= srvstr_push(base_data
, flags2
,
1891 p
+ 4, fname
, PTR_DIFF(end_data
, p
+4),
1892 STR_TERMINATE_ASCII
);
1896 len
= PTR_DIFF(p
, pdata
);
1897 pad
= (len
+ (align
-1)) & ~(align
-1);
1899 * offset to the next entry, the caller
1900 * will overwrite it for the last entry
1901 * that's why we always include the padding
1905 * set padding to zero
1908 memset(p
, 0, pad
- len
);
1915 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
1916 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1918 SIVAL(p
,0,reskey
); p
+= 4;
1919 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
1920 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
1921 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
1922 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
1923 SOFF_T(p
,0,file_size
); p
+= 8;
1924 SOFF_T(p
,0,allocation_size
); p
+= 8;
1925 SIVAL(p
,0,mode
); p
+= 4;
1926 q
= p
; p
+= 4; /* q is placeholder for name length. */
1928 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
1930 SIVAL(p
,0,ea_size
); /* Extended attributes */
1933 len
= srvstr_push(base_data
, flags2
, p
,
1934 fname
, PTR_DIFF(end_data
, p
),
1935 STR_TERMINATE_ASCII
);
1939 len
= PTR_DIFF(p
, pdata
);
1940 pad
= (len
+ (align
-1)) & ~(align
-1);
1942 * offset to the next entry, the caller
1943 * will overwrite it for the last entry
1944 * that's why we always include the padding
1948 * set padding to zero
1951 memset(p
, 0, pad
- len
);
1958 case SMB_FIND_FILE_NAMES_INFO
:
1959 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1961 SIVAL(p
,0,reskey
); p
+= 4;
1963 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1964 acl on a dir (tridge) */
1965 len
= srvstr_push(base_data
, flags2
, p
,
1966 fname
, PTR_DIFF(end_data
, p
),
1967 STR_TERMINATE_ASCII
);
1971 len
= PTR_DIFF(p
, pdata
);
1972 pad
= (len
+ (align
-1)) & ~(align
-1);
1974 * offset to the next entry, the caller
1975 * will overwrite it for the last entry
1976 * that's why we always include the padding
1980 * set padding to zero
1983 memset(p
, 0, pad
- len
);
1990 case SMB_FIND_ID_FULL_DIRECTORY_INFO
:
1991 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1993 SIVAL(p
,0,reskey
); p
+= 4;
1994 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
1995 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
1996 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
1997 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
1998 SOFF_T(p
,0,file_size
); p
+= 8;
1999 SOFF_T(p
,0,allocation_size
); p
+= 8;
2000 SIVAL(p
,0,mode
); p
+= 4;
2001 q
= p
; p
+= 4; /* q is placeholder for name length. */
2002 if (mode
& FILE_ATTRIBUTE_REPARSE_POINT
) {
2003 SIVAL(p
, 0, IO_REPARSE_TAG_DFS
);
2005 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
2007 SIVAL(p
,0,ea_size
); /* Extended attributes */
2010 SIVAL(p
,0,0); p
+= 4; /* Unknown - reserved ? */
2011 SBVAL(p
,0,file_index
); p
+= 8;
2012 len
= srvstr_push(base_data
, flags2
, p
,
2013 fname
, PTR_DIFF(end_data
, p
),
2014 STR_TERMINATE_ASCII
);
2018 len
= PTR_DIFF(p
, pdata
);
2019 pad
= (len
+ (align
-1)) & ~(align
-1);
2021 * offset to the next entry, the caller
2022 * will overwrite it for the last entry
2023 * that's why we always include the padding
2027 * set padding to zero
2030 memset(p
, 0, pad
- len
);
2037 case SMB_FIND_ID_BOTH_DIRECTORY_INFO
:
2038 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
2039 was_8_3
= mangle_is_8_3(fname
, True
, conn
->params
);
2041 SIVAL(p
,0,reskey
); p
+= 4;
2042 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
2043 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
2044 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
2045 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
2046 SOFF_T(p
,0,file_size
); p
+= 8;
2047 SOFF_T(p
,0,allocation_size
); p
+= 8;
2048 SIVAL(p
,0,mode
); p
+= 4;
2049 q
= p
; p
+= 4; /* q is placeholder for name length */
2050 if (mode
& FILE_ATTRIBUTE_REPARSE_POINT
) {
2051 SIVAL(p
, 0, IO_REPARSE_TAG_DFS
);
2053 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
2055 SIVAL(p
,0,ea_size
); /* Extended attributes */
2058 /* Clear the short name buffer. This is
2059 * IMPORTANT as not doing so will trigger
2060 * a Win2k client bug. JRA.
2062 if (!was_8_3
&& check_mangled_names
) {
2063 char mangled_name
[13]; /* mangled 8.3 name. */
2064 if (!name_to_8_3(fname
,mangled_name
,True
,
2066 /* Error - mangle failed ! */
2067 memset(mangled_name
,'\0',12);
2069 mangled_name
[12] = 0;
2070 len
= srvstr_push(base_data
, flags2
,
2071 p
+2, mangled_name
, 24,
2072 STR_UPPER
|STR_UNICODE
);
2075 memset(p
+ 2 + len
,'\0',24 - len
);
2082 SSVAL(p
,0,0); p
+= 2; /* Reserved ? */
2083 SBVAL(p
,0,file_index
); p
+= 8;
2084 len
= srvstr_push(base_data
, flags2
, p
,
2085 fname
, PTR_DIFF(end_data
, p
),
2086 STR_TERMINATE_ASCII
);
2090 len
= PTR_DIFF(p
, pdata
);
2091 pad
= (len
+ (align
-1)) & ~(align
-1);
2093 * offset to the next entry, the caller
2094 * will overwrite it for the last entry
2095 * that's why we always include the padding
2099 * set padding to zero
2102 memset(p
, 0, pad
- len
);
2109 /* CIFS UNIX Extension. */
2111 case SMB_FIND_FILE_UNIX
:
2112 case SMB_FIND_FILE_UNIX_INFO2
:
2114 SIVAL(p
,0,reskey
); p
+= 4; /* Used for continuing search. */
2116 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
2118 if (info_level
== SMB_FIND_FILE_UNIX
) {
2119 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
2120 p
= store_file_unix_basic(conn
, p
,
2121 NULL
, &smb_fname
->st
);
2122 len
= srvstr_push(base_data
, flags2
, p
,
2123 fname
, PTR_DIFF(end_data
, p
),
2126 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
2127 p
= store_file_unix_basic_info2(conn
, p
,
2128 NULL
, &smb_fname
->st
);
2131 len
= srvstr_push(base_data
, flags2
, p
, fname
,
2132 PTR_DIFF(end_data
, p
), 0);
2133 SIVAL(nameptr
, 0, len
);
2138 len
= PTR_DIFF(p
, pdata
);
2139 pad
= (len
+ (align
-1)) & ~(align
-1);
2141 * offset to the next entry, the caller
2142 * will overwrite it for the last entry
2143 * that's why we always include the padding
2147 * set padding to zero
2150 memset(p
, 0, pad
- len
);
2155 /* End of SMB_QUERY_FILE_UNIX_BASIC */
2163 if (PTR_DIFF(p
,pdata
) > space_remaining
) {
2164 *out_of_space
= true;
2165 DEBUG(9,("smbd_marshall_dir_entry: out of space "
2166 "(wanted %u, had %d)\n",
2167 (unsigned int)PTR_DIFF(p
,pdata
),
2169 return false; /* Not finished - just out of space */
2172 /* Setup the last entry pointer, as an offset from base_data */
2173 *last_entry_off
= PTR_DIFF(last_entry_ptr
,base_data
);
2174 /* Advance the data pointer to the next slot */
2180 bool smbd_dirptr_lanman2_entry(TALLOC_CTX
*ctx
,
2181 connection_struct
*conn
,
2182 struct dptr_struct
*dirptr
,
2184 const char *path_mask
,
2187 int requires_resume_key
,
2195 int space_remaining
,
2197 bool *got_exact_match
,
2198 int *_last_entry_off
,
2199 struct ea_list
*name_list
)
2202 const char *mask
= NULL
;
2203 long prev_dirpos
= 0;
2206 struct smb_filename
*smb_fname
= NULL
;
2207 struct smbd_dirptr_lanman2_state state
;
2209 uint64_t last_entry_off
= 0;
2213 state
.info_level
= info_level
;
2214 state
.check_mangled_names
= lp_manglednames(conn
->params
);
2215 state
.has_wild
= dptr_has_wild(dirptr
);
2216 state
.got_exact_match
= false;
2218 *out_of_space
= false;
2219 *got_exact_match
= false;
2221 p
= strrchr_m(path_mask
,'/');
2232 ok
= smbd_dirptr_get_entry(ctx
,
2238 smbd_dirptr_lanman2_match_fn
,
2239 smbd_dirptr_lanman2_mode_fn
,
2249 *got_exact_match
= state
.got_exact_match
;
2251 ok
= smbd_marshall_dir_entry(ctx
,
2256 state
.check_mangled_names
,
2257 requires_resume_key
,
2270 TALLOC_FREE(smb_fname
);
2271 if (*out_of_space
) {
2272 dptr_SeekDir(dirptr
, prev_dirpos
);
2279 *_last_entry_off
= last_entry_off
;
2283 static bool get_lanman2_dir_entry(TALLOC_CTX
*ctx
,
2284 connection_struct
*conn
,
2285 struct dptr_struct
*dirptr
,
2287 const char *path_mask
,
2290 bool requires_resume_key
,
2296 int space_remaining
,
2298 bool *got_exact_match
,
2299 int *last_entry_off
,
2300 struct ea_list
*name_list
)
2303 const bool do_pad
= true;
2305 if (info_level
>= 1 && info_level
<= 3) {
2306 /* No alignment on earlier info levels. */
2310 return smbd_dirptr_lanman2_entry(ctx
, conn
, dirptr
, flags2
,
2311 path_mask
, dirtype
, info_level
,
2312 requires_resume_key
, dont_descend
, ask_sharemode
,
2314 ppdata
, base_data
, end_data
,
2316 out_of_space
, got_exact_match
,
2317 last_entry_off
, name_list
);
2320 /****************************************************************************
2321 Reply to a TRANS2_FINDFIRST.
2322 ****************************************************************************/
2324 static void call_trans2findfirst(connection_struct
*conn
,
2325 struct smb_request
*req
,
2326 char **pparams
, int total_params
,
2327 char **ppdata
, int total_data
,
2328 unsigned int max_data_bytes
)
2330 /* We must be careful here that we don't return more than the
2331 allowed number of data bytes. If this means returning fewer than
2332 maxentries then so be it. We assume that the redirector has
2333 enough room for the fixed number of parameter bytes it has
2335 struct smb_filename
*smb_dname
= NULL
;
2336 char *params
= *pparams
;
2337 char *pdata
= *ppdata
;
2341 uint16 findfirst_flags
;
2342 bool close_after_first
;
2344 bool requires_resume_key
;
2346 char *directory
= NULL
;
2349 int last_entry_off
=0;
2353 bool finished
= False
;
2354 bool dont_descend
= False
;
2355 bool out_of_space
= False
;
2356 int space_remaining
;
2357 bool mask_contains_wcard
= False
;
2358 struct ea_list
*ea_list
= NULL
;
2359 NTSTATUS ntstatus
= NT_STATUS_OK
;
2360 bool ask_sharemode
= lp_parm_bool(SNUM(conn
), "smbd", "search ask sharemode", true);
2361 TALLOC_CTX
*ctx
= talloc_tos();
2362 struct dptr_struct
*dirptr
= NULL
;
2363 struct smbd_server_connection
*sconn
= req
->sconn
;
2364 uint32_t ucf_flags
= (UCF_SAVE_LCOMP
| UCF_ALWAYS_ALLOW_WCARD_LCOMP
);
2365 bool backup_priv
= false;
2367 if (total_params
< 13) {
2368 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2372 dirtype
= SVAL(params
,0);
2373 maxentries
= SVAL(params
,2);
2374 findfirst_flags
= SVAL(params
,4);
2375 close_after_first
= (findfirst_flags
& FLAG_TRANS2_FIND_CLOSE
);
2376 close_if_end
= (findfirst_flags
& FLAG_TRANS2_FIND_CLOSE_IF_END
);
2377 requires_resume_key
= (findfirst_flags
& FLAG_TRANS2_FIND_REQUIRE_RESUME
);
2378 backup_priv
= ((findfirst_flags
& FLAG_TRANS2_FIND_BACKUP_INTENT
) &&
2379 security_token_has_privilege(get_current_nttok(conn
),
2382 info_level
= SVAL(params
,6);
2384 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2385 close_if_end = %d requires_resume_key = %d backup_priv = %d level = 0x%x, max_data_bytes = %d\n",
2386 (unsigned int)dirtype
, maxentries
, close_after_first
, close_if_end
, requires_resume_key
,
2388 info_level
, max_data_bytes
));
2391 /* W2K3 seems to treat zero as 1. */
2395 switch (info_level
) {
2396 case SMB_FIND_INFO_STANDARD
:
2397 case SMB_FIND_EA_SIZE
:
2398 case SMB_FIND_EA_LIST
:
2399 case SMB_FIND_FILE_DIRECTORY_INFO
:
2400 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
2401 case SMB_FIND_FILE_NAMES_INFO
:
2402 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
2403 case SMB_FIND_ID_FULL_DIRECTORY_INFO
:
2404 case SMB_FIND_ID_BOTH_DIRECTORY_INFO
:
2406 case SMB_FIND_FILE_UNIX
:
2407 case SMB_FIND_FILE_UNIX_INFO2
:
2408 /* Always use filesystem for UNIX mtime query. */
2409 ask_sharemode
= false;
2410 if (!lp_unix_extensions()) {
2411 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2414 ucf_flags
|= UCF_UNIX_NAME_LOOKUP
;
2417 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2421 srvstr_get_path_wcard(ctx
, params
, req
->flags2
, &directory
,
2422 params
+12, total_params
- 12,
2423 STR_TERMINATE
, &ntstatus
, &mask_contains_wcard
);
2424 if (!NT_STATUS_IS_OK(ntstatus
)) {
2425 reply_nterror(req
, ntstatus
);
2431 ntstatus
= filename_convert_with_privilege(ctx
,
2436 &mask_contains_wcard
,
2439 ntstatus
= filename_convert(ctx
, conn
,
2440 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
2443 &mask_contains_wcard
,
2447 if (!NT_STATUS_IS_OK(ntstatus
)) {
2448 if (NT_STATUS_EQUAL(ntstatus
,NT_STATUS_PATH_NOT_COVERED
)) {
2449 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
2450 ERRSRV
, ERRbadpath
);
2453 reply_nterror(req
, ntstatus
);
2457 mask
= smb_dname
->original_lcomp
;
2459 directory
= smb_dname
->base_name
;
2461 p
= strrchr_m(directory
,'/');
2463 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2464 if((directory
[0] == '.') && (directory
[1] == '\0')) {
2465 mask
= talloc_strdup(ctx
,"*");
2467 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2470 mask_contains_wcard
= True
;
2476 if (p
== NULL
|| p
== directory
) {
2477 /* Ensure we don't have a directory name of "". */
2478 directory
= talloc_strdup(talloc_tos(), ".");
2480 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2485 DEBUG(5,("dir=%s, mask = %s\n",directory
, mask
));
2487 if (info_level
== SMB_FIND_EA_LIST
) {
2490 if (total_data
< 4) {
2491 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2495 ea_size
= IVAL(pdata
,0);
2496 if (ea_size
!= total_data
) {
2497 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2498 total_data=%u (should be %u)\n", (unsigned int)total_data
, (unsigned int)IVAL(pdata
,0) ));
2499 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2503 if (!lp_ea_support(SNUM(conn
))) {
2504 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
2508 /* Pull out the list of names. */
2509 ea_list
= read_ea_name_list(ctx
, pdata
+ 4, ea_size
- 4);
2511 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2516 *ppdata
= (char *)SMB_REALLOC(
2517 *ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
2518 if(*ppdata
== NULL
) {
2519 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2523 data_end
= pdata
+ max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
- 1;
2525 /* Realloc the params space */
2526 *pparams
= (char *)SMB_REALLOC(*pparams
, 10);
2527 if (*pparams
== NULL
) {
2528 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2533 /* Save the wildcard match and attribs we are using on this directory -
2534 needed as lanman2 assumes these are being saved between calls */
2536 ntstatus
= dptr_create(conn
,
2544 mask_contains_wcard
,
2548 if (!NT_STATUS_IS_OK(ntstatus
)) {
2549 reply_nterror(req
, ntstatus
);
2554 /* Remember this in case we have
2555 to do a findnext. */
2556 dptr_set_priv(dirptr
);
2559 dptr_num
= dptr_dnum(dirptr
);
2560 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num
, mask
, dirtype
));
2562 /* Initialize per TRANS2_FIND_FIRST operation data */
2563 dptr_init_search_op(dirptr
);
2565 /* We don't need to check for VOL here as this is returned by
2566 a different TRANS2 call. */
2568 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2569 directory
,lp_dontdescend(ctx
, SNUM(conn
))));
2570 if (in_list(directory
,lp_dontdescend(ctx
, SNUM(conn
)),conn
->case_sensitive
))
2571 dont_descend
= True
;
2574 space_remaining
= max_data_bytes
;
2575 out_of_space
= False
;
2577 for (i
=0;(i
<maxentries
) && !finished
&& !out_of_space
;i
++) {
2578 bool got_exact_match
= False
;
2580 /* this is a heuristic to avoid seeking the dirptr except when
2581 absolutely necessary. It allows for a filename of about 40 chars */
2582 if (space_remaining
< DIRLEN_GUESS
&& numentries
> 0) {
2583 out_of_space
= True
;
2586 finished
= !get_lanman2_dir_entry(ctx
,
2590 mask
,dirtype
,info_level
,
2591 requires_resume_key
,dont_descend
,
2594 space_remaining
, &out_of_space
,
2596 &last_entry_off
, ea_list
);
2599 if (finished
&& out_of_space
)
2602 if (!finished
&& !out_of_space
)
2606 * As an optimisation if we know we aren't looking
2607 * for a wildcard name (ie. the name matches the wildcard exactly)
2608 * then we can finish on any (first) match.
2609 * This speeds up large directory searches. JRA.
2615 /* Ensure space_remaining never goes -ve. */
2616 if (PTR_DIFF(p
,pdata
) > max_data_bytes
) {
2617 space_remaining
= 0;
2618 out_of_space
= true;
2620 space_remaining
= max_data_bytes
- PTR_DIFF(p
,pdata
);
2624 /* Check if we can close the dirptr */
2625 if(close_after_first
|| (finished
&& close_if_end
)) {
2626 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num
));
2627 dptr_close(sconn
, &dptr_num
);
2631 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2632 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2633 * the protocol level is less than NT1. Tested with smbclient. JRA.
2634 * This should fix the OS/2 client bug #2335.
2637 if(numentries
== 0) {
2638 dptr_close(sconn
, &dptr_num
);
2639 if (get_Protocol() < PROTOCOL_NT1
) {
2640 reply_force_doserror(req
, ERRDOS
, ERRnofiles
);
2643 reply_botherror(req
, NT_STATUS_NO_SUCH_FILE
,
2644 ERRDOS
, ERRbadfile
);
2649 /* At this point pdata points to numentries directory entries. */
2651 /* Set up the return parameter block */
2652 SSVAL(params
,0,dptr_num
);
2653 SSVAL(params
,2,numentries
);
2654 SSVAL(params
,4,finished
);
2655 SSVAL(params
,6,0); /* Never an EA error */
2656 SSVAL(params
,8,last_entry_off
);
2658 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 10, pdata
, PTR_DIFF(p
,pdata
),
2661 if ((! *directory
) && dptr_path(sconn
, dptr_num
)) {
2662 directory
= talloc_strdup(talloc_tos(),dptr_path(sconn
, dptr_num
));
2664 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2668 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2669 smb_fn_name(req
->cmd
),
2670 mask
, directory
, dirtype
, numentries
) );
2673 * Force a name mangle here to ensure that the
2674 * mask as an 8.3 name is top of the mangled cache.
2675 * The reasons for this are subtle. Don't remove
2676 * this code unless you know what you are doing
2677 * (see PR#13758). JRA.
2680 if(!mangle_is_8_3_wildcards( mask
, False
, conn
->params
)) {
2681 char mangled_name
[13];
2682 name_to_8_3(mask
, mangled_name
, True
, conn
->params
);
2690 TALLOC_FREE(smb_dname
);
2694 /****************************************************************************
2695 Reply to a TRANS2_FINDNEXT.
2696 ****************************************************************************/
2698 static void call_trans2findnext(connection_struct
*conn
,
2699 struct smb_request
*req
,
2700 char **pparams
, int total_params
,
2701 char **ppdata
, int total_data
,
2702 unsigned int max_data_bytes
)
2704 /* We must be careful here that we don't return more than the
2705 allowed number of data bytes. If this means returning fewer than
2706 maxentries then so be it. We assume that the redirector has
2707 enough room for the fixed number of parameter bytes it has
2709 char *params
= *pparams
;
2710 char *pdata
= *ppdata
;
2716 uint16 findnext_flags
;
2717 bool close_after_request
;
2719 bool requires_resume_key
;
2721 bool mask_contains_wcard
= False
;
2722 char *resume_name
= NULL
;
2723 const char *mask
= NULL
;
2724 const char *directory
= NULL
;
2728 int i
, last_entry_off
=0;
2729 bool finished
= False
;
2730 bool dont_descend
= False
;
2731 bool out_of_space
= False
;
2732 int space_remaining
;
2733 struct ea_list
*ea_list
= NULL
;
2734 NTSTATUS ntstatus
= NT_STATUS_OK
;
2735 bool ask_sharemode
= lp_parm_bool(SNUM(conn
), "smbd", "search ask sharemode", true);
2736 TALLOC_CTX
*ctx
= talloc_tos();
2737 struct dptr_struct
*dirptr
;
2738 struct smbd_server_connection
*sconn
= req
->sconn
;
2739 bool backup_priv
= false;
2741 if (total_params
< 13) {
2742 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2746 dptr_num
= SVAL(params
,0);
2747 maxentries
= SVAL(params
,2);
2748 info_level
= SVAL(params
,4);
2749 resume_key
= IVAL(params
,6);
2750 findnext_flags
= SVAL(params
,10);
2751 close_after_request
= (findnext_flags
& FLAG_TRANS2_FIND_CLOSE
);
2752 close_if_end
= (findnext_flags
& FLAG_TRANS2_FIND_CLOSE_IF_END
);
2753 requires_resume_key
= (findnext_flags
& FLAG_TRANS2_FIND_REQUIRE_RESUME
);
2754 continue_bit
= (findnext_flags
& FLAG_TRANS2_FIND_CONTINUE
);
2756 if (!continue_bit
) {
2757 /* We only need resume_name if continue_bit is zero. */
2758 srvstr_get_path_wcard(ctx
, params
, req
->flags2
, &resume_name
,
2760 total_params
- 12, STR_TERMINATE
, &ntstatus
,
2761 &mask_contains_wcard
);
2762 if (!NT_STATUS_IS_OK(ntstatus
)) {
2763 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2764 complain (it thinks we're asking for the directory above the shared
2765 path or an invalid name). Catch this as the resume name is only compared, never used in
2766 a file access. JRA. */
2767 srvstr_pull_talloc(ctx
, params
, req
->flags2
,
2768 &resume_name
, params
+12,
2772 if (!resume_name
|| !(ISDOT(resume_name
) || ISDOTDOT(resume_name
))) {
2773 reply_nterror(req
, ntstatus
);
2779 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2780 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2781 resume_key = %d resume name = %s continue=%d level = %d\n",
2782 dptr_num
, max_data_bytes
, maxentries
, close_after_request
, close_if_end
,
2783 requires_resume_key
, resume_key
,
2784 resume_name
? resume_name
: "(NULL)", continue_bit
, info_level
));
2787 /* W2K3 seems to treat zero as 1. */
2791 switch (info_level
) {
2792 case SMB_FIND_INFO_STANDARD
:
2793 case SMB_FIND_EA_SIZE
:
2794 case SMB_FIND_EA_LIST
:
2795 case SMB_FIND_FILE_DIRECTORY_INFO
:
2796 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
2797 case SMB_FIND_FILE_NAMES_INFO
:
2798 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
2799 case SMB_FIND_ID_FULL_DIRECTORY_INFO
:
2800 case SMB_FIND_ID_BOTH_DIRECTORY_INFO
:
2802 case SMB_FIND_FILE_UNIX
:
2803 case SMB_FIND_FILE_UNIX_INFO2
:
2804 /* Always use filesystem for UNIX mtime query. */
2805 ask_sharemode
= false;
2806 if (!lp_unix_extensions()) {
2807 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2812 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2816 if (info_level
== SMB_FIND_EA_LIST
) {
2819 if (total_data
< 4) {
2820 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2824 ea_size
= IVAL(pdata
,0);
2825 if (ea_size
!= total_data
) {
2826 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2827 total_data=%u (should be %u)\n", (unsigned int)total_data
, (unsigned int)IVAL(pdata
,0) ));
2828 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2832 if (!lp_ea_support(SNUM(conn
))) {
2833 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
2837 /* Pull out the list of names. */
2838 ea_list
= read_ea_name_list(ctx
, pdata
+ 4, ea_size
- 4);
2840 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2845 *ppdata
= (char *)SMB_REALLOC(
2846 *ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
2847 if(*ppdata
== NULL
) {
2848 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2853 data_end
= pdata
+ max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
- 1;
2855 /* Realloc the params space */
2856 *pparams
= (char *)SMB_REALLOC(*pparams
, 6*SIZEOFWORD
);
2857 if(*pparams
== NULL
) {
2858 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2864 /* Check that the dptr is valid */
2865 if(!(dirptr
= dptr_fetch_lanman2(sconn
, dptr_num
))) {
2866 reply_nterror(req
, STATUS_NO_MORE_FILES
);
2870 directory
= dptr_path(sconn
, dptr_num
);
2872 /* Get the wildcard mask from the dptr */
2873 if((mask
= dptr_wcard(sconn
, dptr_num
))== NULL
) {
2874 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num
));
2875 reply_nterror(req
, STATUS_NO_MORE_FILES
);
2879 /* Get the attr mask from the dptr */
2880 dirtype
= dptr_attr(sconn
, dptr_num
);
2882 backup_priv
= dptr_get_priv(dirptr
);
2884 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld) "
2885 "backup_priv = %d\n",
2886 dptr_num
, mask
, dirtype
,
2888 dptr_TellDir(dirptr
),
2891 /* Initialize per TRANS2_FIND_NEXT operation data */
2892 dptr_init_search_op(dirptr
);
2894 /* We don't need to check for VOL here as this is returned by
2895 a different TRANS2 call. */
2897 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2898 directory
,lp_dontdescend(ctx
, SNUM(conn
))));
2899 if (in_list(directory
,lp_dontdescend(ctx
, SNUM(conn
)),conn
->case_sensitive
))
2900 dont_descend
= True
;
2903 space_remaining
= max_data_bytes
;
2904 out_of_space
= False
;
2911 * Seek to the correct position. We no longer use the resume key but
2912 * depend on the last file name instead.
2915 if(!continue_bit
&& resume_name
&& *resume_name
) {
2918 long current_pos
= 0;
2920 * Remember, name_to_8_3 is called by
2921 * get_lanman2_dir_entry(), so the resume name
2922 * could be mangled. Ensure we check the unmangled name.
2925 if (mangle_is_mangled(resume_name
, conn
->params
)) {
2926 char *new_resume_name
= NULL
;
2927 mangle_lookup_name_from_8_3(ctx
,
2931 if (new_resume_name
) {
2932 resume_name
= new_resume_name
;
2937 * Fix for NT redirector problem triggered by resume key indexes
2938 * changing between directory scans. We now return a resume key of 0
2939 * and instead look for the filename to continue from (also given
2940 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2941 * findfirst/findnext (as is usual) then the directory pointer
2942 * should already be at the correct place.
2945 finished
= !dptr_SearchDir(dirptr
, resume_name
, ¤t_pos
, &st
);
2946 } /* end if resume_name && !continue_bit */
2948 for (i
=0;(i
<(int)maxentries
) && !finished
&& !out_of_space
;i
++) {
2949 bool got_exact_match
= False
;
2951 /* this is a heuristic to avoid seeking the dirptr except when
2952 absolutely necessary. It allows for a filename of about 40 chars */
2953 if (space_remaining
< DIRLEN_GUESS
&& numentries
> 0) {
2954 out_of_space
= True
;
2957 finished
= !get_lanman2_dir_entry(ctx
,
2961 mask
,dirtype
,info_level
,
2962 requires_resume_key
,dont_descend
,
2965 space_remaining
, &out_of_space
,
2967 &last_entry_off
, ea_list
);
2970 if (finished
&& out_of_space
)
2973 if (!finished
&& !out_of_space
)
2977 * As an optimisation if we know we aren't looking
2978 * for a wildcard name (ie. the name matches the wildcard exactly)
2979 * then we can finish on any (first) match.
2980 * This speeds up large directory searches. JRA.
2986 space_remaining
= max_data_bytes
- PTR_DIFF(p
,pdata
);
2989 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2990 smb_fn_name(req
->cmd
),
2991 mask
, directory
, dirtype
, numentries
) );
2993 /* Check if we can close the dirptr */
2994 if(close_after_request
|| (finished
&& close_if_end
)) {
2995 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num
));
2996 dptr_close(sconn
, &dptr_num
); /* This frees up the saved mask */
3003 /* Set up the return parameter block */
3004 SSVAL(params
,0,numentries
);
3005 SSVAL(params
,2,finished
);
3006 SSVAL(params
,4,0); /* Never an EA error */
3007 SSVAL(params
,6,last_entry_off
);
3009 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 8, pdata
, PTR_DIFF(p
,pdata
),
3015 unsigned char *create_volume_objectid(connection_struct
*conn
, unsigned char objid
[16])
3017 E_md4hash(lp_servicename(talloc_tos(), SNUM(conn
)),objid
);
3021 static void samba_extended_info_version(struct smb_extended_info
*extended_info
)
3023 SMB_ASSERT(extended_info
!= NULL
);
3025 extended_info
->samba_magic
= SAMBA_EXTENDED_INFO_MAGIC
;
3026 extended_info
->samba_version
= ((SAMBA_VERSION_MAJOR
& 0xff) << 24)
3027 | ((SAMBA_VERSION_MINOR
& 0xff) << 16)
3028 | ((SAMBA_VERSION_RELEASE
& 0xff) << 8);
3029 #ifdef SAMBA_VERSION_REVISION
3030 extended_info
->samba_version
|= (tolower(*SAMBA_VERSION_REVISION
) - 'a' + 1) & 0xff;
3032 extended_info
->samba_subversion
= 0;
3033 #ifdef SAMBA_VERSION_RC_RELEASE
3034 extended_info
->samba_subversion
|= (SAMBA_VERSION_RC_RELEASE
& 0xff) << 24;
3036 #ifdef SAMBA_VERSION_PRE_RELEASE
3037 extended_info
->samba_subversion
|= (SAMBA_VERSION_PRE_RELEASE
& 0xff) << 16;
3040 #ifdef SAMBA_VERSION_VENDOR_PATCH
3041 extended_info
->samba_subversion
|= (SAMBA_VERSION_VENDOR_PATCH
& 0xffff);
3043 extended_info
->samba_gitcommitdate
= 0;
3044 #ifdef SAMBA_VERSION_COMMIT_TIME
3045 unix_to_nt_time(&extended_info
->samba_gitcommitdate
, SAMBA_VERSION_COMMIT_TIME
);
3048 memset(extended_info
->samba_version_string
, 0,
3049 sizeof(extended_info
->samba_version_string
));
3051 snprintf (extended_info
->samba_version_string
,
3052 sizeof(extended_info
->samba_version_string
),
3053 "%s", samba_version_string());
3056 NTSTATUS
smbd_do_qfsinfo(connection_struct
*conn
,
3057 TALLOC_CTX
*mem_ctx
,
3058 uint16_t info_level
,
3060 unsigned int max_data_bytes
,
3061 size_t *fixed_portion
,
3062 struct smb_filename
*fname
,
3066 char *pdata
, *end_data
;
3067 int data_len
= 0, len
;
3068 const char *vname
= volume_label(talloc_tos(), SNUM(conn
));
3069 int snum
= SNUM(conn
);
3070 char *fstype
= lp_fstype(talloc_tos(), SNUM(conn
));
3071 char *filename
= NULL
;
3072 uint32 additional_flags
= 0;
3073 struct smb_filename smb_fname
;
3075 NTSTATUS status
= NT_STATUS_OK
;
3077 if (fname
== NULL
|| fname
->base_name
== NULL
) {
3080 filename
= fname
->base_name
;
3084 if (info_level
!= SMB_QUERY_CIFS_UNIX_INFO
) {
3085 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
3086 "info level (0x%x) on IPC$.\n",
3087 (unsigned int)info_level
));
3088 return NT_STATUS_ACCESS_DENIED
;
3092 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level
));
3094 ZERO_STRUCT(smb_fname
);
3095 smb_fname
.base_name
= discard_const_p(char, filename
);
3097 if(SMB_VFS_STAT(conn
, &smb_fname
) != 0) {
3098 DEBUG(2,("stat of . failed (%s)\n", strerror(errno
)));
3099 return map_nt_error_from_unix(errno
);
3104 *ppdata
= (char *)SMB_REALLOC(
3105 *ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
3106 if (*ppdata
== NULL
) {
3107 return NT_STATUS_NO_MEMORY
;
3111 memset((char *)pdata
,'\0',max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
3112 end_data
= pdata
+ max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
- 1;
3116 switch (info_level
) {
3117 case SMB_INFO_ALLOCATION
:
3119 uint64_t dfree
,dsize
,bsize
,block_size
,sectors_per_unit
,bytes_per_sector
;
3121 if (get_dfree_info(conn
,filename
,False
,&bsize
,&dfree
,&dsize
) == (uint64_t)-1) {
3122 return map_nt_error_from_unix(errno
);
3125 block_size
= lp_block_size(snum
);
3126 if (bsize
< block_size
) {
3127 uint64_t factor
= block_size
/bsize
;
3132 if (bsize
> block_size
) {
3133 uint64_t factor
= bsize
/block_size
;
3138 bytes_per_sector
= 512;
3139 sectors_per_unit
= bsize
/bytes_per_sector
;
3141 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
3142 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st
.st_ex_dev
, (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
3143 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
3145 SIVAL(pdata
,l1_idFileSystem
,st
.st_ex_dev
);
3146 SIVAL(pdata
,l1_cSectorUnit
,sectors_per_unit
);
3147 SIVAL(pdata
,l1_cUnit
,dsize
);
3148 SIVAL(pdata
,l1_cUnitAvail
,dfree
);
3149 SSVAL(pdata
,l1_cbSector
,bytes_per_sector
);
3153 case SMB_INFO_VOLUME
:
3154 /* Return volume name */
3156 * Add volume serial number - hash of a combination of
3157 * the called hostname and the service name.
3159 SIVAL(pdata
,0,str_checksum(lp_servicename(talloc_tos(), snum
)) ^ (str_checksum(get_local_machine_name())<<16) );
3161 * Win2k3 and previous mess this up by sending a name length
3162 * one byte short. I believe only older clients (OS/2 Win9x) use
3163 * this call so try fixing this by adding a terminating null to
3164 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
3168 pdata
+l2_vol_szVolLabel
, vname
,
3169 PTR_DIFF(end_data
, pdata
+l2_vol_szVolLabel
),
3170 STR_NOALIGN
|STR_TERMINATE
);
3171 SCVAL(pdata
,l2_vol_cch
,len
);
3172 data_len
= l2_vol_szVolLabel
+ len
;
3173 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %d, name = %s\n",
3174 (unsigned)convert_timespec_to_time_t(st
.st_ex_ctime
),
3178 case SMB_QUERY_FS_ATTRIBUTE_INFO
:
3179 case SMB_FS_ATTRIBUTE_INFORMATION
:
3181 additional_flags
= 0;
3182 #if defined(HAVE_SYS_QUOTAS)
3183 additional_flags
|= FILE_VOLUME_QUOTAS
;
3186 if(lp_nt_acl_support(SNUM(conn
))) {
3187 additional_flags
|= FILE_PERSISTENT_ACLS
;
3190 /* Capabilities are filled in at connection time through STATVFS call */
3191 additional_flags
|= conn
->fs_capabilities
;
3192 additional_flags
|= lp_parm_int(conn
->params
->service
,
3193 "share", "fake_fscaps",
3196 SIVAL(pdata
,0,FILE_CASE_PRESERVED_NAMES
|FILE_CASE_SENSITIVE_SEARCH
|
3197 FILE_SUPPORTS_OBJECT_IDS
|FILE_UNICODE_ON_DISK
|
3198 additional_flags
); /* FS ATTRIBUTES */
3200 SIVAL(pdata
,4,255); /* Max filename component length */
3201 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
3202 and will think we can't do long filenames */
3203 len
= srvstr_push(pdata
, flags2
, pdata
+12, fstype
,
3204 PTR_DIFF(end_data
, pdata
+12),
3207 data_len
= 12 + len
;
3208 if (max_data_bytes
>= 16 && data_len
> max_data_bytes
) {
3209 /* the client only requested a portion of the
3211 data_len
= max_data_bytes
;
3212 status
= STATUS_BUFFER_OVERFLOW
;
3214 *fixed_portion
= 16;
3217 case SMB_QUERY_FS_LABEL_INFO
:
3218 case SMB_FS_LABEL_INFORMATION
:
3219 len
= srvstr_push(pdata
, flags2
, pdata
+4, vname
,
3220 PTR_DIFF(end_data
, pdata
+4), 0);
3225 case SMB_QUERY_FS_VOLUME_INFO
:
3226 case SMB_FS_VOLUME_INFORMATION
:
3229 * Add volume serial number - hash of a combination of
3230 * the called hostname and the service name.
3232 SIVAL(pdata
,8,str_checksum(lp_servicename(talloc_tos(), snum
)) ^
3233 (str_checksum(get_local_machine_name())<<16));
3235 /* Max label len is 32 characters. */
3236 len
= srvstr_push(pdata
, flags2
, pdata
+18, vname
,
3237 PTR_DIFF(end_data
, pdata
+18),
3239 SIVAL(pdata
,12,len
);
3242 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3243 (int)strlen(vname
),vname
,
3244 lp_servicename(talloc_tos(), snum
)));
3245 if (max_data_bytes
>= 24 && data_len
> max_data_bytes
) {
3246 /* the client only requested a portion of the
3248 data_len
= max_data_bytes
;
3249 status
= STATUS_BUFFER_OVERFLOW
;
3251 *fixed_portion
= 24;
3254 case SMB_QUERY_FS_SIZE_INFO
:
3255 case SMB_FS_SIZE_INFORMATION
:
3257 uint64_t dfree
,dsize
,bsize
,block_size
,sectors_per_unit
,bytes_per_sector
;
3259 if (get_dfree_info(conn
,filename
,False
,&bsize
,&dfree
,&dsize
) == (uint64_t)-1) {
3260 return map_nt_error_from_unix(errno
);
3262 block_size
= lp_block_size(snum
);
3263 if (bsize
< block_size
) {
3264 uint64_t factor
= block_size
/bsize
;
3269 if (bsize
> block_size
) {
3270 uint64_t factor
= bsize
/block_size
;
3275 bytes_per_sector
= 512;
3276 sectors_per_unit
= bsize
/bytes_per_sector
;
3277 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3278 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
3279 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
3280 SBIG_UINT(pdata
,0,dsize
);
3281 SBIG_UINT(pdata
,8,dfree
);
3282 SIVAL(pdata
,16,sectors_per_unit
);
3283 SIVAL(pdata
,20,bytes_per_sector
);
3284 *fixed_portion
= 24;
3288 case SMB_FS_FULL_SIZE_INFORMATION
:
3290 uint64_t dfree
,dsize
,bsize
,block_size
,sectors_per_unit
,bytes_per_sector
;
3292 if (get_dfree_info(conn
,filename
,False
,&bsize
,&dfree
,&dsize
) == (uint64_t)-1) {
3293 return map_nt_error_from_unix(errno
);
3295 block_size
= lp_block_size(snum
);
3296 if (bsize
< block_size
) {
3297 uint64_t factor
= block_size
/bsize
;
3302 if (bsize
> block_size
) {
3303 uint64_t factor
= bsize
/block_size
;
3308 bytes_per_sector
= 512;
3309 sectors_per_unit
= bsize
/bytes_per_sector
;
3310 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3311 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
3312 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
3313 SBIG_UINT(pdata
,0,dsize
); /* Total Allocation units. */
3314 SBIG_UINT(pdata
,8,dfree
); /* Caller available allocation units. */
3315 SBIG_UINT(pdata
,16,dfree
); /* Actual available allocation units. */
3316 SIVAL(pdata
,24,sectors_per_unit
); /* Sectors per allocation unit. */
3317 SIVAL(pdata
,28,bytes_per_sector
); /* Bytes per sector. */
3318 *fixed_portion
= 32;
3322 case SMB_QUERY_FS_DEVICE_INFO
:
3323 case SMB_FS_DEVICE_INFORMATION
:
3325 uint32_t characteristics
= FILE_DEVICE_IS_MOUNTED
;
3327 if (!CAN_WRITE(conn
)) {
3328 characteristics
|= FILE_READ_ONLY_DEVICE
;
3331 SIVAL(pdata
,0,FILE_DEVICE_DISK
); /* dev type */
3332 SIVAL(pdata
,4,characteristics
);
3337 #ifdef HAVE_SYS_QUOTAS
3338 case SMB_FS_QUOTA_INFORMATION
:
3340 * what we have to send --metze:
3342 * Unknown1: 24 NULL bytes
3343 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3344 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3345 * Quota Flags: 2 byte :
3346 * Unknown3: 6 NULL bytes
3350 * details for Quota Flags:
3352 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3353 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3354 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3355 * 0x0001 Enable Quotas: enable quota for this fs
3359 /* we need to fake up a fsp here,
3360 * because its not send in this call
3363 SMB_NTQUOTA_STRUCT quotas
;
3366 ZERO_STRUCT(quotas
);
3369 fsp
.fnum
= FNUM_FIELD_INVALID
;
3372 if (get_current_uid(conn
) != 0) {
3373 DEBUG(0,("set_user_quota: access_denied "
3374 "service [%s] user [%s]\n",
3375 lp_servicename(talloc_tos(), SNUM(conn
)),
3376 conn
->session_info
->unix_info
->unix_name
));
3377 return NT_STATUS_ACCESS_DENIED
;
3380 if (vfs_get_ntquota(&fsp
, SMB_USER_FS_QUOTA_TYPE
, NULL
, "as
)!=0) {
3381 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn
))));
3382 return map_nt_error_from_unix(errno
);
3387 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3388 lp_servicename(talloc_tos(), SNUM(conn
))));
3390 /* Unknown1 24 NULL bytes*/
3391 SBIG_UINT(pdata
,0,(uint64_t)0);
3392 SBIG_UINT(pdata
,8,(uint64_t)0);
3393 SBIG_UINT(pdata
,16,(uint64_t)0);
3395 /* Default Soft Quota 8 bytes */
3396 SBIG_UINT(pdata
,24,quotas
.softlim
);
3398 /* Default Hard Quota 8 bytes */
3399 SBIG_UINT(pdata
,32,quotas
.hardlim
);
3401 /* Quota flag 2 bytes */
3402 SSVAL(pdata
,40,quotas
.qflags
);
3404 /* Unknown3 6 NULL bytes */
3410 #endif /* HAVE_SYS_QUOTAS */
3411 case SMB_FS_OBJECTID_INFORMATION
:
3413 unsigned char objid
[16];
3414 struct smb_extended_info extended_info
;
3415 memcpy(pdata
,create_volume_objectid(conn
, objid
),16);
3416 samba_extended_info_version (&extended_info
);
3417 SIVAL(pdata
,16,extended_info
.samba_magic
);
3418 SIVAL(pdata
,20,extended_info
.samba_version
);
3419 SIVAL(pdata
,24,extended_info
.samba_subversion
);
3420 SBIG_UINT(pdata
,28,extended_info
.samba_gitcommitdate
);
3421 memcpy(pdata
+36,extended_info
.samba_version_string
,28);
3427 * Query the version and capabilities of the CIFS UNIX extensions
3431 case SMB_QUERY_CIFS_UNIX_INFO
:
3433 bool large_write
= lp_min_receive_file_size() &&
3434 !srv_is_signing_active(conn
->sconn
);
3435 bool large_read
= !srv_is_signing_active(conn
->sconn
);
3436 int encrypt_caps
= 0;
3438 if (!lp_unix_extensions()) {
3439 return NT_STATUS_INVALID_LEVEL
;
3442 switch (conn
->encrypt_level
) {
3443 case SMB_SIGNING_OFF
:
3446 case SMB_SIGNING_IF_REQUIRED
:
3447 case SMB_SIGNING_DEFAULT
:
3448 encrypt_caps
= CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP
;
3450 case SMB_SIGNING_REQUIRED
:
3451 encrypt_caps
= CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP
|
3452 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP
;
3453 large_write
= false;
3459 SSVAL(pdata
,0,CIFS_UNIX_MAJOR_VERSION
);
3460 SSVAL(pdata
,2,CIFS_UNIX_MINOR_VERSION
);
3462 /* We have POSIX ACLs, pathname, encryption,
3463 * large read/write, and locking capability. */
3465 SBIG_UINT(pdata
,4,((uint64_t)(
3466 CIFS_UNIX_POSIX_ACLS_CAP
|
3467 CIFS_UNIX_POSIX_PATHNAMES_CAP
|
3468 CIFS_UNIX_FCNTL_LOCKS_CAP
|
3469 CIFS_UNIX_EXTATTR_CAP
|
3470 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP
|
3472 (large_read
? CIFS_UNIX_LARGE_READ_CAP
: 0) |
3474 CIFS_UNIX_LARGE_WRITE_CAP
: 0))));
3478 case SMB_QUERY_POSIX_FS_INFO
:
3481 vfs_statvfs_struct svfs
;
3483 if (!lp_unix_extensions()) {
3484 return NT_STATUS_INVALID_LEVEL
;
3487 rc
= SMB_VFS_STATVFS(conn
, filename
, &svfs
);
3491 SIVAL(pdata
,0,svfs
.OptimalTransferSize
);
3492 SIVAL(pdata
,4,svfs
.BlockSize
);
3493 SBIG_UINT(pdata
,8,svfs
.TotalBlocks
);
3494 SBIG_UINT(pdata
,16,svfs
.BlocksAvail
);
3495 SBIG_UINT(pdata
,24,svfs
.UserBlocksAvail
);
3496 SBIG_UINT(pdata
,32,svfs
.TotalFileNodes
);
3497 SBIG_UINT(pdata
,40,svfs
.FreeFileNodes
);
3498 SBIG_UINT(pdata
,48,svfs
.FsIdentifier
);
3499 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3501 } else if (rc
== EOPNOTSUPP
) {
3502 return NT_STATUS_INVALID_LEVEL
;
3503 #endif /* EOPNOTSUPP */
3505 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn
))));
3506 return NT_STATUS_DOS(ERRSRV
, ERRerror
);
3511 case SMB_QUERY_POSIX_WHOAMI
:
3517 if (!lp_unix_extensions()) {
3518 return NT_STATUS_INVALID_LEVEL
;
3521 if (max_data_bytes
< 40) {
3522 return NT_STATUS_BUFFER_TOO_SMALL
;
3525 if (security_session_user_level(conn
->session_info
, NULL
) < SECURITY_USER
) {
3526 flags
|= SMB_WHOAMI_GUEST
;
3529 /* NOTE: 8 bytes for UID/GID, irrespective of native
3530 * platform size. This matches
3531 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3533 data_len
= 4 /* flags */
3540 + 4 /* pad/reserved */
3541 + (conn
->session_info
->unix_token
->ngroups
* 8)
3543 + (conn
->session_info
->security_token
->num_sids
*
3547 SIVAL(pdata
, 0, flags
);
3548 SIVAL(pdata
, 4, SMB_WHOAMI_MASK
);
3550 (uint64_t)conn
->session_info
->unix_token
->uid
);
3551 SBIG_UINT(pdata
, 16,
3552 (uint64_t)conn
->session_info
->unix_token
->gid
);
3555 if (data_len
>= max_data_bytes
) {
3556 /* Potential overflow, skip the GIDs and SIDs. */
3558 SIVAL(pdata
, 24, 0); /* num_groups */
3559 SIVAL(pdata
, 28, 0); /* num_sids */
3560 SIVAL(pdata
, 32, 0); /* num_sid_bytes */
3561 SIVAL(pdata
, 36, 0); /* reserved */
3567 SIVAL(pdata
, 24, conn
->session_info
->unix_token
->ngroups
);
3568 SIVAL(pdata
, 28, conn
->session_info
->security_token
->num_sids
);
3570 /* We walk the SID list twice, but this call is fairly
3571 * infrequent, and I don't expect that it's performance
3572 * sensitive -- jpeach
3574 for (i
= 0, sid_bytes
= 0;
3575 i
< conn
->session_info
->security_token
->num_sids
; ++i
) {
3576 sid_bytes
+= ndr_size_dom_sid(
3577 &conn
->session_info
->security_token
->sids
[i
],
3581 /* SID list byte count */
3582 SIVAL(pdata
, 32, sid_bytes
);
3584 /* 4 bytes pad/reserved - must be zero */
3585 SIVAL(pdata
, 36, 0);
3589 for (i
= 0; i
< conn
->session_info
->unix_token
->ngroups
; ++i
) {
3590 SBIG_UINT(pdata
, data_len
,
3591 (uint64_t)conn
->session_info
->unix_token
->groups
[i
]);
3597 i
< conn
->session_info
->security_token
->num_sids
; ++i
) {
3598 int sid_len
= ndr_size_dom_sid(
3599 &conn
->session_info
->security_token
->sids
[i
],
3602 sid_linearize(pdata
+ data_len
, sid_len
,
3603 &conn
->session_info
->security_token
->sids
[i
]);
3604 data_len
+= sid_len
;
3610 case SMB_MAC_QUERY_FS_INFO
:
3612 * Thursby MAC extension... ONLY on NTFS filesystems
3613 * once we do streams then we don't need this
3615 if (strequal(lp_fstype(talloc_tos(), SNUM(conn
)),"NTFS")) {
3617 SIVAL(pdata
,84,0x100); /* Don't support mac... */
3622 return NT_STATUS_INVALID_LEVEL
;
3625 *ret_data_len
= data_len
;
3629 /****************************************************************************
3630 Reply to a TRANS2_QFSINFO (query filesystem info).
3631 ****************************************************************************/
3633 static void call_trans2qfsinfo(connection_struct
*conn
,
3634 struct smb_request
*req
,
3635 char **pparams
, int total_params
,
3636 char **ppdata
, int total_data
,
3637 unsigned int max_data_bytes
)
3639 char *params
= *pparams
;
3640 uint16_t info_level
;
3642 size_t fixed_portion
;
3645 if (total_params
< 2) {
3646 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3650 info_level
= SVAL(params
,0);
3652 if (ENCRYPTION_REQUIRED(conn
) && !req
->encrypted
) {
3653 if (info_level
!= SMB_QUERY_CIFS_UNIX_INFO
) {
3654 DEBUG(0,("call_trans2qfsinfo: encryption required "
3655 "and info level 0x%x sent.\n",
3656 (unsigned int)info_level
));
3657 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3662 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level
));
3664 status
= smbd_do_qfsinfo(conn
, req
,
3671 if (!NT_STATUS_IS_OK(status
)) {
3672 reply_nterror(req
, status
);
3676 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 0, *ppdata
, data_len
,
3679 DEBUG( 4, ( "%s info_level = %d\n",
3680 smb_fn_name(req
->cmd
), info_level
) );
3685 /****************************************************************************
3686 Reply to a TRANS2_SETFSINFO (set filesystem info).
3687 ****************************************************************************/
3689 static void call_trans2setfsinfo(connection_struct
*conn
,
3690 struct smb_request
*req
,
3691 char **pparams
, int total_params
,
3692 char **ppdata
, int total_data
,
3693 unsigned int max_data_bytes
)
3695 struct smbd_server_connection
*sconn
= req
->sconn
;
3696 char *pdata
= *ppdata
;
3697 char *params
= *pparams
;
3700 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",
3701 lp_servicename(talloc_tos(), SNUM(conn
))));
3704 if (total_params
< 4) {
3705 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3707 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3711 info_level
= SVAL(params
,2);
3714 if (info_level
!= SMB_REQUEST_TRANSPORT_ENCRYPTION
&&
3715 info_level
!= SMB_SET_CIFS_UNIX_INFO
) {
3716 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3717 "info level (0x%x) on IPC$.\n",
3718 (unsigned int)info_level
));
3719 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3724 if (ENCRYPTION_REQUIRED(conn
) && !req
->encrypted
) {
3725 if (info_level
!= SMB_REQUEST_TRANSPORT_ENCRYPTION
) {
3726 DEBUG(0,("call_trans2setfsinfo: encryption required "
3727 "and info level 0x%x sent.\n",
3728 (unsigned int)info_level
));
3729 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3734 switch(info_level
) {
3735 case SMB_SET_CIFS_UNIX_INFO
:
3736 if (!lp_unix_extensions()) {
3737 DEBUG(2,("call_trans2setfsinfo: "
3738 "SMB_SET_CIFS_UNIX_INFO is invalid with "
3739 "unix extensions off\n"));
3741 NT_STATUS_INVALID_LEVEL
);
3745 /* There should be 12 bytes of capabilities set. */
3746 if (total_data
< 12) {
3749 NT_STATUS_INVALID_PARAMETER
);
3752 sconn
->smb1
.unix_info
.client_major
= SVAL(pdata
,0);
3753 sconn
->smb1
.unix_info
.client_minor
= SVAL(pdata
,2);
3754 sconn
->smb1
.unix_info
.client_cap_low
= IVAL(pdata
,4);
3755 sconn
->smb1
.unix_info
.client_cap_high
= IVAL(pdata
,8);
3756 /* Just print these values for now. */
3757 DEBUG(10, ("call_trans2setfsinfo: set unix_info info. "
3758 "major = %u, minor = %u cap_low = 0x%x, "
3760 (unsigned int)sconn
->
3761 smb1
.unix_info
.client_major
,
3762 (unsigned int)sconn
->
3763 smb1
.unix_info
.client_minor
,
3764 (unsigned int)sconn
->
3765 smb1
.unix_info
.client_cap_low
,
3766 (unsigned int)sconn
->
3767 smb1
.unix_info
.client_cap_high
));
3769 /* Here is where we must switch to posix pathname processing... */
3770 if (sconn
->smb1
.unix_info
.client_cap_low
& CIFS_UNIX_POSIX_PATHNAMES_CAP
) {
3771 lp_set_posix_pathnames();
3772 mangle_change_to_posix();
3775 if ((sconn
->smb1
.unix_info
.client_cap_low
& CIFS_UNIX_FCNTL_LOCKS_CAP
) &&
3776 !(sconn
->smb1
.unix_info
.client_cap_low
& CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP
)) {
3777 /* Client that knows how to do posix locks,
3778 * but not posix open/mkdir operations. Set a
3779 * default type for read/write checks. */
3781 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK
);
3786 case SMB_REQUEST_TRANSPORT_ENCRYPTION
:
3789 size_t param_len
= 0;
3790 size_t data_len
= total_data
;
3792 if (!lp_unix_extensions()) {
3795 NT_STATUS_INVALID_LEVEL
);
3799 if (lp_smb_encrypt(SNUM(conn
)) == SMB_SIGNING_OFF
) {
3802 NT_STATUS_NOT_SUPPORTED
);
3806 if (req
->sconn
->smb1
.echo_handler
.trusted_fde
) {
3807 DEBUG( 2,("call_trans2setfsinfo: "
3808 "request transport encryption disabled"
3809 "with 'fork echo handler = yes'\n"));
3812 NT_STATUS_NOT_SUPPORTED
);
3816 DEBUG( 4,("call_trans2setfsinfo: "
3817 "request transport encryption.\n"));
3819 status
= srv_request_encryption_setup(conn
,
3820 (unsigned char **)ppdata
,
3822 (unsigned char **)pparams
,
3825 if (!NT_STATUS_EQUAL(status
, NT_STATUS_MORE_PROCESSING_REQUIRED
) &&
3826 !NT_STATUS_IS_OK(status
)) {
3827 reply_nterror(req
, status
);
3831 send_trans2_replies(conn
, req
,
3839 if (NT_STATUS_IS_OK(status
)) {
3840 /* Server-side transport
3841 * encryption is now *on*. */
3842 status
= srv_encryption_start(conn
);
3843 if (!NT_STATUS_IS_OK(status
)) {
3844 char *reason
= talloc_asprintf(talloc_tos(),
3845 "Failure in setting "
3846 "up encrypted transport: %s",
3848 exit_server_cleanly(reason
);
3854 case SMB_FS_QUOTA_INFORMATION
:
3856 files_struct
*fsp
= NULL
;
3857 SMB_NTQUOTA_STRUCT quotas
;
3859 ZERO_STRUCT(quotas
);
3862 if ((get_current_uid(conn
) != 0) || !CAN_WRITE(conn
)) {
3863 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3864 lp_servicename(talloc_tos(), SNUM(conn
)),
3865 conn
->session_info
->unix_info
->unix_name
));
3866 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3870 /* note: normaly there're 48 bytes,
3871 * but we didn't use the last 6 bytes for now
3874 fsp
= file_fsp(req
, SVAL(params
,0));
3876 if (!check_fsp_ntquota_handle(conn
, req
,
3878 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3880 req
, NT_STATUS_INVALID_HANDLE
);
3884 if (total_data
< 42) {
3885 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3889 NT_STATUS_INVALID_PARAMETER
);
3893 /* unknown_1 24 NULL bytes in pdata*/
3895 /* the soft quotas 8 bytes (uint64_t)*/
3896 quotas
.softlim
= BVAL(pdata
,24);
3898 /* the hard quotas 8 bytes (uint64_t)*/
3899 quotas
.hardlim
= BVAL(pdata
,32);
3901 /* quota_flags 2 bytes **/
3902 quotas
.qflags
= SVAL(pdata
,40);
3904 /* unknown_2 6 NULL bytes follow*/
3906 /* now set the quotas */
3907 if (vfs_set_ntquota(fsp
, SMB_USER_FS_QUOTA_TYPE
, NULL
, "as
)!=0) {
3908 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn
))));
3909 reply_nterror(req
, map_nt_error_from_unix(errno
));
3916 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3918 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
3924 * sending this reply works fine,
3925 * but I'm not sure it's the same
3926 * like windows do...
3929 reply_outbuf(req
, 10, 0);
3932 #if defined(HAVE_POSIX_ACLS)
3933 /****************************************************************************
3934 Utility function to count the number of entries in a POSIX acl.
3935 ****************************************************************************/
3937 static unsigned int count_acl_entries(connection_struct
*conn
, SMB_ACL_T posix_acl
)
3939 unsigned int ace_count
= 0;
3940 int entry_id
= SMB_ACL_FIRST_ENTRY
;
3941 SMB_ACL_ENTRY_T entry
;
3943 while ( posix_acl
&& (sys_acl_get_entry(posix_acl
, entry_id
, &entry
) == 1)) {
3945 if (entry_id
== SMB_ACL_FIRST_ENTRY
) {
3946 entry_id
= SMB_ACL_NEXT_ENTRY
;
3953 /****************************************************************************
3954 Utility function to marshall a POSIX acl into wire format.
3955 ****************************************************************************/
3957 static bool marshall_posix_acl(connection_struct
*conn
, char *pdata
, SMB_STRUCT_STAT
*pst
, SMB_ACL_T posix_acl
)
3959 int entry_id
= SMB_ACL_FIRST_ENTRY
;
3960 SMB_ACL_ENTRY_T entry
;
3962 while ( posix_acl
&& (sys_acl_get_entry(posix_acl
, entry_id
, &entry
) == 1)) {
3963 SMB_ACL_TAG_T tagtype
;
3964 SMB_ACL_PERMSET_T permset
;
3965 unsigned char perms
= 0;
3966 unsigned int own_grp
;
3969 if (entry_id
== SMB_ACL_FIRST_ENTRY
) {
3970 entry_id
= SMB_ACL_NEXT_ENTRY
;
3973 if (sys_acl_get_tag_type(entry
, &tagtype
) == -1) {
3974 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3978 if (sys_acl_get_permset(entry
, &permset
) == -1) {
3979 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3983 perms
|= (sys_acl_get_perm(permset
, SMB_ACL_READ
) ? SMB_POSIX_ACL_READ
: 0);
3984 perms
|= (sys_acl_get_perm(permset
, SMB_ACL_WRITE
) ? SMB_POSIX_ACL_WRITE
: 0);
3985 perms
|= (sys_acl_get_perm(permset
, SMB_ACL_EXECUTE
) ? SMB_POSIX_ACL_EXECUTE
: 0);
3987 SCVAL(pdata
,1,perms
);
3990 case SMB_ACL_USER_OBJ
:
3991 SCVAL(pdata
,0,SMB_POSIX_ACL_USER_OBJ
);
3992 own_grp
= (unsigned int)pst
->st_ex_uid
;
3993 SIVAL(pdata
,2,own_grp
);
3998 uid_t
*puid
= (uid_t
*)sys_acl_get_qualifier(entry
);
4000 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
4003 own_grp
= (unsigned int)*puid
;
4004 SCVAL(pdata
,0,SMB_POSIX_ACL_USER
);
4005 SIVAL(pdata
,2,own_grp
);
4009 case SMB_ACL_GROUP_OBJ
:
4010 SCVAL(pdata
,0,SMB_POSIX_ACL_GROUP_OBJ
);
4011 own_grp
= (unsigned int)pst
->st_ex_gid
;
4012 SIVAL(pdata
,2,own_grp
);
4017 gid_t
*pgid
= (gid_t
*)sys_acl_get_qualifier(entry
);
4019 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
4022 own_grp
= (unsigned int)*pgid
;
4023 SCVAL(pdata
,0,SMB_POSIX_ACL_GROUP
);
4024 SIVAL(pdata
,2,own_grp
);
4029 SCVAL(pdata
,0,SMB_POSIX_ACL_MASK
);
4030 SIVAL(pdata
,2,0xFFFFFFFF);
4031 SIVAL(pdata
,6,0xFFFFFFFF);
4034 SCVAL(pdata
,0,SMB_POSIX_ACL_OTHER
);
4035 SIVAL(pdata
,2,0xFFFFFFFF);
4036 SIVAL(pdata
,6,0xFFFFFFFF);
4039 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
4042 pdata
+= SMB_POSIX_ACL_ENTRY_SIZE
;
4049 /****************************************************************************
4050 Store the FILE_UNIX_BASIC info.
4051 ****************************************************************************/
4053 static char *store_file_unix_basic(connection_struct
*conn
,
4056 const SMB_STRUCT_STAT
*psbuf
)
4058 uint64_t file_index
= get_FileIndex(conn
, psbuf
);
4061 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
4062 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf
->st_ex_mode
));
4064 SOFF_T(pdata
,0,get_file_size_stat(psbuf
)); /* File size 64 Bit */
4067 SOFF_T(pdata
,0,SMB_VFS_GET_ALLOC_SIZE(conn
,fsp
,psbuf
)); /* Number of bytes used on disk - 64 Bit */
4070 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER
, pdata
, psbuf
->st_ex_ctime
); /* Change Time 64 Bit */
4071 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER
,pdata
+8, psbuf
->st_ex_atime
); /* Last access time 64 Bit */
4072 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER
, pdata
+16, psbuf
->st_ex_mtime
); /* Last modification time 64 Bit */
4075 SIVAL(pdata
,0,psbuf
->st_ex_uid
); /* user id for the owner */
4079 SIVAL(pdata
,0,psbuf
->st_ex_gid
); /* group id of owner */
4083 SIVAL(pdata
,0,unix_filetype(psbuf
->st_ex_mode
));
4086 if (S_ISBLK(psbuf
->st_ex_mode
) || S_ISCHR(psbuf
->st_ex_mode
)) {
4087 devno
= psbuf
->st_ex_rdev
;
4089 devno
= psbuf
->st_ex_dev
;
4092 SIVAL(pdata
,0,unix_dev_major(devno
)); /* Major device number if type is device */
4096 SIVAL(pdata
,0,unix_dev_minor(devno
)); /* Minor device number if type is device */
4100 SINO_T_VAL(pdata
,0,(SMB_INO_T
)file_index
); /* inode number */
4103 SIVAL(pdata
,0, unix_perms_to_wire(psbuf
->st_ex_mode
)); /* Standard UNIX file permissions */
4107 SIVAL(pdata
,0,psbuf
->st_ex_nlink
); /* number of hard links */
4114 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
4115 * the chflags(2) (or equivalent) flags.
4117 * XXX: this really should be behind the VFS interface. To do this, we would
4118 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
4119 * Each VFS module could then implement its own mapping as appropriate for the
4120 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
4122 static const struct {unsigned stat_fflag
; unsigned smb_fflag
;}
4126 { UF_NODUMP
, EXT_DO_NOT_BACKUP
},
4130 { UF_IMMUTABLE
, EXT_IMMUTABLE
},
4134 { UF_APPEND
, EXT_OPEN_APPEND_ONLY
},
4138 { UF_HIDDEN
, EXT_HIDDEN
},
4141 /* Do not remove. We need to guarantee that this array has at least one
4142 * entry to build on HP-UX.
4148 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT
*psbuf
,
4149 uint32
*smb_fflags
, uint32
*smb_fmask
)
4153 for (i
= 0; i
< ARRAY_SIZE(info2_flags_map
); ++i
) {
4154 *smb_fmask
|= info2_flags_map
[i
].smb_fflag
;
4155 if (psbuf
->st_ex_flags
& info2_flags_map
[i
].stat_fflag
) {
4156 *smb_fflags
|= info2_flags_map
[i
].smb_fflag
;
4161 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT
*psbuf
,
4162 const uint32 smb_fflags
,
4163 const uint32 smb_fmask
,
4166 uint32 max_fmask
= 0;
4169 *stat_fflags
= psbuf
->st_ex_flags
;
4171 /* For each flags requested in smb_fmask, check the state of the
4172 * corresponding flag in smb_fflags and set or clear the matching
4176 for (i
= 0; i
< ARRAY_SIZE(info2_flags_map
); ++i
) {
4177 max_fmask
|= info2_flags_map
[i
].smb_fflag
;
4178 if (smb_fmask
& info2_flags_map
[i
].smb_fflag
) {
4179 if (smb_fflags
& info2_flags_map
[i
].smb_fflag
) {
4180 *stat_fflags
|= info2_flags_map
[i
].stat_fflag
;
4182 *stat_fflags
&= ~info2_flags_map
[i
].stat_fflag
;
4187 /* If smb_fmask is asking to set any bits that are not supported by
4188 * our flag mappings, we should fail.
4190 if ((smb_fmask
& max_fmask
) != smb_fmask
) {
4198 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
4199 * of file flags and birth (create) time.
4201 static char *store_file_unix_basic_info2(connection_struct
*conn
,
4204 const SMB_STRUCT_STAT
*psbuf
)
4206 uint32 file_flags
= 0;
4207 uint32 flags_mask
= 0;
4209 pdata
= store_file_unix_basic(conn
, pdata
, fsp
, psbuf
);
4211 /* Create (birth) time 64 bit */
4212 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER
,pdata
, psbuf
->st_ex_btime
);
4215 map_info2_flags_from_sbuf(psbuf
, &file_flags
, &flags_mask
);
4216 SIVAL(pdata
, 0, file_flags
); /* flags */
4217 SIVAL(pdata
, 4, flags_mask
); /* mask */
4223 static NTSTATUS
marshall_stream_info(unsigned int num_streams
,
4224 const struct stream_struct
*streams
,
4226 unsigned int max_data_bytes
,
4227 unsigned int *data_size
)
4230 unsigned int ofs
= 0;
4232 if (max_data_bytes
< 32) {
4233 return NT_STATUS_INFO_LENGTH_MISMATCH
;
4236 for (i
= 0; i
< num_streams
; i
++) {
4237 unsigned int next_offset
;
4239 smb_ucs2_t
*namebuf
;
4241 if (!push_ucs2_talloc(talloc_tos(), &namebuf
,
4242 streams
[i
].name
, &namelen
) ||
4245 return NT_STATUS_INVALID_PARAMETER
;
4249 * name_buf is now null-terminated, we need to marshall as not
4256 * We cannot overflow ...
4258 if ((ofs
+ 24 + namelen
) > max_data_bytes
) {
4259 DEBUG(10, ("refusing to overflow reply at stream %u\n",
4261 TALLOC_FREE(namebuf
);
4262 return STATUS_BUFFER_OVERFLOW
;
4265 SIVAL(data
, ofs
+4, namelen
);
4266 SOFF_T(data
, ofs
+8, streams
[i
].size
);
4267 SOFF_T(data
, ofs
+16, streams
[i
].alloc_size
);
4268 memcpy(data
+ofs
+24, namebuf
, namelen
);
4269 TALLOC_FREE(namebuf
);
4271 next_offset
= ofs
+ 24 + namelen
;
4273 if (i
== num_streams
-1) {
4274 SIVAL(data
, ofs
, 0);
4277 unsigned int align
= ndr_align_size(next_offset
, 8);
4279 if ((next_offset
+ align
) > max_data_bytes
) {
4280 DEBUG(10, ("refusing to overflow align "
4281 "reply at stream %u\n",
4283 TALLOC_FREE(namebuf
);
4284 return STATUS_BUFFER_OVERFLOW
;
4287 memset(data
+next_offset
, 0, align
);
4288 next_offset
+= align
;
4290 SIVAL(data
, ofs
, next_offset
- ofs
);
4297 DEBUG(10, ("max_data: %u, data_size: %u\n", max_data_bytes
, ofs
));
4301 return NT_STATUS_OK
;
4304 /****************************************************************************
4305 Reply to a TRANSACT2_QFILEINFO on a PIPE !
4306 ****************************************************************************/
4308 static void call_trans2qpipeinfo(connection_struct
*conn
,
4309 struct smb_request
*req
,
4310 unsigned int tran_call
,
4311 char **pparams
, int total_params
,
4312 char **ppdata
, int total_data
,
4313 unsigned int max_data_bytes
)
4315 char *params
= *pparams
;
4316 char *pdata
= *ppdata
;
4317 unsigned int data_size
= 0;
4318 unsigned int param_size
= 2;
4323 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4327 if (total_params
< 4) {
4328 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4332 fsp
= file_fsp(req
, SVAL(params
,0));
4333 if (!fsp_is_np(fsp
)) {
4334 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
4338 info_level
= SVAL(params
,2);
4340 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
4341 if (*pparams
== NULL
) {
4342 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
4347 data_size
= max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
;
4348 *ppdata
= (char *)SMB_REALLOC(*ppdata
, data_size
);
4349 if (*ppdata
== NULL
) {
4350 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
4355 switch (info_level
) {
4356 case SMB_FILE_STANDARD_INFORMATION
:
4358 SOFF_T(pdata
,0,4096LL);
4365 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
4369 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, param_size
, *ppdata
, data_size
,
4375 NTSTATUS
smbd_do_qfilepathinfo(connection_struct
*conn
,
4376 TALLOC_CTX
*mem_ctx
,
4377 uint16_t info_level
,
4379 struct smb_filename
*smb_fname
,
4380 bool delete_pending
,
4381 struct timespec write_time_ts
,
4382 struct ea_list
*ea_list
,
4383 int lock_data_count
,
4386 unsigned int max_data_bytes
,
4387 size_t *fixed_portion
,
4389 unsigned int *pdata_size
)
4391 char *pdata
= *ppdata
;
4392 char *dstart
, *dend
;
4393 unsigned int data_size
;
4394 struct timespec create_time_ts
, mtime_ts
, atime_ts
, ctime_ts
;
4395 time_t create_time
, mtime
, atime
, c_time
;
4396 SMB_STRUCT_STAT
*psbuf
= &smb_fname
->st
;
4403 uint64_t file_size
= 0;
4405 uint64_t allocation_size
= 0;
4406 uint64_t file_index
= 0;
4407 uint32_t access_mask
= 0;
4409 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
4410 return NT_STATUS_INVALID_LEVEL
;
4413 DEBUG(5,("smbd_do_qfilepathinfo: %s (%s) level=%d max_data=%u\n",
4414 smb_fname_str_dbg(smb_fname
),
4416 info_level
, max_data_bytes
));
4418 mode
= dos_mode(conn
, smb_fname
);
4419 nlink
= psbuf
->st_ex_nlink
;
4421 if (nlink
&& (mode
&FILE_ATTRIBUTE_DIRECTORY
)) {
4425 if ((nlink
> 0) && delete_pending
) {
4429 data_size
= max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
;
4430 *ppdata
= (char *)SMB_REALLOC(*ppdata
, data_size
);
4431 if (*ppdata
== NULL
) {
4432 return NT_STATUS_NO_MEMORY
;
4436 dend
= dstart
+ data_size
- 1;
4438 if (!null_timespec(write_time_ts
) && !INFO_LEVEL_IS_UNIX(info_level
)) {
4439 update_stat_ex_mtime(psbuf
, write_time_ts
);
4442 create_time_ts
= get_create_timespec(conn
, fsp
, smb_fname
);
4443 mtime_ts
= psbuf
->st_ex_mtime
;
4444 atime_ts
= psbuf
->st_ex_atime
;
4445 ctime_ts
= get_change_timespec(conn
, fsp
, smb_fname
);
4447 if (lp_dos_filetime_resolution(SNUM(conn
))) {
4448 dos_filetime_timespec(&create_time_ts
);
4449 dos_filetime_timespec(&mtime_ts
);
4450 dos_filetime_timespec(&atime_ts
);
4451 dos_filetime_timespec(&ctime_ts
);
4454 create_time
= convert_timespec_to_time_t(create_time_ts
);
4455 mtime
= convert_timespec_to_time_t(mtime_ts
);
4456 atime
= convert_timespec_to_time_t(atime_ts
);
4457 c_time
= convert_timespec_to_time_t(ctime_ts
);
4459 p
= strrchr_m(smb_fname
->base_name
,'/');
4461 base_name
= smb_fname
->base_name
;
4465 /* NT expects the name to be in an exact form of the *full*
4466 filename. See the trans2 torture test */
4467 if (ISDOT(base_name
)) {
4468 dos_fname
= talloc_strdup(mem_ctx
, "\\");
4470 return NT_STATUS_NO_MEMORY
;
4473 dos_fname
= talloc_asprintf(mem_ctx
,
4475 smb_fname
->base_name
);
4477 return NT_STATUS_NO_MEMORY
;
4479 if (is_ntfs_stream_smb_fname(smb_fname
)) {
4480 dos_fname
= talloc_asprintf(dos_fname
, "%s",
4481 smb_fname
->stream_name
);
4483 return NT_STATUS_NO_MEMORY
;
4487 string_replace(dos_fname
, '/', '\\');
4490 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
, fsp
, psbuf
);
4493 /* Do we have this path open ? */
4495 struct file_id fileid
= vfs_file_id_from_sbuf(conn
, psbuf
);
4496 fsp1
= file_find_di_first(conn
->sconn
, fileid
);
4497 if (fsp1
&& fsp1
->initial_allocation_size
) {
4498 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
, fsp1
, psbuf
);
4502 if (!(mode
& FILE_ATTRIBUTE_DIRECTORY
)) {
4503 file_size
= get_file_size_stat(psbuf
);
4507 pos
= fsp
->fh
->position_information
;
4511 access_mask
= fsp
->access_mask
;
4513 /* GENERIC_EXECUTE mapping from Windows */
4514 access_mask
= 0x12019F;
4517 /* This should be an index number - looks like
4520 I think this causes us to fail the IFSKIT
4521 BasicFileInformationTest. -tpot */
4522 file_index
= get_FileIndex(conn
, psbuf
);
4526 switch (info_level
) {
4527 case SMB_INFO_STANDARD
:
4528 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4530 srv_put_dos_date2(pdata
,l1_fdateCreation
,create_time
);
4531 srv_put_dos_date2(pdata
,l1_fdateLastAccess
,atime
);
4532 srv_put_dos_date2(pdata
,l1_fdateLastWrite
,mtime
); /* write time */
4533 SIVAL(pdata
,l1_cbFile
,(uint32
)file_size
);
4534 SIVAL(pdata
,l1_cbFileAlloc
,(uint32
)allocation_size
);
4535 SSVAL(pdata
,l1_attrFile
,mode
);
4538 case SMB_INFO_QUERY_EA_SIZE
:
4540 unsigned int ea_size
=
4541 estimate_ea_size(conn
, fsp
,
4543 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4545 srv_put_dos_date2(pdata
,0,create_time
);
4546 srv_put_dos_date2(pdata
,4,atime
);
4547 srv_put_dos_date2(pdata
,8,mtime
); /* write time */
4548 SIVAL(pdata
,12,(uint32
)file_size
);
4549 SIVAL(pdata
,16,(uint32
)allocation_size
);
4550 SSVAL(pdata
,20,mode
);
4551 SIVAL(pdata
,22,ea_size
);
4555 case SMB_INFO_IS_NAME_VALID
:
4556 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4558 /* os/2 needs this ? really ?*/
4559 return NT_STATUS_DOS(ERRDOS
, ERRbadfunc
);
4561 /* This is only reached for qpathinfo */
4565 case SMB_INFO_QUERY_EAS_FROM_LIST
:
4567 size_t total_ea_len
= 0;
4568 struct ea_list
*ea_file_list
= NULL
;
4569 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4572 get_ea_list_from_file(mem_ctx
, conn
, fsp
,
4574 &total_ea_len
, &ea_file_list
);
4575 if (!NT_STATUS_IS_OK(status
)) {
4579 ea_list
= ea_list_union(ea_list
, ea_file_list
, &total_ea_len
);
4581 if (!ea_list
|| (total_ea_len
> data_size
)) {
4583 SIVAL(pdata
,0,4); /* EA List Length must be set to 4 if no EA's. */
4587 data_size
= fill_ea_buffer(mem_ctx
, pdata
, data_size
, conn
, ea_list
);
4591 case SMB_INFO_QUERY_ALL_EAS
:
4593 /* We have data_size bytes to put EA's into. */
4594 size_t total_ea_len
= 0;
4595 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4597 status
= get_ea_list_from_file(mem_ctx
, conn
, fsp
,
4599 &total_ea_len
, &ea_list
);
4600 if (!NT_STATUS_IS_OK(status
)) {
4604 if (!ea_list
|| (total_ea_len
> data_size
)) {
4606 SIVAL(pdata
,0,4); /* EA List Length must be set to 4 if no EA's. */
4610 data_size
= fill_ea_buffer(mem_ctx
, pdata
, data_size
, conn
, ea_list
);
4614 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
4616 /* This is FileFullEaInformation - 0xF which maps to
4617 * 1015 (decimal) in smbd_do_setfilepathinfo. */
4619 /* We have data_size bytes to put EA's into. */
4620 size_t total_ea_len
= 0;
4621 struct ea_list
*ea_file_list
= NULL
;
4623 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
4625 /*TODO: add filtering and index handling */
4628 get_ea_list_from_file(mem_ctx
, conn
, fsp
,
4630 &total_ea_len
, &ea_file_list
);
4631 if (!NT_STATUS_IS_OK(status
)) {
4634 if (!ea_file_list
) {
4635 return NT_STATUS_NO_EAS_ON_FILE
;
4638 status
= fill_ea_chained_buffer(mem_ctx
,
4642 conn
, ea_file_list
);
4643 if (!NT_STATUS_IS_OK(status
)) {
4649 case SMB_FILE_BASIC_INFORMATION
:
4650 case SMB_QUERY_FILE_BASIC_INFO
:
4652 if (info_level
== SMB_QUERY_FILE_BASIC_INFO
) {
4653 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4654 data_size
= 36; /* w95 returns 40 bytes not 36 - why ?. */
4656 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4660 put_long_date_timespec(conn
->ts_res
,pdata
,create_time_ts
);
4661 put_long_date_timespec(conn
->ts_res
,pdata
+8,atime_ts
);
4662 put_long_date_timespec(conn
->ts_res
,pdata
+16,mtime_ts
); /* write time */
4663 put_long_date_timespec(conn
->ts_res
,pdata
+24,ctime_ts
); /* change time */
4664 SIVAL(pdata
,32,mode
);
4666 DEBUG(5,("SMB_QFBI - "));
4667 DEBUG(5,("create: %s ", ctime(&create_time
)));
4668 DEBUG(5,("access: %s ", ctime(&atime
)));
4669 DEBUG(5,("write: %s ", ctime(&mtime
)));
4670 DEBUG(5,("change: %s ", ctime(&c_time
)));
4671 DEBUG(5,("mode: %x\n", mode
));
4672 *fixed_portion
= data_size
;
4675 case SMB_FILE_STANDARD_INFORMATION
:
4676 case SMB_QUERY_FILE_STANDARD_INFO
:
4678 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4680 SOFF_T(pdata
,0,allocation_size
);
4681 SOFF_T(pdata
,8,file_size
);
4682 SIVAL(pdata
,16,nlink
);
4683 SCVAL(pdata
,20,delete_pending
?1:0);
4684 SCVAL(pdata
,21,(mode
&FILE_ATTRIBUTE_DIRECTORY
)?1:0);
4685 SSVAL(pdata
,22,0); /* Padding. */
4686 *fixed_portion
= 24;
4689 case SMB_FILE_EA_INFORMATION
:
4690 case SMB_QUERY_FILE_EA_INFO
:
4692 unsigned int ea_size
=
4693 estimate_ea_size(conn
, fsp
, smb_fname
);
4694 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4697 SIVAL(pdata
,0,ea_size
);
4701 /* Get the 8.3 name - used if NT SMB was negotiated. */
4702 case SMB_QUERY_FILE_ALT_NAME_INFO
:
4703 case SMB_FILE_ALTERNATE_NAME_INFORMATION
:
4706 char mangled_name
[13];
4707 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4708 if (!name_to_8_3(base_name
,mangled_name
,
4709 True
,conn
->params
)) {
4710 return NT_STATUS_NO_MEMORY
;
4712 len
= srvstr_push(dstart
, flags2
,
4713 pdata
+4, mangled_name
,
4714 PTR_DIFF(dend
, pdata
+4),
4716 data_size
= 4 + len
;
4722 case SMB_QUERY_FILE_NAME_INFO
:
4726 this must be *exactly* right for ACLs on mapped drives to work
4728 len
= srvstr_push(dstart
, flags2
,
4730 PTR_DIFF(dend
, pdata
+4),
4732 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4733 data_size
= 4 + len
;
4738 case SMB_FILE_ALLOCATION_INFORMATION
:
4739 case SMB_QUERY_FILE_ALLOCATION_INFO
:
4740 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4742 SOFF_T(pdata
,0,allocation_size
);
4745 case SMB_FILE_END_OF_FILE_INFORMATION
:
4746 case SMB_QUERY_FILE_END_OF_FILEINFO
:
4747 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4749 SOFF_T(pdata
,0,file_size
);
4752 case SMB_QUERY_FILE_ALL_INFO
:
4753 case SMB_FILE_ALL_INFORMATION
:
4756 unsigned int ea_size
=
4757 estimate_ea_size(conn
, fsp
, smb_fname
);
4758 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4759 put_long_date_timespec(conn
->ts_res
,pdata
,create_time_ts
);
4760 put_long_date_timespec(conn
->ts_res
,pdata
+8,atime_ts
);
4761 put_long_date_timespec(conn
->ts_res
,pdata
+16,mtime_ts
); /* write time */
4762 put_long_date_timespec(conn
->ts_res
,pdata
+24,ctime_ts
); /* change time */
4763 SIVAL(pdata
,32,mode
);
4764 SIVAL(pdata
,36,0); /* padding. */
4766 SOFF_T(pdata
,0,allocation_size
);
4767 SOFF_T(pdata
,8,file_size
);
4768 SIVAL(pdata
,16,nlink
);
4769 SCVAL(pdata
,20,delete_pending
);
4770 SCVAL(pdata
,21,(mode
&FILE_ATTRIBUTE_DIRECTORY
)?1:0);
4773 SIVAL(pdata
,0,ea_size
);
4774 pdata
+= 4; /* EA info */
4775 len
= srvstr_push(dstart
, flags2
,
4777 PTR_DIFF(dend
, pdata
+4),
4781 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4782 *fixed_portion
= 10;
4786 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
4789 unsigned int ea_size
=
4790 estimate_ea_size(conn
, fsp
, smb_fname
);
4791 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
4792 put_long_date_timespec(conn
->ts_res
,pdata
+0x00,create_time_ts
);
4793 put_long_date_timespec(conn
->ts_res
,pdata
+0x08,atime_ts
);
4794 put_long_date_timespec(conn
->ts_res
,pdata
+0x10,mtime_ts
); /* write time */
4795 put_long_date_timespec(conn
->ts_res
,pdata
+0x18,ctime_ts
); /* change time */
4796 SIVAL(pdata
, 0x20, mode
);
4797 SIVAL(pdata
, 0x24, 0); /* padding. */
4798 SBVAL(pdata
, 0x28, allocation_size
);
4799 SBVAL(pdata
, 0x30, file_size
);
4800 SIVAL(pdata
, 0x38, nlink
);
4801 SCVAL(pdata
, 0x3C, delete_pending
);
4802 SCVAL(pdata
, 0x3D, (mode
&FILE_ATTRIBUTE_DIRECTORY
)?1:0);
4803 SSVAL(pdata
, 0x3E, 0); /* padding */
4804 SBVAL(pdata
, 0x40, file_index
);
4805 SIVAL(pdata
, 0x48, ea_size
);
4806 SIVAL(pdata
, 0x4C, access_mask
);
4807 SBVAL(pdata
, 0x50, pos
);
4808 SIVAL(pdata
, 0x58, mode
); /*TODO: mode != mode fix this!!! */
4809 SIVAL(pdata
, 0x5C, 0); /* No alignment needed. */
4813 len
= srvstr_push(dstart
, flags2
,
4815 PTR_DIFF(dend
, pdata
+4),
4819 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4820 *fixed_portion
= 104;
4823 case SMB_FILE_INTERNAL_INFORMATION
:
4825 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4826 SBVAL(pdata
, 0, file_index
);
4831 case SMB_FILE_ACCESS_INFORMATION
:
4832 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4833 SIVAL(pdata
, 0, access_mask
);
4838 case SMB_FILE_NAME_INFORMATION
:
4839 /* Pathname with leading '\'. */
4842 byte_len
= dos_PutUniCode(pdata
+4,dos_fname
,(size_t)max_data_bytes
,False
);
4843 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4844 SIVAL(pdata
,0,byte_len
);
4845 data_size
= 4 + byte_len
;
4849 case SMB_FILE_DISPOSITION_INFORMATION
:
4850 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4852 SCVAL(pdata
,0,delete_pending
);
4856 case SMB_FILE_POSITION_INFORMATION
:
4857 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4859 SOFF_T(pdata
,0,pos
);
4863 case SMB_FILE_MODE_INFORMATION
:
4864 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4865 SIVAL(pdata
,0,mode
);
4870 case SMB_FILE_ALIGNMENT_INFORMATION
:
4871 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4872 SIVAL(pdata
,0,0); /* No alignment needed. */
4878 * NT4 server just returns "invalid query" to this - if we try
4879 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4882 /* The first statement above is false - verified using Thursby
4883 * client against NT4 -- gcolley.
4885 case SMB_QUERY_FILE_STREAM_INFO
:
4886 case SMB_FILE_STREAM_INFORMATION
: {
4887 unsigned int num_streams
= 0;
4888 struct stream_struct
*streams
= NULL
;
4890 DEBUG(10,("smbd_do_qfilepathinfo: "
4891 "SMB_FILE_STREAM_INFORMATION\n"));
4893 if (is_ntfs_stream_smb_fname(smb_fname
)) {
4894 return NT_STATUS_INVALID_PARAMETER
;
4897 status
= vfs_streaminfo(conn
, fsp
, smb_fname
->base_name
,
4898 talloc_tos(), &num_streams
, &streams
);
4900 if (!NT_STATUS_IS_OK(status
)) {
4901 DEBUG(10, ("could not get stream info: %s\n",
4902 nt_errstr(status
)));
4906 status
= marshall_stream_info(num_streams
, streams
,
4907 pdata
, max_data_bytes
,
4910 if (!NT_STATUS_IS_OK(status
)) {
4911 DEBUG(10, ("marshall_stream_info failed: %s\n",
4912 nt_errstr(status
)));
4913 TALLOC_FREE(streams
);
4917 TALLOC_FREE(streams
);
4919 *fixed_portion
= 32;
4923 case SMB_QUERY_COMPRESSION_INFO
:
4924 case SMB_FILE_COMPRESSION_INFORMATION
:
4925 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4926 SOFF_T(pdata
,0,file_size
);
4927 SIVAL(pdata
,8,0); /* ??? */
4928 SIVAL(pdata
,12,0); /* ??? */
4930 *fixed_portion
= 16;
4933 case SMB_FILE_NETWORK_OPEN_INFORMATION
:
4934 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4935 put_long_date_timespec(conn
->ts_res
,pdata
,create_time_ts
);
4936 put_long_date_timespec(conn
->ts_res
,pdata
+8,atime_ts
);
4937 put_long_date_timespec(conn
->ts_res
,pdata
+16,mtime_ts
); /* write time */
4938 put_long_date_timespec(conn
->ts_res
,pdata
+24,ctime_ts
); /* change time */
4939 SOFF_T(pdata
,32,allocation_size
);
4940 SOFF_T(pdata
,40,file_size
);
4941 SIVAL(pdata
,48,mode
);
4942 SIVAL(pdata
,52,0); /* ??? */
4944 *fixed_portion
= 56;
4947 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION
:
4948 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4949 SIVAL(pdata
,0,mode
);
4956 * CIFS UNIX Extensions.
4959 case SMB_QUERY_FILE_UNIX_BASIC
:
4961 pdata
= store_file_unix_basic(conn
, pdata
, fsp
, psbuf
);
4962 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4964 DEBUG(4,("smbd_do_qfilepathinfo: "
4965 "SMB_QUERY_FILE_UNIX_BASIC\n"));
4966 dump_data(4, (uint8_t *)(*ppdata
), data_size
);
4970 case SMB_QUERY_FILE_UNIX_INFO2
:
4972 pdata
= store_file_unix_basic_info2(conn
, pdata
, fsp
, psbuf
);
4973 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4977 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4979 for (i
=0; i
<100; i
++)
4980 DEBUG(4,("%d=%x, ",i
, (*ppdata
)[i
]));
4986 case SMB_QUERY_FILE_UNIX_LINK
:
4989 char *buffer
= talloc_array(mem_ctx
, char, PATH_MAX
+1);
4992 return NT_STATUS_NO_MEMORY
;
4995 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4997 if(!S_ISLNK(psbuf
->st_ex_mode
)) {
4998 return NT_STATUS_DOS(ERRSRV
, ERRbadlink
);
5001 return NT_STATUS_DOS(ERRDOS
, ERRbadlink
);
5003 len
= SMB_VFS_READLINK(conn
,
5004 smb_fname
->base_name
,
5007 return map_nt_error_from_unix(errno
);
5010 len
= srvstr_push(dstart
, flags2
,
5012 PTR_DIFF(dend
, pdata
),
5015 data_size
= PTR_DIFF(pdata
,(*ppdata
));
5020 #if defined(HAVE_POSIX_ACLS)
5021 case SMB_QUERY_POSIX_ACL
:
5023 SMB_ACL_T file_acl
= NULL
;
5024 SMB_ACL_T def_acl
= NULL
;
5025 uint16 num_file_acls
= 0;
5026 uint16 num_def_acls
= 0;
5028 if (fsp
&& fsp
->fh
->fd
!= -1) {
5029 file_acl
= SMB_VFS_SYS_ACL_GET_FD(fsp
,
5033 SMB_VFS_SYS_ACL_GET_FILE(conn
,
5034 smb_fname
->base_name
,
5035 SMB_ACL_TYPE_ACCESS
,
5039 if (file_acl
== NULL
&& no_acl_syscall_error(errno
)) {
5040 DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
5041 "not implemented on "
5042 "filesystem containing %s\n",
5043 smb_fname
->base_name
));
5044 return NT_STATUS_NOT_IMPLEMENTED
;
5047 if (S_ISDIR(psbuf
->st_ex_mode
)) {
5048 if (fsp
&& fsp
->is_directory
) {
5050 SMB_VFS_SYS_ACL_GET_FILE(
5052 fsp
->fsp_name
->base_name
,
5053 SMB_ACL_TYPE_DEFAULT
,
5057 SMB_VFS_SYS_ACL_GET_FILE(
5059 smb_fname
->base_name
,
5060 SMB_ACL_TYPE_DEFAULT
,
5063 def_acl
= free_empty_sys_acl(conn
, def_acl
);
5066 num_file_acls
= count_acl_entries(conn
, file_acl
);
5067 num_def_acls
= count_acl_entries(conn
, def_acl
);
5069 if ( data_size
< (num_file_acls
+ num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
+ SMB_POSIX_ACL_HEADER_SIZE
) {
5070 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
5072 (unsigned int)((num_file_acls
+ num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
+
5073 SMB_POSIX_ACL_HEADER_SIZE
) ));
5075 TALLOC_FREE(file_acl
);
5078 TALLOC_FREE(def_acl
);
5080 return NT_STATUS_BUFFER_TOO_SMALL
;
5083 SSVAL(pdata
,0,SMB_POSIX_ACL_VERSION
);
5084 SSVAL(pdata
,2,num_file_acls
);
5085 SSVAL(pdata
,4,num_def_acls
);
5086 if (!marshall_posix_acl(conn
, pdata
+ SMB_POSIX_ACL_HEADER_SIZE
, psbuf
, file_acl
)) {
5088 TALLOC_FREE(file_acl
);
5091 TALLOC_FREE(def_acl
);
5093 return NT_STATUS_INTERNAL_ERROR
;
5095 if (!marshall_posix_acl(conn
, pdata
+ SMB_POSIX_ACL_HEADER_SIZE
+ (num_file_acls
*SMB_POSIX_ACL_ENTRY_SIZE
), psbuf
, def_acl
)) {
5097 TALLOC_FREE(file_acl
);
5100 TALLOC_FREE(def_acl
);
5102 return NT_STATUS_INTERNAL_ERROR
;
5106 TALLOC_FREE(file_acl
);
5109 TALLOC_FREE(def_acl
);
5111 data_size
= (num_file_acls
+ num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
+ SMB_POSIX_ACL_HEADER_SIZE
;
5117 case SMB_QUERY_POSIX_LOCK
:
5122 enum brl_type lock_type
;
5124 /* We need an open file with a real fd for this. */
5125 if (!fsp
|| fsp
->fh
->fd
== -1) {
5126 return NT_STATUS_INVALID_LEVEL
;
5129 if (lock_data_count
!= POSIX_LOCK_DATA_SIZE
) {
5130 return NT_STATUS_INVALID_PARAMETER
;
5133 switch (SVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
)) {
5134 case POSIX_LOCK_TYPE_READ
:
5135 lock_type
= READ_LOCK
;
5137 case POSIX_LOCK_TYPE_WRITE
:
5138 lock_type
= WRITE_LOCK
;
5140 case POSIX_LOCK_TYPE_UNLOCK
:
5142 /* There's no point in asking for an unlock... */
5143 return NT_STATUS_INVALID_PARAMETER
;
5146 smblctx
= (uint64_t)IVAL(pdata
, POSIX_LOCK_PID_OFFSET
);
5147 #if defined(HAVE_LONGLONG)
5148 offset
= (((uint64_t) IVAL(pdata
,(POSIX_LOCK_START_OFFSET
+4))) << 32) |
5149 ((uint64_t) IVAL(pdata
,POSIX_LOCK_START_OFFSET
));
5150 count
= (((uint64_t) IVAL(pdata
,(POSIX_LOCK_LEN_OFFSET
+4))) << 32) |
5151 ((uint64_t) IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
));
5152 #else /* HAVE_LONGLONG */
5153 offset
= (uint64_t)IVAL(pdata
,POSIX_LOCK_START_OFFSET
);
5154 count
= (uint64_t)IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
);
5155 #endif /* HAVE_LONGLONG */
5157 status
= query_lock(fsp
,
5164 if (ERROR_WAS_LOCK_DENIED(status
)) {
5165 /* Here we need to report who has it locked... */
5166 data_size
= POSIX_LOCK_DATA_SIZE
;
5168 SSVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
, lock_type
);
5169 SSVAL(pdata
, POSIX_LOCK_FLAGS_OFFSET
, 0);
5170 SIVAL(pdata
, POSIX_LOCK_PID_OFFSET
, (uint32_t)smblctx
);
5171 #if defined(HAVE_LONGLONG)
5172 SIVAL(pdata
, POSIX_LOCK_START_OFFSET
, (uint32
)(offset
& 0xFFFFFFFF));
5173 SIVAL(pdata
, POSIX_LOCK_START_OFFSET
+ 4, (uint32
)((offset
>> 32) & 0xFFFFFFFF));
5174 SIVAL(pdata
, POSIX_LOCK_LEN_OFFSET
, (uint32
)(count
& 0xFFFFFFFF));
5175 SIVAL(pdata
, POSIX_LOCK_LEN_OFFSET
+ 4, (uint32
)((count
>> 32) & 0xFFFFFFFF));
5176 #else /* HAVE_LONGLONG */
5177 SIVAL(pdata
, POSIX_LOCK_START_OFFSET
, offset
);
5178 SIVAL(pdata
, POSIX_LOCK_LEN_OFFSET
, count
);
5179 #endif /* HAVE_LONGLONG */
5181 } else if (NT_STATUS_IS_OK(status
)) {
5182 /* For success we just return a copy of what we sent
5183 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
5184 data_size
= POSIX_LOCK_DATA_SIZE
;
5185 memcpy(pdata
, lock_data
, POSIX_LOCK_DATA_SIZE
);
5186 SSVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
, POSIX_LOCK_TYPE_UNLOCK
);
5194 return NT_STATUS_INVALID_LEVEL
;
5197 *pdata_size
= data_size
;
5198 return NT_STATUS_OK
;
5201 /****************************************************************************
5202 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
5203 file name or file id).
5204 ****************************************************************************/
5206 static void call_trans2qfilepathinfo(connection_struct
*conn
,
5207 struct smb_request
*req
,
5208 unsigned int tran_call
,
5209 char **pparams
, int total_params
,
5210 char **ppdata
, int total_data
,
5211 unsigned int max_data_bytes
)
5213 char *params
= *pparams
;
5214 char *pdata
= *ppdata
;
5216 unsigned int data_size
= 0;
5217 unsigned int param_size
= 2;
5218 struct smb_filename
*smb_fname
= NULL
;
5219 bool delete_pending
= False
;
5220 struct timespec write_time_ts
;
5221 files_struct
*fsp
= NULL
;
5222 struct file_id fileid
;
5223 struct ea_list
*ea_list
= NULL
;
5224 int lock_data_count
= 0;
5225 char *lock_data
= NULL
;
5226 size_t fixed_portion
;
5227 NTSTATUS status
= NT_STATUS_OK
;
5230 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5234 ZERO_STRUCT(write_time_ts
);
5236 if (tran_call
== TRANSACT2_QFILEINFO
) {
5237 if (total_params
< 4) {
5238 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5243 call_trans2qpipeinfo(conn
, req
, tran_call
,
5244 pparams
, total_params
,
5250 fsp
= file_fsp(req
, SVAL(params
,0));
5251 info_level
= SVAL(params
,2);
5253 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level
));
5255 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
5256 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
5260 /* Initial check for valid fsp ptr. */
5261 if (!check_fsp_open(conn
, req
, fsp
)) {
5265 smb_fname
= cp_smb_filename(talloc_tos(), fsp
->fsp_name
);
5266 if (smb_fname
== NULL
) {
5267 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5271 if(fsp
->fake_file_handle
) {
5273 * This is actually for the QUOTA_FAKE_FILE --metze
5276 /* We know this name is ok, it's already passed the checks. */
5278 } else if(fsp
->fh
->fd
== -1) {
5280 * This is actually a QFILEINFO on a directory
5281 * handle (returned from an NT SMB). NT5.0 seems
5282 * to do this call. JRA.
5285 if (INFO_LEVEL_IS_UNIX(info_level
)) {
5286 /* Always do lstat for UNIX calls. */
5287 if (SMB_VFS_LSTAT(conn
, smb_fname
)) {
5288 DEBUG(3,("call_trans2qfilepathinfo: "
5289 "SMB_VFS_LSTAT of %s failed "
5291 smb_fname_str_dbg(smb_fname
),
5294 map_nt_error_from_unix(errno
));
5297 } else if (SMB_VFS_STAT(conn
, smb_fname
)) {
5298 DEBUG(3,("call_trans2qfilepathinfo: "
5299 "SMB_VFS_STAT of %s failed (%s)\n",
5300 smb_fname_str_dbg(smb_fname
),
5303 map_nt_error_from_unix(errno
));
5307 fileid
= vfs_file_id_from_sbuf(conn
, &smb_fname
->st
);
5308 get_file_infos(fileid
, fsp
->name_hash
, &delete_pending
, &write_time_ts
);
5311 * Original code - this is an open file.
5313 if (SMB_VFS_FSTAT(fsp
, &smb_fname
->st
) != 0) {
5314 DEBUG(3, ("fstat of %s failed (%s)\n",
5315 fsp_fnum_dbg(fsp
), strerror(errno
)));
5317 map_nt_error_from_unix(errno
));
5320 fileid
= vfs_file_id_from_sbuf(conn
, &smb_fname
->st
);
5321 get_file_infos(fileid
, fsp
->name_hash
, &delete_pending
, &write_time_ts
);
5327 uint32_t ucf_flags
= 0;
5330 if (total_params
< 7) {
5331 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5335 info_level
= SVAL(params
,0);
5337 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level
));
5339 if (INFO_LEVEL_IS_UNIX(info_level
)) {
5340 if (!lp_unix_extensions()) {
5341 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
5344 if (info_level
== SMB_QUERY_FILE_UNIX_BASIC
||
5345 info_level
== SMB_QUERY_FILE_UNIX_INFO2
||
5346 info_level
== SMB_QUERY_FILE_UNIX_LINK
) {
5347 ucf_flags
|= UCF_UNIX_NAME_LOOKUP
;
5351 srvstr_get_path(req
, params
, req
->flags2
, &fname
, ¶ms
[6],
5353 STR_TERMINATE
, &status
);
5354 if (!NT_STATUS_IS_OK(status
)) {
5355 reply_nterror(req
, status
);
5359 status
= filename_convert(req
,
5361 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
5366 if (!NT_STATUS_IS_OK(status
)) {
5367 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
5368 reply_botherror(req
,
5369 NT_STATUS_PATH_NOT_COVERED
,
5370 ERRSRV
, ERRbadpath
);
5373 reply_nterror(req
, status
);
5377 /* If this is a stream, check if there is a delete_pending. */
5378 if ((conn
->fs_capabilities
& FILE_NAMED_STREAMS
)
5379 && is_ntfs_stream_smb_fname(smb_fname
)) {
5380 struct smb_filename
*smb_fname_base
;
5382 /* Create an smb_filename with stream_name == NULL. */
5383 smb_fname_base
= synthetic_smb_fname(
5384 talloc_tos(), smb_fname
->base_name
,
5386 if (smb_fname_base
== NULL
) {
5387 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5391 if (INFO_LEVEL_IS_UNIX(info_level
)) {
5392 /* Always do lstat for UNIX calls. */
5393 if (SMB_VFS_LSTAT(conn
, smb_fname_base
) != 0) {
5394 DEBUG(3,("call_trans2qfilepathinfo: "
5395 "SMB_VFS_LSTAT of %s failed "
5397 smb_fname_str_dbg(smb_fname_base
),
5399 TALLOC_FREE(smb_fname_base
);
5401 map_nt_error_from_unix(errno
));
5405 if (SMB_VFS_STAT(conn
, smb_fname_base
) != 0) {
5406 DEBUG(3,("call_trans2qfilepathinfo: "
5407 "fileinfo of %s failed "
5409 smb_fname_str_dbg(smb_fname_base
),
5411 TALLOC_FREE(smb_fname_base
);
5413 map_nt_error_from_unix(errno
));
5418 status
= file_name_hash(conn
,
5419 smb_fname_str_dbg(smb_fname_base
),
5421 if (!NT_STATUS_IS_OK(status
)) {
5422 TALLOC_FREE(smb_fname_base
);
5423 reply_nterror(req
, status
);
5427 fileid
= vfs_file_id_from_sbuf(conn
,
5428 &smb_fname_base
->st
);
5429 TALLOC_FREE(smb_fname_base
);
5430 get_file_infos(fileid
, name_hash
, &delete_pending
, NULL
);
5431 if (delete_pending
) {
5432 reply_nterror(req
, NT_STATUS_DELETE_PENDING
);
5437 if (INFO_LEVEL_IS_UNIX(info_level
)) {
5438 /* Always do lstat for UNIX calls. */
5439 if (SMB_VFS_LSTAT(conn
, smb_fname
)) {
5440 DEBUG(3,("call_trans2qfilepathinfo: "
5441 "SMB_VFS_LSTAT of %s failed (%s)\n",
5442 smb_fname_str_dbg(smb_fname
),
5445 map_nt_error_from_unix(errno
));
5450 if (SMB_VFS_STAT(conn
, smb_fname
) != 0) {
5451 DEBUG(3,("call_trans2qfilepathinfo: "
5452 "SMB_VFS_STAT of %s failed (%s)\n",
5453 smb_fname_str_dbg(smb_fname
),
5456 map_nt_error_from_unix(errno
));
5461 status
= file_name_hash(conn
,
5462 smb_fname_str_dbg(smb_fname
),
5464 if (!NT_STATUS_IS_OK(status
)) {
5465 reply_nterror(req
, status
);
5469 fileid
= vfs_file_id_from_sbuf(conn
, &smb_fname
->st
);
5470 get_file_infos(fileid
, name_hash
, &delete_pending
, &write_time_ts
);
5471 if (delete_pending
) {
5472 reply_nterror(req
, NT_STATUS_DELETE_PENDING
);
5477 DEBUG(3,("call_trans2qfilepathinfo %s (%s) level=%d call=%d "
5478 "total_data=%d\n", smb_fname_str_dbg(smb_fname
),
5480 info_level
,tran_call
,total_data
));
5482 /* Pull out any data sent here before we realloc. */
5483 switch (info_level
) {
5484 case SMB_INFO_QUERY_EAS_FROM_LIST
:
5486 /* Pull any EA list from the data portion. */
5489 if (total_data
< 4) {
5491 req
, NT_STATUS_INVALID_PARAMETER
);
5494 ea_size
= IVAL(pdata
,0);
5496 if (total_data
> 0 && ea_size
!= total_data
) {
5497 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5498 total_data=%u (should be %u)\n", (unsigned int)total_data
, (unsigned int)IVAL(pdata
,0) ));
5500 req
, NT_STATUS_INVALID_PARAMETER
);
5504 if (!lp_ea_support(SNUM(conn
))) {
5505 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
5509 /* Pull out the list of names. */
5510 ea_list
= read_ea_name_list(req
, pdata
+ 4, ea_size
- 4);
5513 req
, NT_STATUS_INVALID_PARAMETER
);
5519 case SMB_QUERY_POSIX_LOCK
:
5521 if (fsp
== NULL
|| fsp
->fh
->fd
== -1) {
5522 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
5526 if (total_data
!= POSIX_LOCK_DATA_SIZE
) {
5528 req
, NT_STATUS_INVALID_PARAMETER
);
5532 /* Copy the lock range data. */
5533 lock_data
= (char *)talloc_memdup(
5534 req
, pdata
, total_data
);
5536 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5539 lock_data_count
= total_data
;
5545 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
5546 if (*pparams
== NULL
) {
5547 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5554 * draft-leach-cifs-v1-spec-02.txt
5555 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
5558 * The requested information is placed in the Data portion of the
5559 * transaction response. For the information levels greater than 0x100,
5560 * the transaction response has 1 parameter word which should be
5561 * ignored by the client.
5563 * However Windows only follows this rule for the IS_NAME_VALID call.
5565 switch (info_level
) {
5566 case SMB_INFO_IS_NAME_VALID
:
5571 if ((info_level
& 0xFF00) == 0xFF00) {
5573 * We use levels that start with 0xFF00
5574 * internally to represent SMB2 specific levels
5576 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
5580 status
= smbd_do_qfilepathinfo(conn
, req
, info_level
,
5582 delete_pending
, write_time_ts
,
5584 lock_data_count
, lock_data
,
5585 req
->flags2
, max_data_bytes
,
5587 ppdata
, &data_size
);
5588 if (!NT_STATUS_IS_OK(status
)) {
5589 reply_nterror(req
, status
);
5592 if (fixed_portion
> max_data_bytes
) {
5593 reply_nterror(req
, NT_STATUS_INFO_LENGTH_MISMATCH
);
5597 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, param_size
, *ppdata
, data_size
,
5603 /****************************************************************************
5604 Set a hard link (called by UNIX extensions and by NT rename with HARD link
5606 ****************************************************************************/
5608 NTSTATUS
hardlink_internals(TALLOC_CTX
*ctx
,
5609 connection_struct
*conn
,
5610 struct smb_request
*req
,
5611 bool overwrite_if_exists
,
5612 const struct smb_filename
*smb_fname_old
,
5613 struct smb_filename
*smb_fname_new
)
5615 NTSTATUS status
= NT_STATUS_OK
;
5617 /* source must already exist. */
5618 if (!VALID_STAT(smb_fname_old
->st
)) {
5619 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5622 if (VALID_STAT(smb_fname_new
->st
)) {
5623 if (overwrite_if_exists
) {
5624 if (S_ISDIR(smb_fname_new
->st
.st_ex_mode
)) {
5625 return NT_STATUS_FILE_IS_A_DIRECTORY
;
5627 status
= unlink_internals(conn
,
5629 FILE_ATTRIBUTE_NORMAL
,
5632 if (!NT_STATUS_IS_OK(status
)) {
5636 /* Disallow if newname already exists. */
5637 return NT_STATUS_OBJECT_NAME_COLLISION
;
5641 /* No links from a directory. */
5642 if (S_ISDIR(smb_fname_old
->st
.st_ex_mode
)) {
5643 return NT_STATUS_FILE_IS_A_DIRECTORY
;
5646 /* Setting a hardlink to/from a stream isn't currently supported. */
5647 if (is_ntfs_stream_smb_fname(smb_fname_old
) ||
5648 is_ntfs_stream_smb_fname(smb_fname_new
)) {
5649 return NT_STATUS_INVALID_PARAMETER
;
5652 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
5653 smb_fname_old
->base_name
, smb_fname_new
->base_name
));
5655 if (SMB_VFS_LINK(conn
, smb_fname_old
->base_name
,
5656 smb_fname_new
->base_name
) != 0) {
5657 status
= map_nt_error_from_unix(errno
);
5658 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
5659 nt_errstr(status
), smb_fname_old
->base_name
,
5660 smb_fname_new
->base_name
));
5665 /****************************************************************************
5666 Deal with setting the time from any of the setfilepathinfo functions.
5667 NOTE !!!! The check for FILE_WRITE_ATTRIBUTES access must be done *before*
5668 calling this function.
5669 ****************************************************************************/
5671 NTSTATUS
smb_set_file_time(connection_struct
*conn
,
5673 const struct smb_filename
*smb_fname
,
5674 struct smb_file_time
*ft
,
5675 bool setting_write_time
)
5677 struct smb_filename smb_fname_base
;
5679 FILE_NOTIFY_CHANGE_LAST_ACCESS
5680 |FILE_NOTIFY_CHANGE_LAST_WRITE
5681 |FILE_NOTIFY_CHANGE_CREATION
;
5683 if (!VALID_STAT(smb_fname
->st
)) {
5684 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5687 /* get some defaults (no modifications) if any info is zero or -1. */
5688 if (null_timespec(ft
->create_time
)) {
5689 action
&= ~FILE_NOTIFY_CHANGE_CREATION
;
5692 if (null_timespec(ft
->atime
)) {
5693 action
&= ~FILE_NOTIFY_CHANGE_LAST_ACCESS
;
5696 if (null_timespec(ft
->mtime
)) {
5697 action
&= ~FILE_NOTIFY_CHANGE_LAST_WRITE
;
5700 if (!setting_write_time
) {
5701 /* ft->mtime comes from change time, not write time. */
5702 action
&= ~FILE_NOTIFY_CHANGE_LAST_WRITE
;
5705 /* Ensure the resolution is the correct for
5706 * what we can store on this filesystem. */
5708 round_timespec(conn
->ts_res
, &ft
->create_time
);
5709 round_timespec(conn
->ts_res
, &ft
->ctime
);
5710 round_timespec(conn
->ts_res
, &ft
->atime
);
5711 round_timespec(conn
->ts_res
, &ft
->mtime
);
5713 DEBUG(5,("smb_set_filetime: actime: %s\n ",
5714 time_to_asc(convert_timespec_to_time_t(ft
->atime
))));
5715 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
5716 time_to_asc(convert_timespec_to_time_t(ft
->mtime
))));
5717 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
5718 time_to_asc(convert_timespec_to_time_t(ft
->ctime
))));
5719 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
5720 time_to_asc(convert_timespec_to_time_t(ft
->create_time
))));
5722 if (setting_write_time
) {
5724 * This was a Windows setfileinfo on an open file.
5725 * NT does this a lot. We also need to
5726 * set the time here, as it can be read by
5727 * FindFirst/FindNext and with the patch for bug #2045
5728 * in smbd/fileio.c it ensures that this timestamp is
5729 * kept sticky even after a write. We save the request
5730 * away and will set it on file close and after a write. JRA.
5733 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
5734 time_to_asc(convert_timespec_to_time_t(ft
->mtime
))));
5737 if (fsp
->base_fsp
) {
5738 set_sticky_write_time_fsp(fsp
->base_fsp
,
5741 set_sticky_write_time_fsp(fsp
, ft
->mtime
);
5744 set_sticky_write_time_path(
5745 vfs_file_id_from_sbuf(conn
, &smb_fname
->st
),
5750 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5752 /* Always call ntimes on the base, even if a stream was passed in. */
5753 smb_fname_base
= *smb_fname
;
5754 smb_fname_base
.stream_name
= NULL
;
5756 if(file_ntimes(conn
, &smb_fname_base
, ft
)!=0) {
5757 return map_nt_error_from_unix(errno
);
5760 notify_fname(conn
, NOTIFY_ACTION_MODIFIED
, action
,
5761 smb_fname
->base_name
);
5762 return NT_STATUS_OK
;
5765 /****************************************************************************
5766 Deal with setting the dosmode from any of the setfilepathinfo functions.
5767 NB. The check for FILE_WRITE_ATTRIBUTES access on this path must have been
5768 done before calling this function.
5769 ****************************************************************************/
5771 static NTSTATUS
smb_set_file_dosmode(connection_struct
*conn
,
5772 const struct smb_filename
*smb_fname
,
5775 struct smb_filename
*smb_fname_base
;
5778 if (!VALID_STAT(smb_fname
->st
)) {
5779 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5782 /* Always operate on the base_name, even if a stream was passed in. */
5783 smb_fname_base
= synthetic_smb_fname(
5784 talloc_tos(), smb_fname
->base_name
, NULL
, &smb_fname
->st
);
5785 if (smb_fname_base
== NULL
) {
5786 return NT_STATUS_NO_MEMORY
;
5790 if (S_ISDIR(smb_fname_base
->st
.st_ex_mode
)) {
5791 dosmode
|= FILE_ATTRIBUTE_DIRECTORY
;
5793 dosmode
&= ~FILE_ATTRIBUTE_DIRECTORY
;
5797 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode
));
5799 /* check the mode isn't different, before changing it */
5800 if ((dosmode
!= 0) && (dosmode
!= dos_mode(conn
, smb_fname_base
))) {
5801 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
5802 "0x%x\n", smb_fname_str_dbg(smb_fname_base
),
5803 (unsigned int)dosmode
));
5805 if(file_set_dosmode(conn
, smb_fname_base
, dosmode
, NULL
,
5807 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
5809 smb_fname_str_dbg(smb_fname_base
),
5811 status
= map_nt_error_from_unix(errno
);
5815 status
= NT_STATUS_OK
;
5817 TALLOC_FREE(smb_fname_base
);
5821 /****************************************************************************
5822 Deal with setting the size from any of the setfilepathinfo functions.
5823 ****************************************************************************/
5825 static NTSTATUS
smb_set_file_size(connection_struct
*conn
,
5826 struct smb_request
*req
,
5828 const struct smb_filename
*smb_fname
,
5829 const SMB_STRUCT_STAT
*psbuf
,
5831 bool fail_after_createfile
)
5833 NTSTATUS status
= NT_STATUS_OK
;
5834 struct smb_filename
*smb_fname_tmp
= NULL
;
5835 files_struct
*new_fsp
= NULL
;
5837 if (!VALID_STAT(*psbuf
)) {
5838 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5841 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size
));
5843 if (size
== get_file_size_stat(psbuf
)) {
5844 return NT_STATUS_OK
;
5847 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5848 smb_fname_str_dbg(smb_fname
), (double)size
));
5850 if (fsp
&& fsp
->fh
->fd
!= -1) {
5851 /* Handle based call. */
5852 if (!(fsp
->access_mask
& FILE_WRITE_DATA
)) {
5853 return NT_STATUS_ACCESS_DENIED
;
5856 if (vfs_set_filelen(fsp
, size
) == -1) {
5857 return map_nt_error_from_unix(errno
);
5859 trigger_write_time_update_immediate(fsp
);
5860 return NT_STATUS_OK
;
5863 smb_fname_tmp
= cp_smb_filename(talloc_tos(), smb_fname
);
5864 if (smb_fname_tmp
== NULL
) {
5865 return NT_STATUS_NO_MEMORY
;
5868 smb_fname_tmp
->st
= *psbuf
;
5870 status
= SMB_VFS_CREATE_FILE(
5873 0, /* root_dir_fid */
5874 smb_fname_tmp
, /* fname */
5875 FILE_WRITE_DATA
, /* access_mask */
5876 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
5878 FILE_OPEN
, /* create_disposition*/
5879 0, /* create_options */
5880 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
5881 FORCE_OPLOCK_BREAK_TO_NONE
, /* oplock_request */
5882 0, /* allocation_size */
5883 0, /* private_flags */
5886 &new_fsp
, /* result */
5889 TALLOC_FREE(smb_fname_tmp
);
5891 if (!NT_STATUS_IS_OK(status
)) {
5892 /* NB. We check for open_was_deferred in the caller. */
5896 /* See RAW-SFILEINFO-END-OF-FILE */
5897 if (fail_after_createfile
) {
5898 close_file(req
, new_fsp
,NORMAL_CLOSE
);
5899 return NT_STATUS_INVALID_LEVEL
;
5902 if (vfs_set_filelen(new_fsp
, size
) == -1) {
5903 status
= map_nt_error_from_unix(errno
);
5904 close_file(req
, new_fsp
,NORMAL_CLOSE
);
5908 trigger_write_time_update_immediate(new_fsp
);
5909 close_file(req
, new_fsp
,NORMAL_CLOSE
);
5910 return NT_STATUS_OK
;
5913 /****************************************************************************
5914 Deal with SMB_INFO_SET_EA.
5915 ****************************************************************************/
5917 static NTSTATUS
smb_info_set_ea(connection_struct
*conn
,
5921 const struct smb_filename
*smb_fname
)
5923 struct ea_list
*ea_list
= NULL
;
5924 TALLOC_CTX
*ctx
= NULL
;
5925 NTSTATUS status
= NT_STATUS_OK
;
5927 if (total_data
< 10) {
5929 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5930 length. They seem to have no effect. Bug #3212. JRA */
5932 if ((total_data
== 4) && (IVAL(pdata
,0) == 4)) {
5933 /* We're done. We only get EA info in this call. */
5934 return NT_STATUS_OK
;
5937 return NT_STATUS_INVALID_PARAMETER
;
5940 if (IVAL(pdata
,0) > total_data
) {
5941 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5942 IVAL(pdata
,0), (unsigned int)total_data
));
5943 return NT_STATUS_INVALID_PARAMETER
;
5947 ea_list
= read_ea_list(ctx
, pdata
+ 4, total_data
- 4);
5949 return NT_STATUS_INVALID_PARAMETER
;
5952 status
= set_ea(conn
, fsp
, smb_fname
, ea_list
);
5957 /****************************************************************************
5958 Deal with SMB_FILE_FULL_EA_INFORMATION set.
5959 ****************************************************************************/
5961 static NTSTATUS
smb_set_file_full_ea_info(connection_struct
*conn
,
5966 struct ea_list
*ea_list
= NULL
;
5970 return NT_STATUS_INVALID_HANDLE
;
5973 if (!lp_ea_support(SNUM(conn
))) {
5974 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
5975 "EA's not supported.\n",
5976 (unsigned int)total_data
));
5977 return NT_STATUS_EAS_NOT_SUPPORTED
;
5980 if (total_data
< 10) {
5981 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
5983 (unsigned int)total_data
));
5984 return NT_STATUS_INVALID_PARAMETER
;
5987 ea_list
= read_nttrans_ea_list(talloc_tos(),
5992 return NT_STATUS_INVALID_PARAMETER
;
5995 status
= set_ea(conn
, fsp
, fsp
->fsp_name
, ea_list
);
5997 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
5998 smb_fname_str_dbg(fsp
->fsp_name
),
5999 nt_errstr(status
) ));
6005 /****************************************************************************
6006 Deal with SMB_SET_FILE_DISPOSITION_INFO.
6007 ****************************************************************************/
6009 static NTSTATUS
smb_set_file_disposition_info(connection_struct
*conn
,
6013 struct smb_filename
*smb_fname
)
6015 NTSTATUS status
= NT_STATUS_OK
;
6016 bool delete_on_close
;
6019 if (total_data
< 1) {
6020 return NT_STATUS_INVALID_PARAMETER
;
6024 return NT_STATUS_INVALID_HANDLE
;
6027 delete_on_close
= (CVAL(pdata
,0) ? True
: False
);
6028 dosmode
= dos_mode(conn
, smb_fname
);
6030 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
6031 "delete_on_close = %u\n",
6032 smb_fname_str_dbg(smb_fname
),
6033 (unsigned int)dosmode
,
6034 (unsigned int)delete_on_close
));
6036 if (delete_on_close
) {
6037 status
= can_set_delete_on_close(fsp
, dosmode
);
6038 if (!NT_STATUS_IS_OK(status
)) {
6043 /* The set is across all open files on this dev/inode pair. */
6044 if (!set_delete_on_close(fsp
, delete_on_close
,
6045 conn
->session_info
->security_token
,
6046 conn
->session_info
->unix_token
)) {
6047 return NT_STATUS_ACCESS_DENIED
;
6049 return NT_STATUS_OK
;
6052 /****************************************************************************
6053 Deal with SMB_FILE_POSITION_INFORMATION.
6054 ****************************************************************************/
6056 static NTSTATUS
smb_file_position_information(connection_struct
*conn
,
6061 uint64_t position_information
;
6063 if (total_data
< 8) {
6064 return NT_STATUS_INVALID_PARAMETER
;
6068 /* Ignore on pathname based set. */
6069 return NT_STATUS_OK
;
6072 position_information
= (uint64_t)IVAL(pdata
,0);
6073 position_information
|= (((uint64_t)IVAL(pdata
,4)) << 32);
6075 DEBUG(10,("smb_file_position_information: Set file position "
6076 "information for file %s to %.0f\n", fsp_str_dbg(fsp
),
6077 (double)position_information
));
6078 fsp
->fh
->position_information
= position_information
;
6079 return NT_STATUS_OK
;
6082 /****************************************************************************
6083 Deal with SMB_FILE_MODE_INFORMATION.
6084 ****************************************************************************/
6086 static NTSTATUS
smb_file_mode_information(connection_struct
*conn
,
6092 if (total_data
< 4) {
6093 return NT_STATUS_INVALID_PARAMETER
;
6095 mode
= IVAL(pdata
,0);
6096 if (mode
!= 0 && mode
!= 2 && mode
!= 4 && mode
!= 6) {
6097 return NT_STATUS_INVALID_PARAMETER
;
6099 return NT_STATUS_OK
;
6102 /****************************************************************************
6103 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
6104 ****************************************************************************/
6106 static NTSTATUS
smb_set_file_unix_link(connection_struct
*conn
,
6107 struct smb_request
*req
,
6110 const struct smb_filename
*smb_fname
)
6112 char *link_target
= NULL
;
6113 const char *newname
= smb_fname
->base_name
;
6114 TALLOC_CTX
*ctx
= talloc_tos();
6116 /* Set a symbolic link. */
6117 /* Don't allow this if follow links is false. */
6119 if (total_data
== 0) {
6120 return NT_STATUS_INVALID_PARAMETER
;
6123 if (!lp_symlinks(SNUM(conn
))) {
6124 return NT_STATUS_ACCESS_DENIED
;
6127 srvstr_pull_talloc(ctx
, pdata
, req
->flags2
, &link_target
, pdata
,
6128 total_data
, STR_TERMINATE
);
6131 return NT_STATUS_INVALID_PARAMETER
;
6134 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
6135 newname
, link_target
));
6137 if (SMB_VFS_SYMLINK(conn
,link_target
,newname
) != 0) {
6138 return map_nt_error_from_unix(errno
);
6141 return NT_STATUS_OK
;
6144 /****************************************************************************
6145 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
6146 ****************************************************************************/
6148 static NTSTATUS
smb_set_file_unix_hlink(connection_struct
*conn
,
6149 struct smb_request
*req
,
6150 const char *pdata
, int total_data
,
6151 struct smb_filename
*smb_fname_new
)
6153 char *oldname
= NULL
;
6154 struct smb_filename
*smb_fname_old
= NULL
;
6155 TALLOC_CTX
*ctx
= talloc_tos();
6156 NTSTATUS status
= NT_STATUS_OK
;
6158 /* Set a hard link. */
6159 if (total_data
== 0) {
6160 return NT_STATUS_INVALID_PARAMETER
;
6163 srvstr_get_path(ctx
, pdata
, req
->flags2
, &oldname
, pdata
,
6164 total_data
, STR_TERMINATE
, &status
);
6165 if (!NT_STATUS_IS_OK(status
)) {
6169 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
6170 smb_fname_str_dbg(smb_fname_new
), oldname
));
6172 status
= filename_convert(ctx
,
6174 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6179 if (!NT_STATUS_IS_OK(status
)) {
6183 return hardlink_internals(ctx
, conn
, req
, false,
6184 smb_fname_old
, smb_fname_new
);
6187 /****************************************************************************
6188 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
6189 ****************************************************************************/
6191 static NTSTATUS
smb2_file_rename_information(connection_struct
*conn
,
6192 struct smb_request
*req
,
6196 struct smb_filename
*smb_fname_src
)
6200 char *newname
= NULL
;
6201 struct smb_filename
*smb_fname_dst
= NULL
;
6202 NTSTATUS status
= NT_STATUS_OK
;
6203 TALLOC_CTX
*ctx
= talloc_tos();
6206 return NT_STATUS_INVALID_HANDLE
;
6209 if (total_data
< 20) {
6210 return NT_STATUS_INVALID_PARAMETER
;
6213 overwrite
= (CVAL(pdata
,0) ? True
: False
);
6214 len
= IVAL(pdata
,16);
6216 if (len
> (total_data
- 20) || (len
== 0)) {
6217 return NT_STATUS_INVALID_PARAMETER
;
6220 srvstr_get_path(ctx
, pdata
, req
->flags2
, &newname
,
6221 &pdata
[20], len
, STR_TERMINATE
,
6223 if (!NT_STATUS_IS_OK(status
)) {
6227 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
6230 status
= filename_convert(ctx
,
6232 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6237 if (!NT_STATUS_IS_OK(status
)) {
6241 if (fsp
->base_fsp
) {
6242 /* newname must be a stream name. */
6243 if (newname
[0] != ':') {
6244 return NT_STATUS_NOT_SUPPORTED
;
6247 /* Create an smb_fname to call rename_internals_fsp() with. */
6248 smb_fname_dst
= synthetic_smb_fname(
6249 talloc_tos(), fsp
->base_fsp
->fsp_name
->base_name
,
6251 if (smb_fname_dst
== NULL
) {
6252 status
= NT_STATUS_NO_MEMORY
;
6257 * Set the original last component, since
6258 * rename_internals_fsp() requires it.
6260 smb_fname_dst
->original_lcomp
= talloc_strdup(smb_fname_dst
,
6262 if (smb_fname_dst
->original_lcomp
== NULL
) {
6263 status
= NT_STATUS_NO_MEMORY
;
6269 DEBUG(10,("smb2_file_rename_information: "
6270 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
6271 fsp_fnum_dbg(fsp
), fsp_str_dbg(fsp
),
6272 smb_fname_str_dbg(smb_fname_dst
)));
6273 status
= rename_internals_fsp(conn
, fsp
, smb_fname_dst
,
6274 (FILE_ATTRIBUTE_HIDDEN
|FILE_ATTRIBUTE_SYSTEM
),
6278 TALLOC_FREE(smb_fname_dst
);
6282 static NTSTATUS
smb_file_link_information(connection_struct
*conn
,
6283 struct smb_request
*req
,
6287 struct smb_filename
*smb_fname_src
)
6291 char *newname
= NULL
;
6292 struct smb_filename
*smb_fname_dst
= NULL
;
6293 NTSTATUS status
= NT_STATUS_OK
;
6294 TALLOC_CTX
*ctx
= talloc_tos();
6297 return NT_STATUS_INVALID_HANDLE
;
6300 if (total_data
< 20) {
6301 return NT_STATUS_INVALID_PARAMETER
;
6304 overwrite
= (CVAL(pdata
,0) ? true : false);
6305 len
= IVAL(pdata
,16);
6307 if (len
> (total_data
- 20) || (len
== 0)) {
6308 return NT_STATUS_INVALID_PARAMETER
;
6311 srvstr_get_path(ctx
, pdata
, req
->flags2
, &newname
,
6312 &pdata
[20], len
, STR_TERMINATE
,
6314 if (!NT_STATUS_IS_OK(status
)) {
6318 DEBUG(10,("smb_file_link_information: got name |%s|\n",
6321 status
= filename_convert(ctx
,
6323 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6328 if (!NT_STATUS_IS_OK(status
)) {
6332 if (fsp
->base_fsp
) {
6333 /* No stream names. */
6334 return NT_STATUS_NOT_SUPPORTED
;
6337 DEBUG(10,("smb_file_link_information: "
6338 "SMB_FILE_LINK_INFORMATION (%s) %s -> %s\n",
6339 fsp_fnum_dbg(fsp
), fsp_str_dbg(fsp
),
6340 smb_fname_str_dbg(smb_fname_dst
)));
6341 status
= hardlink_internals(ctx
,
6348 TALLOC_FREE(smb_fname_dst
);
6352 /****************************************************************************
6353 Deal with SMB_FILE_RENAME_INFORMATION.
6354 ****************************************************************************/
6356 static NTSTATUS
smb_file_rename_information(connection_struct
*conn
,
6357 struct smb_request
*req
,
6361 struct smb_filename
*smb_fname_src
)
6366 char *newname
= NULL
;
6367 struct smb_filename
*smb_fname_dst
= NULL
;
6368 bool dest_has_wcard
= False
;
6369 NTSTATUS status
= NT_STATUS_OK
;
6371 TALLOC_CTX
*ctx
= talloc_tos();
6373 if (total_data
< 13) {
6374 return NT_STATUS_INVALID_PARAMETER
;
6377 overwrite
= (CVAL(pdata
,0) ? True
: False
);
6378 root_fid
= IVAL(pdata
,4);
6379 len
= IVAL(pdata
,8);
6381 if (len
> (total_data
- 12) || (len
== 0) || (root_fid
!= 0)) {
6382 return NT_STATUS_INVALID_PARAMETER
;
6385 srvstr_get_path_wcard(ctx
, pdata
, req
->flags2
, &newname
, &pdata
[12],
6388 if (!NT_STATUS_IS_OK(status
)) {
6392 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
6395 status
= resolve_dfspath_wcard(ctx
, conn
,
6396 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6399 !conn
->sconn
->using_smb2
,
6402 if (!NT_STATUS_IS_OK(status
)) {
6406 /* Check the new name has no '/' characters. */
6407 if (strchr_m(newname
, '/')) {
6408 return NT_STATUS_NOT_SUPPORTED
;
6411 if (fsp
&& fsp
->base_fsp
) {
6412 /* newname must be a stream name. */
6413 if (newname
[0] != ':') {
6414 return NT_STATUS_NOT_SUPPORTED
;
6417 /* Create an smb_fname to call rename_internals_fsp() with. */
6418 smb_fname_dst
= synthetic_smb_fname(
6419 talloc_tos(), fsp
->base_fsp
->fsp_name
->base_name
,
6421 if (smb_fname_dst
== NULL
) {
6422 status
= NT_STATUS_NO_MEMORY
;
6427 * Set the original last component, since
6428 * rename_internals_fsp() requires it.
6430 smb_fname_dst
->original_lcomp
= talloc_strdup(smb_fname_dst
,
6432 if (smb_fname_dst
->original_lcomp
== NULL
) {
6433 status
= NT_STATUS_NO_MEMORY
;
6439 * Build up an smb_fname_dst based on the filename passed in.
6440 * We basically just strip off the last component, and put on
6441 * the newname instead.
6443 char *base_name
= NULL
;
6445 /* newname must *not* be a stream name. */
6446 if (newname
[0] == ':') {
6447 return NT_STATUS_NOT_SUPPORTED
;
6451 * Strip off the last component (filename) of the path passed
6454 base_name
= talloc_strdup(ctx
, smb_fname_src
->base_name
);
6456 return NT_STATUS_NO_MEMORY
;
6458 p
= strrchr_m(base_name
, '/');
6462 base_name
= talloc_strdup(ctx
, "");
6464 return NT_STATUS_NO_MEMORY
;
6467 /* Append the new name. */
6468 base_name
= talloc_asprintf_append(base_name
,
6472 return NT_STATUS_NO_MEMORY
;
6475 status
= unix_convert(ctx
, conn
, base_name
, &smb_fname_dst
,
6478 UCF_ALWAYS_ALLOW_WCARD_LCOMP
:
6481 /* If an error we expect this to be
6482 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
6484 if (!NT_STATUS_IS_OK(status
)) {
6485 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND
,
6489 /* Create an smb_fname to call rename_internals_fsp() */
6490 smb_fname_dst
= synthetic_smb_fname(
6491 ctx
, base_name
, NULL
, NULL
);
6492 if (smb_fname_dst
== NULL
) {
6493 status
= NT_STATUS_NO_MEMORY
;
6500 DEBUG(10,("smb_file_rename_information: "
6501 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
6502 fsp_fnum_dbg(fsp
), fsp_str_dbg(fsp
),
6503 smb_fname_str_dbg(smb_fname_dst
)));
6504 status
= rename_internals_fsp(conn
, fsp
, smb_fname_dst
, 0,
6507 DEBUG(10,("smb_file_rename_information: "
6508 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
6509 smb_fname_str_dbg(smb_fname_src
),
6510 smb_fname_str_dbg(smb_fname_dst
)));
6511 status
= rename_internals(ctx
, conn
, req
, smb_fname_src
,
6512 smb_fname_dst
, 0, overwrite
, false,
6514 FILE_WRITE_ATTRIBUTES
);
6517 TALLOC_FREE(smb_fname_dst
);
6521 /****************************************************************************
6522 Deal with SMB_SET_POSIX_ACL.
6523 ****************************************************************************/
6525 #if defined(HAVE_POSIX_ACLS)
6526 static NTSTATUS
smb_set_posix_acl(connection_struct
*conn
,
6530 const struct smb_filename
*smb_fname
)
6532 uint16 posix_acl_version
;
6533 uint16 num_file_acls
;
6534 uint16 num_def_acls
;
6535 bool valid_file_acls
= True
;
6536 bool valid_def_acls
= True
;
6538 if (total_data
< SMB_POSIX_ACL_HEADER_SIZE
) {
6539 return NT_STATUS_INVALID_PARAMETER
;
6541 posix_acl_version
= SVAL(pdata
,0);
6542 num_file_acls
= SVAL(pdata
,2);
6543 num_def_acls
= SVAL(pdata
,4);
6545 if (num_file_acls
== SMB_POSIX_IGNORE_ACE_ENTRIES
) {
6546 valid_file_acls
= False
;
6550 if (num_def_acls
== SMB_POSIX_IGNORE_ACE_ENTRIES
) {
6551 valid_def_acls
= False
;
6555 if (posix_acl_version
!= SMB_POSIX_ACL_VERSION
) {
6556 return NT_STATUS_INVALID_PARAMETER
;
6559 if (total_data
< SMB_POSIX_ACL_HEADER_SIZE
+
6560 (num_file_acls
+num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
) {
6561 return NT_STATUS_INVALID_PARAMETER
;
6564 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
6565 smb_fname
? smb_fname_str_dbg(smb_fname
) : fsp_str_dbg(fsp
),
6566 (unsigned int)num_file_acls
,
6567 (unsigned int)num_def_acls
));
6569 if (valid_file_acls
&& !set_unix_posix_acl(conn
, fsp
,
6570 smb_fname
->base_name
, num_file_acls
,
6571 pdata
+ SMB_POSIX_ACL_HEADER_SIZE
)) {
6572 return map_nt_error_from_unix(errno
);
6575 if (valid_def_acls
&& !set_unix_posix_default_acl(conn
,
6576 smb_fname
->base_name
, &smb_fname
->st
, num_def_acls
,
6577 pdata
+ SMB_POSIX_ACL_HEADER_SIZE
+
6578 (num_file_acls
*SMB_POSIX_ACL_ENTRY_SIZE
))) {
6579 return map_nt_error_from_unix(errno
);
6581 return NT_STATUS_OK
;
6585 /****************************************************************************
6586 Deal with SMB_SET_POSIX_LOCK.
6587 ****************************************************************************/
6589 static NTSTATUS
smb_set_posix_lock(connection_struct
*conn
,
6590 struct smb_request
*req
,
6598 bool blocking_lock
= False
;
6599 enum brl_type lock_type
;
6601 NTSTATUS status
= NT_STATUS_OK
;
6603 if (fsp
== NULL
|| fsp
->fh
->fd
== -1) {
6604 return NT_STATUS_INVALID_HANDLE
;
6607 if (total_data
!= POSIX_LOCK_DATA_SIZE
) {
6608 return NT_STATUS_INVALID_PARAMETER
;
6611 switch (SVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
)) {
6612 case POSIX_LOCK_TYPE_READ
:
6613 lock_type
= READ_LOCK
;
6615 case POSIX_LOCK_TYPE_WRITE
:
6616 /* Return the right POSIX-mappable error code for files opened read-only. */
6617 if (!fsp
->can_write
) {
6618 return NT_STATUS_INVALID_HANDLE
;
6620 lock_type
= WRITE_LOCK
;
6622 case POSIX_LOCK_TYPE_UNLOCK
:
6623 lock_type
= UNLOCK_LOCK
;
6626 return NT_STATUS_INVALID_PARAMETER
;
6629 if (SVAL(pdata
,POSIX_LOCK_FLAGS_OFFSET
) == POSIX_LOCK_FLAG_NOWAIT
) {
6630 blocking_lock
= False
;
6631 } else if (SVAL(pdata
,POSIX_LOCK_FLAGS_OFFSET
) == POSIX_LOCK_FLAG_WAIT
) {
6632 blocking_lock
= True
;
6634 return NT_STATUS_INVALID_PARAMETER
;
6637 if (!lp_blocking_locks(SNUM(conn
))) {
6638 blocking_lock
= False
;
6641 smblctx
= (uint64_t)IVAL(pdata
, POSIX_LOCK_PID_OFFSET
);
6642 #if defined(HAVE_LONGLONG)
6643 offset
= (((uint64_t) IVAL(pdata
,(POSIX_LOCK_START_OFFSET
+4))) << 32) |
6644 ((uint64_t) IVAL(pdata
,POSIX_LOCK_START_OFFSET
));
6645 count
= (((uint64_t) IVAL(pdata
,(POSIX_LOCK_LEN_OFFSET
+4))) << 32) |
6646 ((uint64_t) IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
));
6647 #else /* HAVE_LONGLONG */
6648 offset
= (uint64_t)IVAL(pdata
,POSIX_LOCK_START_OFFSET
);
6649 count
= (uint64_t)IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
);
6650 #endif /* HAVE_LONGLONG */
6652 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
6653 "smblctx = %llu, count = %.0f, offset = %.0f\n",
6655 (unsigned int)lock_type
,
6656 (unsigned long long)smblctx
,
6660 if (lock_type
== UNLOCK_LOCK
) {
6661 status
= do_unlock(req
->sconn
->msg_ctx
,
6668 uint64_t block_smblctx
;
6670 struct byte_range_lock
*br_lck
= do_lock(req
->sconn
->msg_ctx
,
6682 if (br_lck
&& blocking_lock
&& ERROR_WAS_LOCK_DENIED(status
)) {
6684 * A blocking lock was requested. Package up
6685 * this smb into a queued request and push it
6686 * onto the blocking lock queue.
6688 if(push_blocking_lock_request(br_lck
,
6691 -1, /* infinite timeout. */
6699 TALLOC_FREE(br_lck
);
6703 TALLOC_FREE(br_lck
);
6709 /****************************************************************************
6710 Deal with SMB_SET_FILE_BASIC_INFO.
6711 ****************************************************************************/
6713 static NTSTATUS
smb_set_file_basic_info(connection_struct
*conn
,
6717 const struct smb_filename
*smb_fname
)
6719 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
6720 struct smb_file_time ft
;
6722 NTSTATUS status
= NT_STATUS_OK
;
6726 if (total_data
< 36) {
6727 return NT_STATUS_INVALID_PARAMETER
;
6730 status
= check_access(conn
, fsp
, smb_fname
, FILE_WRITE_ATTRIBUTES
);
6731 if (!NT_STATUS_IS_OK(status
)) {
6735 /* Set the attributes */
6736 dosmode
= IVAL(pdata
,32);
6737 status
= smb_set_file_dosmode(conn
, smb_fname
, dosmode
);
6738 if (!NT_STATUS_IS_OK(status
)) {
6743 ft
.create_time
= interpret_long_date(pdata
);
6746 ft
.atime
= interpret_long_date(pdata
+8);
6749 ft
.mtime
= interpret_long_date(pdata
+16);
6752 ft
.ctime
= interpret_long_date(pdata
+24);
6754 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
6755 smb_fname_str_dbg(smb_fname
)));
6757 return smb_set_file_time(conn
, fsp
, smb_fname
, &ft
,
6761 /****************************************************************************
6762 Deal with SMB_INFO_STANDARD.
6763 ****************************************************************************/
6765 static NTSTATUS
smb_set_info_standard(connection_struct
*conn
,
6769 const struct smb_filename
*smb_fname
)
6772 struct smb_file_time ft
;
6776 if (total_data
< 12) {
6777 return NT_STATUS_INVALID_PARAMETER
;
6781 ft
.create_time
= convert_time_t_to_timespec(srv_make_unix_date2(pdata
));
6783 ft
.atime
= convert_time_t_to_timespec(srv_make_unix_date2(pdata
+4));
6785 ft
.mtime
= convert_time_t_to_timespec(srv_make_unix_date2(pdata
+8));
6787 DEBUG(10,("smb_set_info_standard: file %s\n",
6788 smb_fname_str_dbg(smb_fname
)));
6790 status
= check_access(conn
, fsp
, smb_fname
, FILE_WRITE_ATTRIBUTES
);
6791 if (!NT_STATUS_IS_OK(status
)) {
6795 return smb_set_file_time(conn
,
6802 /****************************************************************************
6803 Deal with SMB_SET_FILE_ALLOCATION_INFO.
6804 ****************************************************************************/
6806 static NTSTATUS
smb_set_file_allocation_info(connection_struct
*conn
,
6807 struct smb_request
*req
,
6811 struct smb_filename
*smb_fname
)
6813 uint64_t allocation_size
= 0;
6814 NTSTATUS status
= NT_STATUS_OK
;
6815 files_struct
*new_fsp
= NULL
;
6817 if (!VALID_STAT(smb_fname
->st
)) {
6818 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
6821 if (total_data
< 8) {
6822 return NT_STATUS_INVALID_PARAMETER
;
6825 allocation_size
= (uint64_t)IVAL(pdata
,0);
6826 allocation_size
|= (((uint64_t)IVAL(pdata
,4)) << 32);
6827 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
6828 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname
),
6829 (double)allocation_size
));
6831 if (allocation_size
) {
6832 allocation_size
= smb_roundup(conn
, allocation_size
);
6835 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
6836 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname
),
6837 (double)allocation_size
));
6839 if (fsp
&& fsp
->fh
->fd
!= -1) {
6840 /* Open file handle. */
6841 if (!(fsp
->access_mask
& FILE_WRITE_DATA
)) {
6842 return NT_STATUS_ACCESS_DENIED
;
6845 /* Only change if needed. */
6846 if (allocation_size
!= get_file_size_stat(&smb_fname
->st
)) {
6847 if (vfs_allocate_file_space(fsp
, allocation_size
) == -1) {
6848 return map_nt_error_from_unix(errno
);
6851 /* But always update the time. */
6853 * This is equivalent to a write. Ensure it's seen immediately
6854 * if there are no pending writes.
6856 trigger_write_time_update_immediate(fsp
);
6857 return NT_STATUS_OK
;
6860 /* Pathname or stat or directory file. */
6861 status
= SMB_VFS_CREATE_FILE(
6864 0, /* root_dir_fid */
6865 smb_fname
, /* fname */
6866 FILE_WRITE_DATA
, /* access_mask */
6867 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
6869 FILE_OPEN
, /* create_disposition*/
6870 0, /* create_options */
6871 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
6872 FORCE_OPLOCK_BREAK_TO_NONE
, /* oplock_request */
6873 0, /* allocation_size */
6874 0, /* private_flags */
6877 &new_fsp
, /* result */
6880 if (!NT_STATUS_IS_OK(status
)) {
6881 /* NB. We check for open_was_deferred in the caller. */
6885 /* Only change if needed. */
6886 if (allocation_size
!= get_file_size_stat(&smb_fname
->st
)) {
6887 if (vfs_allocate_file_space(new_fsp
, allocation_size
) == -1) {
6888 status
= map_nt_error_from_unix(errno
);
6889 close_file(req
, new_fsp
, NORMAL_CLOSE
);
6894 /* Changing the allocation size should set the last mod time. */
6896 * This is equivalent to a write. Ensure it's seen immediately
6897 * if there are no pending writes.
6899 trigger_write_time_update_immediate(new_fsp
);
6901 close_file(req
, new_fsp
, NORMAL_CLOSE
);
6902 return NT_STATUS_OK
;
6905 /****************************************************************************
6906 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
6907 ****************************************************************************/
6909 static NTSTATUS
smb_set_file_end_of_file_info(connection_struct
*conn
,
6910 struct smb_request
*req
,
6914 const struct smb_filename
*smb_fname
,
6915 bool fail_after_createfile
)
6919 if (total_data
< 8) {
6920 return NT_STATUS_INVALID_PARAMETER
;
6923 size
= IVAL(pdata
,0);
6924 size
|= (((off_t
)IVAL(pdata
,4)) << 32);
6925 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
6926 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname
),
6929 return smb_set_file_size(conn
, req
,
6934 fail_after_createfile
);
6937 /****************************************************************************
6938 Allow a UNIX info mknod.
6939 ****************************************************************************/
6941 static NTSTATUS
smb_unix_mknod(connection_struct
*conn
,
6944 const struct smb_filename
*smb_fname
)
6946 uint32 file_type
= IVAL(pdata
,56);
6947 #if defined(HAVE_MAKEDEV)
6948 uint32 dev_major
= IVAL(pdata
,60);
6949 uint32 dev_minor
= IVAL(pdata
,68);
6951 SMB_DEV_T dev
= (SMB_DEV_T
)0;
6952 uint32 raw_unixmode
= IVAL(pdata
,84);
6956 if (total_data
< 100) {
6957 return NT_STATUS_INVALID_PARAMETER
;
6960 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
6961 PERM_NEW_FILE
, &unixmode
);
6962 if (!NT_STATUS_IS_OK(status
)) {
6966 #if defined(HAVE_MAKEDEV)
6967 dev
= makedev(dev_major
, dev_minor
);
6970 switch (file_type
) {
6971 #if defined(S_IFIFO)
6972 case UNIX_TYPE_FIFO
:
6973 unixmode
|= S_IFIFO
;
6976 #if defined(S_IFSOCK)
6977 case UNIX_TYPE_SOCKET
:
6978 unixmode
|= S_IFSOCK
;
6981 #if defined(S_IFCHR)
6982 case UNIX_TYPE_CHARDEV
:
6983 unixmode
|= S_IFCHR
;
6986 #if defined(S_IFBLK)
6987 case UNIX_TYPE_BLKDEV
:
6988 unixmode
|= S_IFBLK
;
6992 return NT_STATUS_INVALID_PARAMETER
;
6995 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
6996 "%.0f mode 0%o for file %s\n", (double)dev
,
6997 (unsigned int)unixmode
, smb_fname_str_dbg(smb_fname
)));
6999 /* Ok - do the mknod. */
7000 if (SMB_VFS_MKNOD(conn
, smb_fname
->base_name
, unixmode
, dev
) != 0) {
7001 return map_nt_error_from_unix(errno
);
7004 /* If any of the other "set" calls fail we
7005 * don't want to end up with a half-constructed mknod.
7008 if (lp_inherit_perms(SNUM(conn
))) {
7010 if (!parent_dirname(talloc_tos(), smb_fname
->base_name
,
7012 return NT_STATUS_NO_MEMORY
;
7014 inherit_access_posix_acl(conn
, parent
, smb_fname
->base_name
,
7016 TALLOC_FREE(parent
);
7019 return NT_STATUS_OK
;
7022 /****************************************************************************
7023 Deal with SMB_SET_FILE_UNIX_BASIC.
7024 ****************************************************************************/
7026 static NTSTATUS
smb_set_file_unix_basic(connection_struct
*conn
,
7027 struct smb_request
*req
,
7031 const struct smb_filename
*smb_fname
)
7033 struct smb_file_time ft
;
7034 uint32 raw_unixmode
;
7037 uid_t set_owner
= (uid_t
)SMB_UID_NO_CHANGE
;
7038 gid_t set_grp
= (uid_t
)SMB_GID_NO_CHANGE
;
7039 NTSTATUS status
= NT_STATUS_OK
;
7040 bool delete_on_fail
= False
;
7041 enum perm_type ptype
;
7042 files_struct
*all_fsps
= NULL
;
7043 bool modify_mtime
= true;
7045 struct smb_filename
*smb_fname_tmp
= NULL
;
7046 SMB_STRUCT_STAT sbuf
;
7050 if (total_data
< 100) {
7051 return NT_STATUS_INVALID_PARAMETER
;
7054 if(IVAL(pdata
, 0) != SMB_SIZE_NO_CHANGE_LO
&&
7055 IVAL(pdata
, 4) != SMB_SIZE_NO_CHANGE_HI
) {
7056 size
=IVAL(pdata
,0); /* first 8 Bytes are size */
7057 size
|= (((off_t
)IVAL(pdata
,4)) << 32);
7060 ft
.atime
= interpret_long_date(pdata
+24); /* access_time */
7061 ft
.mtime
= interpret_long_date(pdata
+32); /* modification_time */
7062 set_owner
= (uid_t
)IVAL(pdata
,40);
7063 set_grp
= (gid_t
)IVAL(pdata
,48);
7064 raw_unixmode
= IVAL(pdata
,84);
7066 if (VALID_STAT(smb_fname
->st
)) {
7067 if (S_ISDIR(smb_fname
->st
.st_ex_mode
)) {
7068 ptype
= PERM_EXISTING_DIR
;
7070 ptype
= PERM_EXISTING_FILE
;
7073 ptype
= PERM_NEW_FILE
;
7076 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
7078 if (!NT_STATUS_IS_OK(status
)) {
7082 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
7083 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
7084 smb_fname_str_dbg(smb_fname
), (double)size
,
7085 (unsigned int)set_owner
, (unsigned int)set_grp
,
7086 (int)raw_unixmode
));
7088 sbuf
= smb_fname
->st
;
7090 if (!VALID_STAT(sbuf
)) {
7092 * The only valid use of this is to create character and block
7093 * devices, and named pipes. This is deprecated (IMHO) and
7094 * a new info level should be used for mknod. JRA.
7097 status
= smb_unix_mknod(conn
,
7101 if (!NT_STATUS_IS_OK(status
)) {
7105 smb_fname_tmp
= cp_smb_filename(talloc_tos(), smb_fname
);
7106 if (smb_fname_tmp
== NULL
) {
7107 return NT_STATUS_NO_MEMORY
;
7110 if (SMB_VFS_STAT(conn
, smb_fname_tmp
) != 0) {
7111 status
= map_nt_error_from_unix(errno
);
7112 TALLOC_FREE(smb_fname_tmp
);
7113 SMB_VFS_UNLINK(conn
, smb_fname
);
7117 sbuf
= smb_fname_tmp
->st
;
7118 smb_fname
= smb_fname_tmp
;
7120 /* Ensure we don't try and change anything else. */
7121 raw_unixmode
= SMB_MODE_NO_CHANGE
;
7122 size
= get_file_size_stat(&sbuf
);
7123 ft
.atime
= sbuf
.st_ex_atime
;
7124 ft
.mtime
= sbuf
.st_ex_mtime
;
7126 * We continue here as we might want to change the
7129 delete_on_fail
= True
;
7133 /* Horrible backwards compatibility hack as an old server bug
7134 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
7138 size
= get_file_size_stat(&sbuf
);
7143 * Deal with the UNIX specific mode set.
7146 if (raw_unixmode
!= SMB_MODE_NO_CHANGE
) {
7149 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7150 "setting mode 0%o for file %s\n",
7151 (unsigned int)unixmode
,
7152 smb_fname_str_dbg(smb_fname
)));
7153 if (fsp
&& fsp
->fh
->fd
!= -1) {
7154 ret
= SMB_VFS_FCHMOD(fsp
, unixmode
);
7156 ret
= SMB_VFS_CHMOD(conn
, smb_fname
->base_name
, unixmode
);
7159 return map_nt_error_from_unix(errno
);
7164 * Deal with the UNIX specific uid set.
7167 if ((set_owner
!= (uid_t
)SMB_UID_NO_CHANGE
) &&
7168 (sbuf
.st_ex_uid
!= set_owner
)) {
7171 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7172 "changing owner %u for path %s\n",
7173 (unsigned int)set_owner
,
7174 smb_fname_str_dbg(smb_fname
)));
7176 if (fsp
&& fsp
->fh
->fd
!= -1) {
7177 ret
= SMB_VFS_FCHOWN(fsp
, set_owner
, (gid_t
)-1);
7180 * UNIX extensions calls must always operate
7183 ret
= SMB_VFS_LCHOWN(conn
, smb_fname
->base_name
,
7184 set_owner
, (gid_t
)-1);
7188 status
= map_nt_error_from_unix(errno
);
7189 if (delete_on_fail
) {
7190 SMB_VFS_UNLINK(conn
, smb_fname
);
7197 * Deal with the UNIX specific gid set.
7200 if ((set_grp
!= (uid_t
)SMB_GID_NO_CHANGE
) &&
7201 (sbuf
.st_ex_gid
!= set_grp
)) {
7204 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7205 "changing group %u for file %s\n",
7206 (unsigned int)set_owner
,
7207 smb_fname_str_dbg(smb_fname
)));
7208 if (fsp
&& fsp
->fh
->fd
!= -1) {
7209 ret
= SMB_VFS_FCHOWN(fsp
, set_owner
, (gid_t
)-1);
7212 * UNIX extensions calls must always operate
7215 ret
= SMB_VFS_LCHOWN(conn
, smb_fname
->base_name
, (uid_t
)-1,
7219 status
= map_nt_error_from_unix(errno
);
7220 if (delete_on_fail
) {
7221 SMB_VFS_UNLINK(conn
, smb_fname
);
7227 /* Deal with any size changes. */
7229 status
= smb_set_file_size(conn
, req
,
7235 if (!NT_STATUS_IS_OK(status
)) {
7239 /* Deal with any time changes. */
7240 if (null_timespec(ft
.mtime
) && null_timespec(ft
.atime
)) {
7241 /* No change, don't cancel anything. */
7245 id
= vfs_file_id_from_sbuf(conn
, &sbuf
);
7246 for(all_fsps
= file_find_di_first(conn
->sconn
, id
); all_fsps
;
7247 all_fsps
= file_find_di_next(all_fsps
)) {
7249 * We're setting the time explicitly for UNIX.
7250 * Cancel any pending changes over all handles.
7252 all_fsps
->update_write_time_on_close
= false;
7253 TALLOC_FREE(all_fsps
->update_write_time_event
);
7257 * Override the "setting_write_time"
7258 * parameter here as it almost does what
7259 * we need. Just remember if we modified
7260 * mtime and send the notify ourselves.
7262 if (null_timespec(ft
.mtime
)) {
7263 modify_mtime
= false;
7266 status
= smb_set_file_time(conn
,
7272 notify_fname(conn
, NOTIFY_ACTION_MODIFIED
,
7273 FILE_NOTIFY_CHANGE_LAST_WRITE
, smb_fname
->base_name
);
7278 /****************************************************************************
7279 Deal with SMB_SET_FILE_UNIX_INFO2.
7280 ****************************************************************************/
7282 static NTSTATUS
smb_set_file_unix_info2(connection_struct
*conn
,
7283 struct smb_request
*req
,
7287 const struct smb_filename
*smb_fname
)
7293 if (total_data
< 116) {
7294 return NT_STATUS_INVALID_PARAMETER
;
7297 /* Start by setting all the fields that are common between UNIX_BASIC
7300 status
= smb_set_file_unix_basic(conn
, req
, pdata
, total_data
,
7302 if (!NT_STATUS_IS_OK(status
)) {
7306 smb_fflags
= IVAL(pdata
, 108);
7307 smb_fmask
= IVAL(pdata
, 112);
7309 /* NB: We should only attempt to alter the file flags if the client
7310 * sends a non-zero mask.
7312 if (smb_fmask
!= 0) {
7313 int stat_fflags
= 0;
7315 if (!map_info2_flags_to_sbuf(&smb_fname
->st
, smb_fflags
,
7316 smb_fmask
, &stat_fflags
)) {
7317 /* Client asked to alter a flag we don't understand. */
7318 return NT_STATUS_INVALID_PARAMETER
;
7321 if (fsp
&& fsp
->fh
->fd
!= -1) {
7322 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
7323 return NT_STATUS_NOT_SUPPORTED
;
7325 if (SMB_VFS_CHFLAGS(conn
, smb_fname
->base_name
,
7326 stat_fflags
) != 0) {
7327 return map_nt_error_from_unix(errno
);
7332 /* XXX: need to add support for changing the create_time here. You
7333 * can do this for paths on Darwin with setattrlist(2). The right way
7334 * to hook this up is probably by extending the VFS utimes interface.
7337 return NT_STATUS_OK
;
7340 /****************************************************************************
7341 Create a directory with POSIX semantics.
7342 ****************************************************************************/
7344 static NTSTATUS
smb_posix_mkdir(connection_struct
*conn
,
7345 struct smb_request
*req
,
7348 struct smb_filename
*smb_fname
,
7349 int *pdata_return_size
)
7351 NTSTATUS status
= NT_STATUS_OK
;
7352 uint32 raw_unixmode
= 0;
7353 uint32 mod_unixmode
= 0;
7354 mode_t unixmode
= (mode_t
)0;
7355 files_struct
*fsp
= NULL
;
7356 uint16 info_level_return
= 0;
7358 char *pdata
= *ppdata
;
7360 if (total_data
< 18) {
7361 return NT_STATUS_INVALID_PARAMETER
;
7364 raw_unixmode
= IVAL(pdata
,8);
7365 /* Next 4 bytes are not yet defined. */
7367 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
7368 PERM_NEW_DIR
, &unixmode
);
7369 if (!NT_STATUS_IS_OK(status
)) {
7373 mod_unixmode
= (uint32
)unixmode
| FILE_FLAG_POSIX_SEMANTICS
;
7375 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
7376 smb_fname_str_dbg(smb_fname
), (unsigned int)unixmode
));
7378 status
= SMB_VFS_CREATE_FILE(
7381 0, /* root_dir_fid */
7382 smb_fname
, /* fname */
7383 FILE_READ_ATTRIBUTES
, /* access_mask */
7384 FILE_SHARE_NONE
, /* share_access */
7385 FILE_CREATE
, /* create_disposition*/
7386 FILE_DIRECTORY_FILE
, /* create_options */
7387 mod_unixmode
, /* file_attributes */
7388 0, /* oplock_request */
7389 0, /* allocation_size */
7390 0, /* private_flags */
7396 if (NT_STATUS_IS_OK(status
)) {
7397 close_file(req
, fsp
, NORMAL_CLOSE
);
7400 info_level_return
= SVAL(pdata
,16);
7402 if (info_level_return
== SMB_QUERY_FILE_UNIX_BASIC
) {
7403 *pdata_return_size
= 12 + SMB_FILE_UNIX_BASIC_SIZE
;
7404 } else if (info_level_return
== SMB_QUERY_FILE_UNIX_INFO2
) {
7405 *pdata_return_size
= 12 + SMB_FILE_UNIX_INFO2_SIZE
;
7407 *pdata_return_size
= 12;
7410 /* Realloc the data size */
7411 *ppdata
= (char *)SMB_REALLOC(*ppdata
,*pdata_return_size
);
7412 if (*ppdata
== NULL
) {
7413 *pdata_return_size
= 0;
7414 return NT_STATUS_NO_MEMORY
;
7418 SSVAL(pdata
,0,NO_OPLOCK_RETURN
);
7419 SSVAL(pdata
,2,0); /* No fnum. */
7420 SIVAL(pdata
,4,info
); /* Was directory created. */
7422 switch (info_level_return
) {
7423 case SMB_QUERY_FILE_UNIX_BASIC
:
7424 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_BASIC
);
7425 SSVAL(pdata
,10,0); /* Padding. */
7426 store_file_unix_basic(conn
, pdata
+ 12, fsp
,
7429 case SMB_QUERY_FILE_UNIX_INFO2
:
7430 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_INFO2
);
7431 SSVAL(pdata
,10,0); /* Padding. */
7432 store_file_unix_basic_info2(conn
, pdata
+ 12, fsp
,
7436 SSVAL(pdata
,8,SMB_NO_INFO_LEVEL_RETURNED
);
7437 SSVAL(pdata
,10,0); /* Padding. */
7444 /****************************************************************************
7445 Open/Create a file with POSIX semantics.
7446 ****************************************************************************/
7448 #define SMB_O_RDONLY_MAPPING (FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA)
7449 #define SMB_O_WRONLY_MAPPING (FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA)
7451 static NTSTATUS
smb_posix_open(connection_struct
*conn
,
7452 struct smb_request
*req
,
7455 struct smb_filename
*smb_fname
,
7456 int *pdata_return_size
)
7458 bool extended_oplock_granted
= False
;
7459 char *pdata
= *ppdata
;
7461 uint32 wire_open_mode
= 0;
7462 uint32 raw_unixmode
= 0;
7463 uint32 mod_unixmode
= 0;
7464 uint32 create_disp
= 0;
7465 uint32 access_mask
= 0;
7466 uint32 create_options
= FILE_NON_DIRECTORY_FILE
;
7467 NTSTATUS status
= NT_STATUS_OK
;
7468 mode_t unixmode
= (mode_t
)0;
7469 files_struct
*fsp
= NULL
;
7470 int oplock_request
= 0;
7472 uint16 info_level_return
= 0;
7474 if (total_data
< 18) {
7475 return NT_STATUS_INVALID_PARAMETER
;
7478 flags
= IVAL(pdata
,0);
7479 oplock_request
= (flags
& REQUEST_OPLOCK
) ? EXCLUSIVE_OPLOCK
: 0;
7480 if (oplock_request
) {
7481 oplock_request
|= (flags
& REQUEST_BATCH_OPLOCK
) ? BATCH_OPLOCK
: 0;
7484 wire_open_mode
= IVAL(pdata
,4);
7486 if (wire_open_mode
== (SMB_O_CREAT
|SMB_O_DIRECTORY
)) {
7487 return smb_posix_mkdir(conn
, req
,
7494 switch (wire_open_mode
& SMB_ACCMODE
) {
7496 access_mask
= SMB_O_RDONLY_MAPPING
;
7499 access_mask
= SMB_O_WRONLY_MAPPING
;
7502 access_mask
= (SMB_O_RDONLY_MAPPING
|
7503 SMB_O_WRONLY_MAPPING
);
7506 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
7507 (unsigned int)wire_open_mode
));
7508 return NT_STATUS_INVALID_PARAMETER
;
7511 wire_open_mode
&= ~SMB_ACCMODE
;
7513 /* First take care of O_CREAT|O_EXCL interactions. */
7514 switch (wire_open_mode
& (SMB_O_CREAT
| SMB_O_EXCL
)) {
7515 case (SMB_O_CREAT
| SMB_O_EXCL
):
7516 /* File exists fail. File not exist create. */
7517 create_disp
= FILE_CREATE
;
7520 /* File exists open. File not exist create. */
7521 create_disp
= FILE_OPEN_IF
;
7524 /* O_EXCL on its own without O_CREAT is undefined.
7525 We deliberately ignore it as some versions of
7526 Linux CIFSFS can send a bare O_EXCL on the
7527 wire which other filesystems in the kernel
7528 ignore. See bug 9519 for details. */
7533 /* File exists open. File not exist fail. */
7534 create_disp
= FILE_OPEN
;
7537 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
7538 (unsigned int)wire_open_mode
));
7539 return NT_STATUS_INVALID_PARAMETER
;
7542 /* Next factor in the effects of O_TRUNC. */
7543 wire_open_mode
&= ~(SMB_O_CREAT
| SMB_O_EXCL
);
7545 if (wire_open_mode
& SMB_O_TRUNC
) {
7546 switch (create_disp
) {
7548 /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
7549 /* Leave create_disp alone as
7550 (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
7552 /* File exists fail. File not exist create. */
7555 /* SMB_O_CREAT | SMB_O_TRUNC */
7556 /* File exists overwrite. File not exist create. */
7557 create_disp
= FILE_OVERWRITE_IF
;
7561 /* File exists overwrite. File not exist fail. */
7562 create_disp
= FILE_OVERWRITE
;
7565 /* Cannot get here. */
7566 smb_panic("smb_posix_open: logic error");
7567 return NT_STATUS_INVALID_PARAMETER
;
7571 raw_unixmode
= IVAL(pdata
,8);
7572 /* Next 4 bytes are not yet defined. */
7574 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
7575 (VALID_STAT(smb_fname
->st
) ?
7576 PERM_EXISTING_FILE
: PERM_NEW_FILE
),
7579 if (!NT_STATUS_IS_OK(status
)) {
7583 mod_unixmode
= (uint32
)unixmode
| FILE_FLAG_POSIX_SEMANTICS
;
7585 if (wire_open_mode
& SMB_O_SYNC
) {
7586 create_options
|= FILE_WRITE_THROUGH
;
7588 if (wire_open_mode
& SMB_O_APPEND
) {
7589 access_mask
|= FILE_APPEND_DATA
;
7591 if (wire_open_mode
& SMB_O_DIRECT
) {
7592 mod_unixmode
|= FILE_FLAG_NO_BUFFERING
;
7595 if ((wire_open_mode
& SMB_O_DIRECTORY
) ||
7596 VALID_STAT_OF_DIR(smb_fname
->st
)) {
7597 if (access_mask
!= SMB_O_RDONLY_MAPPING
) {
7598 return NT_STATUS_FILE_IS_A_DIRECTORY
;
7600 create_options
&= ~FILE_NON_DIRECTORY_FILE
;
7601 create_options
|= FILE_DIRECTORY_FILE
;
7604 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
7605 smb_fname_str_dbg(smb_fname
),
7606 (unsigned int)wire_open_mode
,
7607 (unsigned int)unixmode
));
7609 status
= SMB_VFS_CREATE_FILE(
7612 0, /* root_dir_fid */
7613 smb_fname
, /* fname */
7614 access_mask
, /* access_mask */
7615 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
7617 create_disp
, /* create_disposition*/
7618 create_options
, /* create_options */
7619 mod_unixmode
, /* file_attributes */
7620 oplock_request
, /* oplock_request */
7621 0, /* allocation_size */
7622 0, /* private_flags */
7628 if (!NT_STATUS_IS_OK(status
)) {
7632 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
7633 extended_oplock_granted
= True
;
7636 if(oplock_request
&& EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
7637 extended_oplock_granted
= True
;
7640 info_level_return
= SVAL(pdata
,16);
7642 /* Allocate the correct return size. */
7644 if (info_level_return
== SMB_QUERY_FILE_UNIX_BASIC
) {
7645 *pdata_return_size
= 12 + SMB_FILE_UNIX_BASIC_SIZE
;
7646 } else if (info_level_return
== SMB_QUERY_FILE_UNIX_INFO2
) {
7647 *pdata_return_size
= 12 + SMB_FILE_UNIX_INFO2_SIZE
;
7649 *pdata_return_size
= 12;
7652 /* Realloc the data size */
7653 *ppdata
= (char *)SMB_REALLOC(*ppdata
,*pdata_return_size
);
7654 if (*ppdata
== NULL
) {
7655 close_file(req
, fsp
, ERROR_CLOSE
);
7656 *pdata_return_size
= 0;
7657 return NT_STATUS_NO_MEMORY
;
7661 if (extended_oplock_granted
) {
7662 if (flags
& REQUEST_BATCH_OPLOCK
) {
7663 SSVAL(pdata
,0, BATCH_OPLOCK_RETURN
);
7665 SSVAL(pdata
,0, EXCLUSIVE_OPLOCK_RETURN
);
7667 } else if (fsp
->oplock_type
== LEVEL_II_OPLOCK
) {
7668 SSVAL(pdata
,0, LEVEL_II_OPLOCK_RETURN
);
7670 SSVAL(pdata
,0,NO_OPLOCK_RETURN
);
7673 SSVAL(pdata
,2,fsp
->fnum
);
7674 SIVAL(pdata
,4,info
); /* Was file created etc. */
7676 switch (info_level_return
) {
7677 case SMB_QUERY_FILE_UNIX_BASIC
:
7678 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_BASIC
);
7679 SSVAL(pdata
,10,0); /* padding. */
7680 store_file_unix_basic(conn
, pdata
+ 12, fsp
,
7683 case SMB_QUERY_FILE_UNIX_INFO2
:
7684 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_INFO2
);
7685 SSVAL(pdata
,10,0); /* padding. */
7686 store_file_unix_basic_info2(conn
, pdata
+ 12, fsp
,
7690 SSVAL(pdata
,8,SMB_NO_INFO_LEVEL_RETURNED
);
7691 SSVAL(pdata
,10,0); /* padding. */
7694 return NT_STATUS_OK
;
7697 /****************************************************************************
7698 Delete a file with POSIX semantics.
7699 ****************************************************************************/
7701 static NTSTATUS
smb_posix_unlink(connection_struct
*conn
,
7702 struct smb_request
*req
,
7705 struct smb_filename
*smb_fname
)
7707 NTSTATUS status
= NT_STATUS_OK
;
7708 files_struct
*fsp
= NULL
;
7712 int create_options
= 0;
7714 struct share_mode_lock
*lck
= NULL
;
7716 if (total_data
< 2) {
7717 return NT_STATUS_INVALID_PARAMETER
;
7720 flags
= SVAL(pdata
,0);
7722 if (!VALID_STAT(smb_fname
->st
)) {
7723 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
7726 if ((flags
== SMB_POSIX_UNLINK_DIRECTORY_TARGET
) &&
7727 !VALID_STAT_OF_DIR(smb_fname
->st
)) {
7728 return NT_STATUS_NOT_A_DIRECTORY
;
7731 DEBUG(10,("smb_posix_unlink: %s %s\n",
7732 (flags
== SMB_POSIX_UNLINK_DIRECTORY_TARGET
) ? "directory" : "file",
7733 smb_fname_str_dbg(smb_fname
)));
7735 if (VALID_STAT_OF_DIR(smb_fname
->st
)) {
7736 create_options
|= FILE_DIRECTORY_FILE
;
7739 status
= SMB_VFS_CREATE_FILE(
7742 0, /* root_dir_fid */
7743 smb_fname
, /* fname */
7744 DELETE_ACCESS
, /* access_mask */
7745 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
7747 FILE_OPEN
, /* create_disposition*/
7748 create_options
, /* create_options */
7749 FILE_FLAG_POSIX_SEMANTICS
|0777, /* file_attributes */
7750 0, /* oplock_request */
7751 0, /* allocation_size */
7752 0, /* private_flags */
7758 if (!NT_STATUS_IS_OK(status
)) {
7763 * Don't lie to client. If we can't really delete due to
7764 * non-POSIX opens return SHARING_VIOLATION.
7767 lck
= get_existing_share_mode_lock(talloc_tos(), fsp
->file_id
);
7769 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
7770 "lock for file %s\n", fsp_str_dbg(fsp
)));
7771 close_file(req
, fsp
, NORMAL_CLOSE
);
7772 return NT_STATUS_INVALID_PARAMETER
;
7776 * See if others still have the file open. If this is the case, then
7777 * don't delete. If all opens are POSIX delete we can set the delete
7778 * on close disposition.
7780 for (i
=0; i
<lck
->data
->num_share_modes
; i
++) {
7781 struct share_mode_entry
*e
= &lck
->data
->share_modes
[i
];
7782 if (is_valid_share_mode_entry(e
)) {
7783 if (e
->flags
& SHARE_MODE_FLAG_POSIX_OPEN
) {
7786 if (share_mode_stale_pid(lck
->data
, i
)) {
7789 /* Fail with sharing violation. */
7791 close_file(req
, fsp
, NORMAL_CLOSE
);
7792 return NT_STATUS_SHARING_VIOLATION
;
7797 * Set the delete on close.
7799 status
= smb_set_file_disposition_info(conn
,
7807 if (!NT_STATUS_IS_OK(status
)) {
7808 close_file(req
, fsp
, NORMAL_CLOSE
);
7811 return close_file(req
, fsp
, NORMAL_CLOSE
);
7814 NTSTATUS
smbd_do_setfilepathinfo(connection_struct
*conn
,
7815 struct smb_request
*req
,
7816 TALLOC_CTX
*mem_ctx
,
7817 uint16_t info_level
,
7819 struct smb_filename
*smb_fname
,
7820 char **ppdata
, int total_data
,
7823 char *pdata
= *ppdata
;
7824 NTSTATUS status
= NT_STATUS_OK
;
7825 int data_return_size
= 0;
7829 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
7830 return NT_STATUS_INVALID_LEVEL
;
7833 if (!CAN_WRITE(conn
)) {
7834 /* Allow POSIX opens. The open path will deny
7835 * any non-readonly opens. */
7836 if (info_level
!= SMB_POSIX_PATH_OPEN
) {
7837 return NT_STATUS_DOS(ERRSRV
, ERRaccess
);
7841 DEBUG(3,("smbd_do_setfilepathinfo: %s (%s) info_level=%d "
7842 "totdata=%d\n", smb_fname_str_dbg(smb_fname
),
7844 info_level
, total_data
));
7846 switch (info_level
) {
7848 case SMB_INFO_STANDARD
:
7850 status
= smb_set_info_standard(conn
,
7858 case SMB_INFO_SET_EA
:
7860 status
= smb_info_set_ea(conn
,
7868 case SMB_SET_FILE_BASIC_INFO
:
7869 case SMB_FILE_BASIC_INFORMATION
:
7871 status
= smb_set_file_basic_info(conn
,
7879 case SMB_FILE_ALLOCATION_INFORMATION
:
7880 case SMB_SET_FILE_ALLOCATION_INFO
:
7882 status
= smb_set_file_allocation_info(conn
, req
,
7890 case SMB_FILE_END_OF_FILE_INFORMATION
:
7891 case SMB_SET_FILE_END_OF_FILE_INFO
:
7894 * XP/Win7 both fail after the createfile with
7895 * SMB_SET_FILE_END_OF_FILE_INFO but not
7896 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
7897 * The level is known here, so pass it down
7901 (info_level
== SMB_SET_FILE_END_OF_FILE_INFO
);
7903 status
= smb_set_file_end_of_file_info(conn
, req
,
7912 case SMB_FILE_DISPOSITION_INFORMATION
:
7913 case SMB_SET_FILE_DISPOSITION_INFO
: /* Set delete on close for open file. */
7916 /* JRA - We used to just ignore this on a path ?
7917 * Shouldn't this be invalid level on a pathname
7920 if (tran_call
!= TRANSACT2_SETFILEINFO
) {
7921 return ERROR_NT(NT_STATUS_INVALID_LEVEL
);
7924 status
= smb_set_file_disposition_info(conn
,
7932 case SMB_FILE_POSITION_INFORMATION
:
7934 status
= smb_file_position_information(conn
,
7941 case SMB_FILE_FULL_EA_INFORMATION
:
7943 status
= smb_set_file_full_ea_info(conn
,
7950 /* From tridge Samba4 :
7951 * MODE_INFORMATION in setfileinfo (I have no
7952 * idea what "mode information" on a file is - it takes a value of 0,
7953 * 2, 4 or 6. What could it be?).
7956 case SMB_FILE_MODE_INFORMATION
:
7958 status
= smb_file_mode_information(conn
,
7965 * CIFS UNIX extensions.
7968 case SMB_SET_FILE_UNIX_BASIC
:
7970 status
= smb_set_file_unix_basic(conn
, req
,
7978 case SMB_SET_FILE_UNIX_INFO2
:
7980 status
= smb_set_file_unix_info2(conn
, req
,
7988 case SMB_SET_FILE_UNIX_LINK
:
7991 /* We must have a pathname for this. */
7992 return NT_STATUS_INVALID_LEVEL
;
7994 status
= smb_set_file_unix_link(conn
, req
, pdata
,
7995 total_data
, smb_fname
);
7999 case SMB_SET_FILE_UNIX_HLINK
:
8002 /* We must have a pathname for this. */
8003 return NT_STATUS_INVALID_LEVEL
;
8005 status
= smb_set_file_unix_hlink(conn
, req
,
8011 case SMB_FILE_RENAME_INFORMATION
:
8013 status
= smb_file_rename_information(conn
, req
,
8019 case SMB2_FILE_RENAME_INFORMATION_INTERNAL
:
8021 /* SMB2 rename information. */
8022 status
= smb2_file_rename_information(conn
, req
,
8028 case SMB_FILE_LINK_INFORMATION
:
8030 status
= smb_file_link_information(conn
, req
,
8036 #if defined(HAVE_POSIX_ACLS)
8037 case SMB_SET_POSIX_ACL
:
8039 status
= smb_set_posix_acl(conn
,
8048 case SMB_SET_POSIX_LOCK
:
8051 return NT_STATUS_INVALID_LEVEL
;
8053 status
= smb_set_posix_lock(conn
, req
,
8054 pdata
, total_data
, fsp
);
8058 case SMB_POSIX_PATH_OPEN
:
8061 /* We must have a pathname for this. */
8062 return NT_STATUS_INVALID_LEVEL
;
8065 status
= smb_posix_open(conn
, req
,
8073 case SMB_POSIX_PATH_UNLINK
:
8076 /* We must have a pathname for this. */
8077 return NT_STATUS_INVALID_LEVEL
;
8080 status
= smb_posix_unlink(conn
, req
,
8088 return NT_STATUS_INVALID_LEVEL
;
8091 if (!NT_STATUS_IS_OK(status
)) {
8095 *ret_data_size
= data_return_size
;
8096 return NT_STATUS_OK
;
8099 /****************************************************************************
8100 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
8101 ****************************************************************************/
8103 static void call_trans2setfilepathinfo(connection_struct
*conn
,
8104 struct smb_request
*req
,
8105 unsigned int tran_call
,
8106 char **pparams
, int total_params
,
8107 char **ppdata
, int total_data
,
8108 unsigned int max_data_bytes
)
8110 char *params
= *pparams
;
8111 char *pdata
= *ppdata
;
8113 struct smb_filename
*smb_fname
= NULL
;
8114 files_struct
*fsp
= NULL
;
8115 NTSTATUS status
= NT_STATUS_OK
;
8116 int data_return_size
= 0;
8119 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8123 if (tran_call
== TRANSACT2_SETFILEINFO
) {
8124 if (total_params
< 4) {
8125 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8129 fsp
= file_fsp(req
, SVAL(params
,0));
8130 /* Basic check for non-null fsp. */
8131 if (!check_fsp_open(conn
, req
, fsp
)) {
8134 info_level
= SVAL(params
,2);
8136 smb_fname
= cp_smb_filename(talloc_tos(), fsp
->fsp_name
);
8137 if (smb_fname
== NULL
) {
8138 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8142 if(fsp
->fh
->fd
== -1) {
8144 * This is actually a SETFILEINFO on a directory
8145 * handle (returned from an NT SMB). NT5.0 seems
8146 * to do this call. JRA.
8148 if (INFO_LEVEL_IS_UNIX(info_level
)) {
8149 /* Always do lstat for UNIX calls. */
8150 if (SMB_VFS_LSTAT(conn
, smb_fname
)) {
8151 DEBUG(3,("call_trans2setfilepathinfo: "
8152 "SMB_VFS_LSTAT of %s failed "
8154 smb_fname_str_dbg(smb_fname
),
8156 reply_nterror(req
, map_nt_error_from_unix(errno
));
8160 if (SMB_VFS_STAT(conn
, smb_fname
) != 0) {
8161 DEBUG(3,("call_trans2setfilepathinfo: "
8162 "fileinfo of %s failed (%s)\n",
8163 smb_fname_str_dbg(smb_fname
),
8165 reply_nterror(req
, map_nt_error_from_unix(errno
));
8169 } else if (fsp
->print_file
) {
8171 * Doing a DELETE_ON_CLOSE should cancel a print job.
8173 if ((info_level
== SMB_SET_FILE_DISPOSITION_INFO
) && CVAL(pdata
,0)) {
8174 fsp
->fh
->private_options
|= NTCREATEX_OPTIONS_PRIVATE_DELETE_ON_CLOSE
;
8176 DEBUG(3,("call_trans2setfilepathinfo: "
8177 "Cancelling print job (%s)\n",
8181 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 2,
8187 NT_STATUS_OBJECT_PATH_NOT_FOUND
);
8192 * Original code - this is an open file.
8194 if (SMB_VFS_FSTAT(fsp
, &smb_fname
->st
) != 0) {
8195 DEBUG(3,("call_trans2setfilepathinfo: fstat "
8196 "of %s failed (%s)\n", fsp_fnum_dbg(fsp
),
8198 reply_nterror(req
, map_nt_error_from_unix(errno
));
8204 uint32_t ucf_flags
= 0;
8207 if (total_params
< 7) {
8208 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8212 info_level
= SVAL(params
,0);
8213 srvstr_get_path(req
, params
, req
->flags2
, &fname
, ¶ms
[6],
8214 total_params
- 6, STR_TERMINATE
,
8216 if (!NT_STATUS_IS_OK(status
)) {
8217 reply_nterror(req
, status
);
8221 if (info_level
== SMB_SET_FILE_UNIX_BASIC
||
8222 info_level
== SMB_SET_FILE_UNIX_INFO2
||
8223 info_level
== SMB_FILE_RENAME_INFORMATION
||
8224 info_level
== SMB_POSIX_PATH_UNLINK
) {
8225 ucf_flags
|= UCF_UNIX_NAME_LOOKUP
;
8228 status
= filename_convert(req
, conn
,
8229 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
8234 if (!NT_STATUS_IS_OK(status
)) {
8235 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
8236 reply_botherror(req
,
8237 NT_STATUS_PATH_NOT_COVERED
,
8238 ERRSRV
, ERRbadpath
);
8241 reply_nterror(req
, status
);
8245 if (INFO_LEVEL_IS_UNIX(info_level
)) {
8247 * For CIFS UNIX extensions the target name may not exist.
8250 /* Always do lstat for UNIX calls. */
8251 SMB_VFS_LSTAT(conn
, smb_fname
);
8253 } else if (!VALID_STAT(smb_fname
->st
) &&
8254 SMB_VFS_STAT(conn
, smb_fname
)) {
8255 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
8257 smb_fname_str_dbg(smb_fname
),
8259 reply_nterror(req
, map_nt_error_from_unix(errno
));
8264 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (%s) info_level=%d "
8265 "totdata=%d\n", tran_call
, smb_fname_str_dbg(smb_fname
),
8267 info_level
,total_data
));
8269 /* Realloc the parameter size */
8270 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
8271 if (*pparams
== NULL
) {
8272 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8279 status
= smbd_do_setfilepathinfo(conn
, req
, req
,
8285 if (!NT_STATUS_IS_OK(status
)) {
8286 if (open_was_deferred(req
->sconn
, req
->mid
)) {
8287 /* We have re-scheduled this call. */
8290 if (blocking_lock_was_deferred_smb1(req
->sconn
, req
->mid
)) {
8291 /* We have re-scheduled this call. */
8294 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
8295 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
8296 ERRSRV
, ERRbadpath
);
8299 if (info_level
== SMB_POSIX_PATH_OPEN
) {
8300 reply_openerror(req
, status
);
8305 * Invalid EA name needs to return 2 param bytes,
8306 * not a zero-length error packet.
8308 if (NT_STATUS_EQUAL(status
, STATUS_INVALID_EA_NAME
)) {
8309 send_trans2_replies(conn
, req
, status
, params
, 2, NULL
, 0,
8312 reply_nterror(req
, status
);
8317 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 2, *ppdata
, data_return_size
,
8323 /****************************************************************************
8324 Reply to a TRANS2_MKDIR (make directory with extended attributes).
8325 ****************************************************************************/
8327 static void call_trans2mkdir(connection_struct
*conn
, struct smb_request
*req
,
8328 char **pparams
, int total_params
,
8329 char **ppdata
, int total_data
,
8330 unsigned int max_data_bytes
)
8332 struct smb_filename
*smb_dname
= NULL
;
8333 char *params
= *pparams
;
8334 char *pdata
= *ppdata
;
8335 char *directory
= NULL
;
8336 NTSTATUS status
= NT_STATUS_OK
;
8337 struct ea_list
*ea_list
= NULL
;
8338 TALLOC_CTX
*ctx
= talloc_tos();
8340 if (!CAN_WRITE(conn
)) {
8341 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
8345 if (total_params
< 5) {
8346 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8350 srvstr_get_path(ctx
, params
, req
->flags2
, &directory
, ¶ms
[4],
8351 total_params
- 4, STR_TERMINATE
,
8353 if (!NT_STATUS_IS_OK(status
)) {
8354 reply_nterror(req
, status
);
8358 DEBUG(3,("call_trans2mkdir : name = %s\n", directory
));
8360 status
= filename_convert(ctx
,
8362 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
8368 if (!NT_STATUS_IS_OK(status
)) {
8369 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
8370 reply_botherror(req
,
8371 NT_STATUS_PATH_NOT_COVERED
,
8372 ERRSRV
, ERRbadpath
);
8375 reply_nterror(req
, status
);
8380 * OS/2 workplace shell seems to send SET_EA requests of "null"
8381 * length (4 bytes containing IVAL 4).
8382 * They seem to have no effect. Bug #3212. JRA.
8385 if (total_data
&& (total_data
!= 4)) {
8386 /* Any data in this call is an EA list. */
8387 if (total_data
< 10) {
8388 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8392 if (IVAL(pdata
,0) > total_data
) {
8393 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
8394 IVAL(pdata
,0), (unsigned int)total_data
));
8395 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8399 ea_list
= read_ea_list(talloc_tos(), pdata
+ 4,
8402 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8406 if (!lp_ea_support(SNUM(conn
))) {
8407 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
8411 /* If total_data == 4 Windows doesn't care what values
8412 * are placed in that field, it just ignores them.
8413 * The System i QNTC IBM SMB client puts bad values here,
8414 * so ignore them. */
8416 status
= create_directory(conn
, req
, smb_dname
);
8418 if (!NT_STATUS_IS_OK(status
)) {
8419 reply_nterror(req
, status
);
8423 /* Try and set any given EA. */
8425 status
= set_ea(conn
, NULL
, smb_dname
, ea_list
);
8426 if (!NT_STATUS_IS_OK(status
)) {
8427 reply_nterror(req
, status
);
8432 /* Realloc the parameter and data sizes */
8433 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
8434 if(*pparams
== NULL
) {
8435 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8442 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 2, *ppdata
, 0, max_data_bytes
);
8445 TALLOC_FREE(smb_dname
);
8449 /****************************************************************************
8450 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
8451 We don't actually do this - we just send a null response.
8452 ****************************************************************************/
8454 static void call_trans2findnotifyfirst(connection_struct
*conn
,
8455 struct smb_request
*req
,
8456 char **pparams
, int total_params
,
8457 char **ppdata
, int total_data
,
8458 unsigned int max_data_bytes
)
8460 char *params
= *pparams
;
8463 if (total_params
< 6) {
8464 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8468 info_level
= SVAL(params
,4);
8469 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level
));
8471 switch (info_level
) {
8476 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
8480 /* Realloc the parameter and data sizes */
8481 *pparams
= (char *)SMB_REALLOC(*pparams
,6);
8482 if (*pparams
== NULL
) {
8483 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8488 SSVAL(params
,0,fnf_handle
);
8489 SSVAL(params
,2,0); /* No changes */
8490 SSVAL(params
,4,0); /* No EA errors */
8497 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 6, *ppdata
, 0, max_data_bytes
);
8502 /****************************************************************************
8503 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
8504 changes). Currently this does nothing.
8505 ****************************************************************************/
8507 static void call_trans2findnotifynext(connection_struct
*conn
,
8508 struct smb_request
*req
,
8509 char **pparams
, int total_params
,
8510 char **ppdata
, int total_data
,
8511 unsigned int max_data_bytes
)
8513 char *params
= *pparams
;
8515 DEBUG(3,("call_trans2findnotifynext\n"));
8517 /* Realloc the parameter and data sizes */
8518 *pparams
= (char *)SMB_REALLOC(*pparams
,4);
8519 if (*pparams
== NULL
) {
8520 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8525 SSVAL(params
,0,0); /* No changes */
8526 SSVAL(params
,2,0); /* No EA errors */
8528 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 4, *ppdata
, 0, max_data_bytes
);
8533 /****************************************************************************
8534 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
8535 ****************************************************************************/
8537 static void call_trans2getdfsreferral(connection_struct
*conn
,
8538 struct smb_request
*req
,
8539 char **pparams
, int total_params
,
8540 char **ppdata
, int total_data
,
8541 unsigned int max_data_bytes
)
8543 char *params
= *pparams
;
8544 char *pathname
= NULL
;
8546 int max_referral_level
;
8547 NTSTATUS status
= NT_STATUS_OK
;
8548 TALLOC_CTX
*ctx
= talloc_tos();
8550 DEBUG(10,("call_trans2getdfsreferral\n"));
8552 if (total_params
< 3) {
8553 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8557 max_referral_level
= SVAL(params
,0);
8559 if(!lp_host_msdfs()) {
8560 reply_nterror(req
, NT_STATUS_NOT_IMPLEMENTED
);
8564 srvstr_pull_talloc(ctx
, params
, req
->flags2
, &pathname
, ¶ms
[2],
8565 total_params
- 2, STR_TERMINATE
);
8567 reply_nterror(req
, NT_STATUS_NOT_FOUND
);
8570 if((reply_size
= setup_dfs_referral(conn
, pathname
, max_referral_level
,
8571 ppdata
,&status
)) < 0) {
8572 reply_nterror(req
, status
);
8576 SSVAL((discard_const_p(uint8_t, req
->inbuf
)), smb_flg2
,
8577 SVAL(req
->inbuf
,smb_flg2
) | FLAGS2_DFS_PATHNAMES
);
8578 send_trans2_replies(conn
, req
, NT_STATUS_OK
, 0,0,*ppdata
,reply_size
, max_data_bytes
);
8583 #define LMCAT_SPL 0x53
8584 #define LMFUNC_GETJOBID 0x60
8586 /****************************************************************************
8587 Reply to a TRANS2_IOCTL - used for OS/2 printing.
8588 ****************************************************************************/
8590 static void call_trans2ioctl(connection_struct
*conn
,
8591 struct smb_request
*req
,
8592 char **pparams
, int total_params
,
8593 char **ppdata
, int total_data
,
8594 unsigned int max_data_bytes
)
8596 char *pdata
= *ppdata
;
8597 files_struct
*fsp
= file_fsp(req
, SVAL(req
->vwv
+15, 0));
8599 /* check for an invalid fid before proceeding */
8602 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
8606 if ((SVAL(req
->vwv
+16, 0) == LMCAT_SPL
)
8607 && (SVAL(req
->vwv
+17, 0) == LMFUNC_GETJOBID
)) {
8608 *ppdata
= (char *)SMB_REALLOC(*ppdata
, 32);
8609 if (*ppdata
== NULL
) {
8610 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8615 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
8616 CAN ACCEPT THIS IN UNICODE. JRA. */
8619 SSVAL(pdata
, 0, print_spool_rap_jobid(fsp
->print_file
));
8621 srvstr_push(pdata
, req
->flags2
, pdata
+ 2,
8622 lp_netbios_name(), 15,
8623 STR_ASCII
|STR_TERMINATE
); /* Our NetBIOS name */
8624 srvstr_push(pdata
, req
->flags2
, pdata
+18,
8625 lp_servicename(talloc_tos(), SNUM(conn
)), 13,
8626 STR_ASCII
|STR_TERMINATE
); /* Service name */
8627 send_trans2_replies(conn
, req
, NT_STATUS_OK
, *pparams
, 0, *ppdata
, 32,
8632 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
8633 reply_nterror(req
, NT_STATUS_NOT_IMPLEMENTED
);
8636 /****************************************************************************
8637 Reply to a SMBfindclose (stop trans2 directory search).
8638 ****************************************************************************/
8640 void reply_findclose(struct smb_request
*req
)
8643 struct smbd_server_connection
*sconn
= req
->sconn
;
8645 START_PROFILE(SMBfindclose
);
8648 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8649 END_PROFILE(SMBfindclose
);
8653 dptr_num
= SVALS(req
->vwv
+0, 0);
8655 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num
));
8657 dptr_close(sconn
, &dptr_num
);
8659 reply_outbuf(req
, 0, 0);
8661 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num
));
8663 END_PROFILE(SMBfindclose
);
8667 /****************************************************************************
8668 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
8669 ****************************************************************************/
8671 void reply_findnclose(struct smb_request
*req
)
8675 START_PROFILE(SMBfindnclose
);
8678 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8679 END_PROFILE(SMBfindnclose
);
8683 dptr_num
= SVAL(req
->vwv
+0, 0);
8685 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num
));
8687 /* We never give out valid handles for a
8688 findnotifyfirst - so any dptr_num is ok here.
8691 reply_outbuf(req
, 0, 0);
8693 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num
));
8695 END_PROFILE(SMBfindnclose
);
8699 static void handle_trans2(connection_struct
*conn
, struct smb_request
*req
,
8700 struct trans_state
*state
)
8702 if (get_Protocol() >= PROTOCOL_NT1
) {
8703 req
->flags2
|= 0x40; /* IS_LONG_NAME */
8704 SSVAL((discard_const_p(uint8_t, req
->inbuf
)),smb_flg2
,req
->flags2
);
8707 if (ENCRYPTION_REQUIRED(conn
) && !req
->encrypted
) {
8708 if (state
->call
!= TRANSACT2_QFSINFO
&&
8709 state
->call
!= TRANSACT2_SETFSINFO
) {
8710 DEBUG(0,("handle_trans2: encryption required "
8712 (unsigned int)state
->call
));
8713 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
8718 SMB_PERFCOUNT_SET_SUBOP(&req
->pcd
, state
->call
);
8720 /* Now we must call the relevant TRANS2 function */
8721 switch(state
->call
) {
8722 case TRANSACT2_OPEN
:
8724 START_PROFILE(Trans2_open
);
8725 call_trans2open(conn
, req
,
8726 &state
->param
, state
->total_param
,
8727 &state
->data
, state
->total_data
,
8728 state
->max_data_return
);
8729 END_PROFILE(Trans2_open
);
8733 case TRANSACT2_FINDFIRST
:
8735 START_PROFILE(Trans2_findfirst
);
8736 call_trans2findfirst(conn
, req
,
8737 &state
->param
, state
->total_param
,
8738 &state
->data
, state
->total_data
,
8739 state
->max_data_return
);
8740 END_PROFILE(Trans2_findfirst
);
8744 case TRANSACT2_FINDNEXT
:
8746 START_PROFILE(Trans2_findnext
);
8747 call_trans2findnext(conn
, req
,
8748 &state
->param
, state
->total_param
,
8749 &state
->data
, state
->total_data
,
8750 state
->max_data_return
);
8751 END_PROFILE(Trans2_findnext
);
8755 case TRANSACT2_QFSINFO
:
8757 START_PROFILE(Trans2_qfsinfo
);
8758 call_trans2qfsinfo(conn
, req
,
8759 &state
->param
, state
->total_param
,
8760 &state
->data
, state
->total_data
,
8761 state
->max_data_return
);
8762 END_PROFILE(Trans2_qfsinfo
);
8766 case TRANSACT2_SETFSINFO
:
8768 START_PROFILE(Trans2_setfsinfo
);
8769 call_trans2setfsinfo(conn
, req
,
8770 &state
->param
, state
->total_param
,
8771 &state
->data
, state
->total_data
,
8772 state
->max_data_return
);
8773 END_PROFILE(Trans2_setfsinfo
);
8777 case TRANSACT2_QPATHINFO
:
8778 case TRANSACT2_QFILEINFO
:
8780 START_PROFILE(Trans2_qpathinfo
);
8781 call_trans2qfilepathinfo(conn
, req
, state
->call
,
8782 &state
->param
, state
->total_param
,
8783 &state
->data
, state
->total_data
,
8784 state
->max_data_return
);
8785 END_PROFILE(Trans2_qpathinfo
);
8789 case TRANSACT2_SETPATHINFO
:
8790 case TRANSACT2_SETFILEINFO
:
8792 START_PROFILE(Trans2_setpathinfo
);
8793 call_trans2setfilepathinfo(conn
, req
, state
->call
,
8794 &state
->param
, state
->total_param
,
8795 &state
->data
, state
->total_data
,
8796 state
->max_data_return
);
8797 END_PROFILE(Trans2_setpathinfo
);
8801 case TRANSACT2_FINDNOTIFYFIRST
:
8803 START_PROFILE(Trans2_findnotifyfirst
);
8804 call_trans2findnotifyfirst(conn
, req
,
8805 &state
->param
, state
->total_param
,
8806 &state
->data
, state
->total_data
,
8807 state
->max_data_return
);
8808 END_PROFILE(Trans2_findnotifyfirst
);
8812 case TRANSACT2_FINDNOTIFYNEXT
:
8814 START_PROFILE(Trans2_findnotifynext
);
8815 call_trans2findnotifynext(conn
, req
,
8816 &state
->param
, state
->total_param
,
8817 &state
->data
, state
->total_data
,
8818 state
->max_data_return
);
8819 END_PROFILE(Trans2_findnotifynext
);
8823 case TRANSACT2_MKDIR
:
8825 START_PROFILE(Trans2_mkdir
);
8826 call_trans2mkdir(conn
, req
,
8827 &state
->param
, state
->total_param
,
8828 &state
->data
, state
->total_data
,
8829 state
->max_data_return
);
8830 END_PROFILE(Trans2_mkdir
);
8834 case TRANSACT2_GET_DFS_REFERRAL
:
8836 START_PROFILE(Trans2_get_dfs_referral
);
8837 call_trans2getdfsreferral(conn
, req
,
8838 &state
->param
, state
->total_param
,
8839 &state
->data
, state
->total_data
,
8840 state
->max_data_return
);
8841 END_PROFILE(Trans2_get_dfs_referral
);
8845 case TRANSACT2_IOCTL
:
8847 START_PROFILE(Trans2_ioctl
);
8848 call_trans2ioctl(conn
, req
,
8849 &state
->param
, state
->total_param
,
8850 &state
->data
, state
->total_data
,
8851 state
->max_data_return
);
8852 END_PROFILE(Trans2_ioctl
);
8857 /* Error in request */
8858 DEBUG(2,("Unknown request %d in trans2 call\n", state
->call
));
8859 reply_nterror(req
, NT_STATUS_NOT_IMPLEMENTED
);
8863 /****************************************************************************
8864 Reply to a SMBtrans2.
8865 ****************************************************************************/
8867 void reply_trans2(struct smb_request
*req
)
8869 connection_struct
*conn
= req
->conn
;
8874 unsigned int tran_call
;
8875 struct trans_state
*state
;
8878 START_PROFILE(SMBtrans2
);
8880 if (req
->wct
< 14) {
8881 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8882 END_PROFILE(SMBtrans2
);
8886 dsoff
= SVAL(req
->vwv
+12, 0);
8887 dscnt
= SVAL(req
->vwv
+11, 0);
8888 psoff
= SVAL(req
->vwv
+10, 0);
8889 pscnt
= SVAL(req
->vwv
+9, 0);
8890 tran_call
= SVAL(req
->vwv
+14, 0);
8892 result
= allow_new_trans(conn
->pending_trans
, req
->mid
);
8893 if (!NT_STATUS_IS_OK(result
)) {
8894 DEBUG(2, ("Got invalid trans2 request: %s\n",
8895 nt_errstr(result
)));
8896 reply_nterror(req
, result
);
8897 END_PROFILE(SMBtrans2
);
8902 switch (tran_call
) {
8903 /* List the allowed trans2 calls on IPC$ */
8904 case TRANSACT2_OPEN
:
8905 case TRANSACT2_GET_DFS_REFERRAL
:
8906 case TRANSACT2_QFILEINFO
:
8907 case TRANSACT2_QFSINFO
:
8908 case TRANSACT2_SETFSINFO
:
8911 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
8912 END_PROFILE(SMBtrans2
);
8917 if ((state
= talloc(conn
, struct trans_state
)) == NULL
) {
8918 DEBUG(0, ("talloc failed\n"));
8919 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8920 END_PROFILE(SMBtrans2
);
8924 state
->cmd
= SMBtrans2
;
8926 state
->mid
= req
->mid
;
8927 state
->vuid
= req
->vuid
;
8928 state
->setup_count
= SVAL(req
->vwv
+13, 0);
8929 state
->setup
= NULL
;
8930 state
->total_param
= SVAL(req
->vwv
+0, 0);
8931 state
->param
= NULL
;
8932 state
->total_data
= SVAL(req
->vwv
+1, 0);
8934 state
->max_param_return
= SVAL(req
->vwv
+2, 0);
8935 state
->max_data_return
= SVAL(req
->vwv
+3, 0);
8936 state
->max_setup_return
= SVAL(req
->vwv
+4, 0);
8937 state
->close_on_completion
= BITSETW(req
->vwv
+5, 0);
8938 state
->one_way
= BITSETW(req
->vwv
+5, 1);
8940 state
->call
= tran_call
;
8942 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
8943 is so as a sanity check */
8944 if (state
->setup_count
!= 1) {
8946 * Need to have rc=0 for ioctl to get job id for OS/2.
8947 * Network printing will fail if function is not successful.
8948 * Similar function in reply.c will be used if protocol
8949 * is LANMAN1.0 instead of LM1.2X002.
8950 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
8951 * outbuf doesn't have to be set(only job id is used).
8953 if ( (state
->setup_count
== 4)
8954 && (tran_call
== TRANSACT2_IOCTL
)
8955 && (SVAL(req
->vwv
+16, 0) == LMCAT_SPL
)
8956 && (SVAL(req
->vwv
+17, 0) == LMFUNC_GETJOBID
)) {
8957 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
8959 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state
->setup_count
));
8960 DEBUG(2,("Transaction is %d\n",tran_call
));
8962 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8963 END_PROFILE(SMBtrans2
);
8968 if ((dscnt
> state
->total_data
) || (pscnt
> state
->total_param
))
8971 if (state
->total_data
) {
8973 if (trans_oob(state
->total_data
, 0, dscnt
)
8974 || trans_oob(smb_len(req
->inbuf
), dsoff
, dscnt
)) {
8978 /* Can't use talloc here, the core routines do realloc on the
8979 * params and data. */
8980 state
->data
= (char *)SMB_MALLOC(state
->total_data
);
8981 if (state
->data
== NULL
) {
8982 DEBUG(0,("reply_trans2: data malloc fail for %u "
8983 "bytes !\n", (unsigned int)state
->total_data
));
8985 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8986 END_PROFILE(SMBtrans2
);
8990 memcpy(state
->data
,smb_base(req
->inbuf
)+dsoff
,dscnt
);
8993 if (state
->total_param
) {
8995 if (trans_oob(state
->total_param
, 0, pscnt
)
8996 || trans_oob(smb_len(req
->inbuf
), psoff
, pscnt
)) {
9000 /* Can't use talloc here, the core routines do realloc on the
9001 * params and data. */
9002 state
->param
= (char *)SMB_MALLOC(state
->total_param
);
9003 if (state
->param
== NULL
) {
9004 DEBUG(0,("reply_trans: param malloc fail for %u "
9005 "bytes !\n", (unsigned int)state
->total_param
));
9006 SAFE_FREE(state
->data
);
9008 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
9009 END_PROFILE(SMBtrans2
);
9013 memcpy(state
->param
,smb_base(req
->inbuf
)+psoff
,pscnt
);
9016 state
->received_data
= dscnt
;
9017 state
->received_param
= pscnt
;
9019 if ((state
->received_param
== state
->total_param
) &&
9020 (state
->received_data
== state
->total_data
)) {
9022 handle_trans2(conn
, req
, state
);
9024 SAFE_FREE(state
->data
);
9025 SAFE_FREE(state
->param
);
9027 END_PROFILE(SMBtrans2
);
9031 DLIST_ADD(conn
->pending_trans
, state
);
9033 /* We need to send an interim response then receive the rest
9034 of the parameter/data bytes */
9035 reply_outbuf(req
, 0, 0);
9036 show_msg((char *)req
->outbuf
);
9037 END_PROFILE(SMBtrans2
);
9042 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
9043 SAFE_FREE(state
->data
);
9044 SAFE_FREE(state
->param
);
9046 END_PROFILE(SMBtrans2
);
9047 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
9051 /****************************************************************************
9052 Reply to a SMBtranss2
9053 ****************************************************************************/
9055 void reply_transs2(struct smb_request
*req
)
9057 connection_struct
*conn
= req
->conn
;
9058 unsigned int pcnt
,poff
,dcnt
,doff
,pdisp
,ddisp
;
9059 struct trans_state
*state
;
9061 START_PROFILE(SMBtranss2
);
9063 show_msg((const char *)req
->inbuf
);
9065 /* Windows clients expect all replies to
9066 a transact secondary (SMBtranss2 0x33)
9067 to have a command code of transact
9068 (SMBtrans2 0x32). See bug #8989
9069 and also [MS-CIFS] section 2.2.4.47.2
9072 req
->cmd
= SMBtrans2
;
9075 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
9076 END_PROFILE(SMBtranss2
);
9080 for (state
= conn
->pending_trans
; state
!= NULL
;
9081 state
= state
->next
) {
9082 if (state
->mid
== req
->mid
) {
9087 if ((state
== NULL
) || (state
->cmd
!= SMBtrans2
)) {
9088 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
9089 END_PROFILE(SMBtranss2
);
9093 /* Revise state->total_param and state->total_data in case they have
9094 changed downwards */
9096 if (SVAL(req
->vwv
+0, 0) < state
->total_param
)
9097 state
->total_param
= SVAL(req
->vwv
+0, 0);
9098 if (SVAL(req
->vwv
+1, 0) < state
->total_data
)
9099 state
->total_data
= SVAL(req
->vwv
+1, 0);
9101 pcnt
= SVAL(req
->vwv
+2, 0);
9102 poff
= SVAL(req
->vwv
+3, 0);
9103 pdisp
= SVAL(req
->vwv
+4, 0);
9105 dcnt
= SVAL(req
->vwv
+5, 0);
9106 doff
= SVAL(req
->vwv
+6, 0);
9107 ddisp
= SVAL(req
->vwv
+7, 0);
9109 state
->received_param
+= pcnt
;
9110 state
->received_data
+= dcnt
;
9112 if ((state
->received_data
> state
->total_data
) ||
9113 (state
->received_param
> state
->total_param
))
9117 if (trans_oob(state
->total_param
, pdisp
, pcnt
)
9118 || trans_oob(smb_len(req
->inbuf
), poff
, pcnt
)) {
9121 memcpy(state
->param
+pdisp
,smb_base(req
->inbuf
)+poff
,pcnt
);
9125 if (trans_oob(state
->total_data
, ddisp
, dcnt
)
9126 || trans_oob(smb_len(req
->inbuf
), doff
, dcnt
)) {
9129 memcpy(state
->data
+ddisp
, smb_base(req
->inbuf
)+doff
,dcnt
);
9132 if ((state
->received_param
< state
->total_param
) ||
9133 (state
->received_data
< state
->total_data
)) {
9134 END_PROFILE(SMBtranss2
);
9138 handle_trans2(conn
, req
, state
);
9140 DLIST_REMOVE(conn
->pending_trans
, state
);
9141 SAFE_FREE(state
->data
);
9142 SAFE_FREE(state
->param
);
9145 END_PROFILE(SMBtranss2
);
9150 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
9151 DLIST_REMOVE(conn
->pending_trans
, state
);
9152 SAFE_FREE(state
->data
);
9153 SAFE_FREE(state
->param
);
9155 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
9156 END_PROFILE(SMBtranss2
);