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
) {
1396 /* Apply mode mask */
1397 ret
&= lp_create_mask(SNUM(conn
));
1398 /* Add in force bits */
1399 ret
|= lp_force_create_mode(SNUM(conn
));
1400 } else if (ptype
== PERM_NEW_DIR
) {
1401 ret
&= lp_dir_mask(SNUM(conn
));
1402 /* Add in force bits */
1403 ret
|= lp_force_dir_mode(SNUM(conn
));
1407 return NT_STATUS_OK
;
1410 /****************************************************************************
1411 Needed to show the msdfs symlinks as directories. Modifies psbuf
1412 to be a directory if it's a msdfs link.
1413 ****************************************************************************/
1415 static bool check_msdfs_link(connection_struct
*conn
,
1416 const char *pathname
,
1417 SMB_STRUCT_STAT
*psbuf
)
1419 int saved_errno
= errno
;
1420 if(lp_host_msdfs() &&
1421 lp_msdfs_root(SNUM(conn
)) &&
1422 is_msdfs_link(conn
, pathname
, psbuf
)) {
1424 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1427 psbuf
->st_ex_mode
= (psbuf
->st_ex_mode
& 0xFFF) | S_IFDIR
;
1428 errno
= saved_errno
;
1431 errno
= saved_errno
;
1436 /****************************************************************************
1437 Get a level dependent lanman2 dir entry.
1438 ****************************************************************************/
1440 struct smbd_dirptr_lanman2_state
{
1441 connection_struct
*conn
;
1442 uint32_t info_level
;
1443 bool check_mangled_names
;
1445 bool got_exact_match
;
1448 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX
*ctx
,
1454 struct smbd_dirptr_lanman2_state
*state
=
1455 (struct smbd_dirptr_lanman2_state
*)private_data
;
1457 char mangled_name
[13]; /* mangled 8.3 name. */
1461 /* Mangle fname if it's an illegal name. */
1462 if (mangle_must_mangle(dname
, state
->conn
->params
)) {
1463 ok
= name_to_8_3(dname
, mangled_name
,
1464 true, state
->conn
->params
);
1468 fname
= mangled_name
;
1473 got_match
= exact_match(state
->has_wild
,
1474 state
->conn
->case_sensitive
,
1476 state
->got_exact_match
= got_match
;
1478 got_match
= mask_match(fname
, mask
,
1479 state
->conn
->case_sensitive
);
1482 if(!got_match
&& state
->check_mangled_names
&&
1483 !mangle_is_8_3(fname
, false, state
->conn
->params
)) {
1485 * It turns out that NT matches wildcards against
1486 * both long *and* short names. This may explain some
1487 * of the wildcard wierdness from old DOS clients
1488 * that some people have been seeing.... JRA.
1490 /* Force the mangling into 8.3. */
1491 ok
= name_to_8_3(fname
, mangled_name
,
1492 false, state
->conn
->params
);
1497 got_match
= exact_match(state
->has_wild
,
1498 state
->conn
->case_sensitive
,
1499 mangled_name
, mask
);
1500 state
->got_exact_match
= got_match
;
1502 got_match
= mask_match(mangled_name
, mask
,
1503 state
->conn
->case_sensitive
);
1511 *_fname
= talloc_strdup(ctx
, fname
);
1512 if (*_fname
== NULL
) {
1519 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX
*ctx
,
1521 struct smb_filename
*smb_fname
,
1524 struct smbd_dirptr_lanman2_state
*state
=
1525 (struct smbd_dirptr_lanman2_state
*)private_data
;
1526 bool ms_dfs_link
= false;
1529 if (INFO_LEVEL_IS_UNIX(state
->info_level
)) {
1530 if (SMB_VFS_LSTAT(state
->conn
, smb_fname
) != 0) {
1531 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1532 "Couldn't lstat [%s] (%s)\n",
1533 smb_fname_str_dbg(smb_fname
),
1537 } else if (!VALID_STAT(smb_fname
->st
) &&
1538 SMB_VFS_STAT(state
->conn
, smb_fname
) != 0) {
1539 /* Needed to show the msdfs symlinks as
1542 ms_dfs_link
= check_msdfs_link(state
->conn
,
1543 smb_fname
->base_name
,
1546 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1547 "Couldn't stat [%s] (%s)\n",
1548 smb_fname_str_dbg(smb_fname
),
1555 mode
= dos_mode_msdfs(state
->conn
, smb_fname
);
1557 mode
= dos_mode(state
->conn
, smb_fname
);
1564 static bool smbd_marshall_dir_entry(TALLOC_CTX
*ctx
,
1565 connection_struct
*conn
,
1567 uint32_t info_level
,
1568 struct ea_list
*name_list
,
1569 bool check_mangled_names
,
1570 bool requires_resume_key
,
1573 const struct smb_filename
*smb_fname
,
1574 int space_remaining
,
1581 uint64_t *last_entry_off
)
1583 char *p
, *q
, *pdata
= *ppdata
;
1585 uint64_t file_size
= 0;
1586 uint64_t allocation_size
= 0;
1587 uint64_t file_index
= 0;
1589 struct timespec mdate_ts
, adate_ts
, cdate_ts
, create_date_ts
;
1590 time_t mdate
= (time_t)0, adate
= (time_t)0, create_date
= (time_t)0;
1592 char *last_entry_ptr
;
1597 *out_of_space
= false;
1599 ZERO_STRUCT(mdate_ts
);
1600 ZERO_STRUCT(adate_ts
);
1601 ZERO_STRUCT(create_date_ts
);
1602 ZERO_STRUCT(cdate_ts
);
1604 if (!(mode
& FILE_ATTRIBUTE_DIRECTORY
)) {
1605 file_size
= get_file_size_stat(&smb_fname
->st
);
1607 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
, NULL
, &smb_fname
->st
);
1609 file_index
= get_FileIndex(conn
, &smb_fname
->st
);
1611 mdate_ts
= smb_fname
->st
.st_ex_mtime
;
1612 adate_ts
= smb_fname
->st
.st_ex_atime
;
1613 create_date_ts
= get_create_timespec(conn
, NULL
, smb_fname
);
1614 cdate_ts
= get_change_timespec(conn
, NULL
, smb_fname
);
1616 if (lp_dos_filetime_resolution(SNUM(conn
))) {
1617 dos_filetime_timespec(&create_date_ts
);
1618 dos_filetime_timespec(&mdate_ts
);
1619 dos_filetime_timespec(&adate_ts
);
1620 dos_filetime_timespec(&cdate_ts
);
1623 create_date
= convert_timespec_to_time_t(create_date_ts
);
1624 mdate
= convert_timespec_to_time_t(mdate_ts
);
1625 adate
= convert_timespec_to_time_t(adate_ts
);
1627 /* align the record */
1628 SMB_ASSERT(align
>= 1);
1630 off
= (int)PTR_DIFF(pdata
, base_data
);
1631 pad
= (off
+ (align
-1)) & ~(align
-1);
1634 if (pad
&& pad
> space_remaining
) {
1635 *out_of_space
= true;
1636 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1637 "for padding (wanted %u, had %d)\n",
1640 return false; /* Not finished - just out of space */
1644 /* initialize padding to 0 */
1646 memset(pdata
, 0, pad
);
1648 space_remaining
-= pad
;
1650 DEBUG(10,("smbd_marshall_dir_entry: space_remaining = %d\n",
1660 switch (info_level
) {
1661 case SMB_FIND_INFO_STANDARD
:
1662 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1663 if(requires_resume_key
) {
1667 srv_put_dos_date2(p
,0,create_date
);
1668 srv_put_dos_date2(p
,4,adate
);
1669 srv_put_dos_date2(p
,8,mdate
);
1670 SIVAL(p
,12,(uint32
)file_size
);
1671 SIVAL(p
,16,(uint32
)allocation_size
);
1675 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1676 p
+= ucs2_align(base_data
, p
, 0);
1678 len
= srvstr_push(base_data
, flags2
, p
,
1679 fname
, PTR_DIFF(end_data
, p
),
1681 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1683 SCVAL(nameptr
, -1, len
- 2);
1685 SCVAL(nameptr
, -1, 0);
1689 SCVAL(nameptr
, -1, len
- 1);
1691 SCVAL(nameptr
, -1, 0);
1697 case SMB_FIND_EA_SIZE
:
1698 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
1699 if (requires_resume_key
) {
1703 srv_put_dos_date2(p
,0,create_date
);
1704 srv_put_dos_date2(p
,4,adate
);
1705 srv_put_dos_date2(p
,8,mdate
);
1706 SIVAL(p
,12,(uint32
)file_size
);
1707 SIVAL(p
,16,(uint32
)allocation_size
);
1710 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
1712 SIVAL(p
,22,ea_size
); /* Extended attributes */
1716 len
= srvstr_push(base_data
, flags2
,
1717 p
, fname
, PTR_DIFF(end_data
, p
),
1718 STR_TERMINATE
| STR_NOALIGN
);
1719 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1732 SCVAL(nameptr
,0,len
);
1734 SCVAL(p
,0,0); p
+= 1; /* Extra zero byte ? - why.. */
1737 case SMB_FIND_EA_LIST
:
1739 struct ea_list
*file_list
= NULL
;
1743 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
1747 if (requires_resume_key
) {
1751 srv_put_dos_date2(p
,0,create_date
);
1752 srv_put_dos_date2(p
,4,adate
);
1753 srv_put_dos_date2(p
,8,mdate
);
1754 SIVAL(p
,12,(uint32
)file_size
);
1755 SIVAL(p
,16,(uint32
)allocation_size
);
1757 p
+= 22; /* p now points to the EA area. */
1759 status
= get_ea_list_from_file(ctx
, conn
, NULL
,
1761 &ea_len
, &file_list
);
1762 if (!NT_STATUS_IS_OK(status
)) {
1765 name_list
= ea_list_union(name_list
, file_list
, &ea_len
);
1767 /* We need to determine if this entry will fit in the space available. */
1768 /* Max string size is 255 bytes. */
1769 if (PTR_DIFF(p
+ 255 + ea_len
,pdata
) > space_remaining
) {
1770 *out_of_space
= true;
1771 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1772 "(wanted %u, had %d)\n",
1773 (unsigned int)PTR_DIFF(p
+ 255 + ea_len
,pdata
),
1775 return False
; /* Not finished - just out of space */
1778 /* Push the ea_data followed by the name. */
1779 p
+= fill_ea_buffer(ctx
, p
, space_remaining
, conn
, name_list
);
1781 len
= srvstr_push(base_data
, flags2
,
1782 p
+ 1, fname
, PTR_DIFF(end_data
, p
+1),
1783 STR_TERMINATE
| STR_NOALIGN
);
1784 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1797 SCVAL(nameptr
,0,len
);
1799 SCVAL(p
,0,0); p
+= 1; /* Extra zero byte ? - why.. */
1803 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
1804 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1805 was_8_3
= mangle_is_8_3(fname
, True
, conn
->params
);
1807 SIVAL(p
,0,reskey
); p
+= 4;
1808 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
1809 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
1810 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
1811 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
1812 SOFF_T(p
,0,file_size
); p
+= 8;
1813 SOFF_T(p
,0,allocation_size
); p
+= 8;
1814 SIVAL(p
,0,mode
); p
+= 4;
1815 q
= p
; p
+= 4; /* q is placeholder for name length. */
1816 if (mode
& FILE_ATTRIBUTE_REPARSE_POINT
) {
1817 SIVAL(p
, 0, IO_REPARSE_TAG_DFS
);
1819 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
1821 SIVAL(p
,0,ea_size
); /* Extended attributes */
1824 /* Clear the short name buffer. This is
1825 * IMPORTANT as not doing so will trigger
1826 * a Win2k client bug. JRA.
1828 if (!was_8_3
&& check_mangled_names
) {
1829 char mangled_name
[13]; /* mangled 8.3 name. */
1830 if (!name_to_8_3(fname
,mangled_name
,True
,
1832 /* Error - mangle failed ! */
1833 memset(mangled_name
,'\0',12);
1835 mangled_name
[12] = 0;
1836 len
= srvstr_push(base_data
, flags2
,
1837 p
+2, mangled_name
, 24,
1838 STR_UPPER
|STR_UNICODE
);
1840 memset(p
+ 2 + len
,'\0',24 - len
);
1847 len
= srvstr_push(base_data
, flags2
, p
,
1848 fname
, PTR_DIFF(end_data
, p
),
1849 STR_TERMINATE_ASCII
);
1853 len
= PTR_DIFF(p
, pdata
);
1854 pad
= (len
+ (align
-1)) & ~(align
-1);
1856 * offset to the next entry, the caller
1857 * will overwrite it for the last entry
1858 * that's why we always include the padding
1862 * set padding to zero
1865 memset(p
, 0, pad
- len
);
1872 case SMB_FIND_FILE_DIRECTORY_INFO
:
1873 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1875 SIVAL(p
,0,reskey
); p
+= 4;
1876 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
1877 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
1878 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
1879 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
1880 SOFF_T(p
,0,file_size
); p
+= 8;
1881 SOFF_T(p
,0,allocation_size
); p
+= 8;
1882 SIVAL(p
,0,mode
); p
+= 4;
1883 len
= srvstr_push(base_data
, flags2
,
1884 p
+ 4, fname
, PTR_DIFF(end_data
, p
+4),
1885 STR_TERMINATE_ASCII
);
1889 len
= PTR_DIFF(p
, pdata
);
1890 pad
= (len
+ (align
-1)) & ~(align
-1);
1892 * offset to the next entry, the caller
1893 * will overwrite it for the last entry
1894 * that's why we always include the padding
1898 * set padding to zero
1901 memset(p
, 0, pad
- len
);
1908 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
1909 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1911 SIVAL(p
,0,reskey
); p
+= 4;
1912 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
1913 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
1914 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
1915 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
1916 SOFF_T(p
,0,file_size
); p
+= 8;
1917 SOFF_T(p
,0,allocation_size
); p
+= 8;
1918 SIVAL(p
,0,mode
); p
+= 4;
1919 q
= p
; p
+= 4; /* q is placeholder for name length. */
1921 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
1923 SIVAL(p
,0,ea_size
); /* Extended attributes */
1926 len
= srvstr_push(base_data
, flags2
, p
,
1927 fname
, PTR_DIFF(end_data
, p
),
1928 STR_TERMINATE_ASCII
);
1932 len
= PTR_DIFF(p
, pdata
);
1933 pad
= (len
+ (align
-1)) & ~(align
-1);
1935 * offset to the next entry, the caller
1936 * will overwrite it for the last entry
1937 * that's why we always include the padding
1941 * set padding to zero
1944 memset(p
, 0, pad
- len
);
1951 case SMB_FIND_FILE_NAMES_INFO
:
1952 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1954 SIVAL(p
,0,reskey
); p
+= 4;
1956 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1957 acl on a dir (tridge) */
1958 len
= srvstr_push(base_data
, flags2
, p
,
1959 fname
, PTR_DIFF(end_data
, p
),
1960 STR_TERMINATE_ASCII
);
1964 len
= PTR_DIFF(p
, pdata
);
1965 pad
= (len
+ (align
-1)) & ~(align
-1);
1967 * offset to the next entry, the caller
1968 * will overwrite it for the last entry
1969 * that's why we always include the padding
1973 * set padding to zero
1976 memset(p
, 0, pad
- len
);
1983 case SMB_FIND_ID_FULL_DIRECTORY_INFO
:
1984 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1986 SIVAL(p
,0,reskey
); p
+= 4;
1987 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
1988 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
1989 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
1990 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
1991 SOFF_T(p
,0,file_size
); p
+= 8;
1992 SOFF_T(p
,0,allocation_size
); p
+= 8;
1993 SIVAL(p
,0,mode
); p
+= 4;
1994 q
= p
; p
+= 4; /* q is placeholder for name length. */
1995 if (mode
& FILE_ATTRIBUTE_REPARSE_POINT
) {
1996 SIVAL(p
, 0, IO_REPARSE_TAG_DFS
);
1998 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
2000 SIVAL(p
,0,ea_size
); /* Extended attributes */
2003 SIVAL(p
,0,0); p
+= 4; /* Unknown - reserved ? */
2004 SBVAL(p
,0,file_index
); p
+= 8;
2005 len
= srvstr_push(base_data
, flags2
, p
,
2006 fname
, PTR_DIFF(end_data
, p
),
2007 STR_TERMINATE_ASCII
);
2011 len
= PTR_DIFF(p
, pdata
);
2012 pad
= (len
+ (align
-1)) & ~(align
-1);
2014 * offset to the next entry, the caller
2015 * will overwrite it for the last entry
2016 * that's why we always include the padding
2020 * set padding to zero
2023 memset(p
, 0, pad
- len
);
2030 case SMB_FIND_ID_BOTH_DIRECTORY_INFO
:
2031 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
2032 was_8_3
= mangle_is_8_3(fname
, True
, conn
->params
);
2034 SIVAL(p
,0,reskey
); p
+= 4;
2035 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
2036 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
2037 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
2038 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
2039 SOFF_T(p
,0,file_size
); p
+= 8;
2040 SOFF_T(p
,0,allocation_size
); p
+= 8;
2041 SIVAL(p
,0,mode
); p
+= 4;
2042 q
= p
; p
+= 4; /* q is placeholder for name length */
2043 if (mode
& FILE_ATTRIBUTE_REPARSE_POINT
) {
2044 SIVAL(p
, 0, IO_REPARSE_TAG_DFS
);
2046 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
2048 SIVAL(p
,0,ea_size
); /* Extended attributes */
2051 /* Clear the short name buffer. This is
2052 * IMPORTANT as not doing so will trigger
2053 * a Win2k client bug. JRA.
2055 if (!was_8_3
&& check_mangled_names
) {
2056 char mangled_name
[13]; /* mangled 8.3 name. */
2057 if (!name_to_8_3(fname
,mangled_name
,True
,
2059 /* Error - mangle failed ! */
2060 memset(mangled_name
,'\0',12);
2062 mangled_name
[12] = 0;
2063 len
= srvstr_push(base_data
, flags2
,
2064 p
+2, mangled_name
, 24,
2065 STR_UPPER
|STR_UNICODE
);
2068 memset(p
+ 2 + len
,'\0',24 - len
);
2075 SSVAL(p
,0,0); p
+= 2; /* Reserved ? */
2076 SBVAL(p
,0,file_index
); p
+= 8;
2077 len
= srvstr_push(base_data
, flags2
, p
,
2078 fname
, PTR_DIFF(end_data
, p
),
2079 STR_TERMINATE_ASCII
);
2083 len
= PTR_DIFF(p
, pdata
);
2084 pad
= (len
+ (align
-1)) & ~(align
-1);
2086 * offset to the next entry, the caller
2087 * will overwrite it for the last entry
2088 * that's why we always include the padding
2092 * set padding to zero
2095 memset(p
, 0, pad
- len
);
2102 /* CIFS UNIX Extension. */
2104 case SMB_FIND_FILE_UNIX
:
2105 case SMB_FIND_FILE_UNIX_INFO2
:
2107 SIVAL(p
,0,reskey
); p
+= 4; /* Used for continuing search. */
2109 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
2111 if (info_level
== SMB_FIND_FILE_UNIX
) {
2112 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
2113 p
= store_file_unix_basic(conn
, p
,
2114 NULL
, &smb_fname
->st
);
2115 len
= srvstr_push(base_data
, flags2
, p
,
2116 fname
, PTR_DIFF(end_data
, p
),
2119 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
2120 p
= store_file_unix_basic_info2(conn
, p
,
2121 NULL
, &smb_fname
->st
);
2124 len
= srvstr_push(base_data
, flags2
, p
, fname
,
2125 PTR_DIFF(end_data
, p
), 0);
2126 SIVAL(nameptr
, 0, len
);
2131 len
= PTR_DIFF(p
, pdata
);
2132 pad
= (len
+ (align
-1)) & ~(align
-1);
2134 * offset to the next entry, the caller
2135 * will overwrite it for the last entry
2136 * that's why we always include the padding
2140 * set padding to zero
2143 memset(p
, 0, pad
- len
);
2148 /* End of SMB_QUERY_FILE_UNIX_BASIC */
2156 if (PTR_DIFF(p
,pdata
) > space_remaining
) {
2157 *out_of_space
= true;
2158 DEBUG(9,("smbd_marshall_dir_entry: out of space "
2159 "(wanted %u, had %d)\n",
2160 (unsigned int)PTR_DIFF(p
,pdata
),
2162 return false; /* Not finished - just out of space */
2165 /* Setup the last entry pointer, as an offset from base_data */
2166 *last_entry_off
= PTR_DIFF(last_entry_ptr
,base_data
);
2167 /* Advance the data pointer to the next slot */
2173 bool smbd_dirptr_lanman2_entry(TALLOC_CTX
*ctx
,
2174 connection_struct
*conn
,
2175 struct dptr_struct
*dirptr
,
2177 const char *path_mask
,
2180 int requires_resume_key
,
2188 int space_remaining
,
2190 bool *got_exact_match
,
2191 int *_last_entry_off
,
2192 struct ea_list
*name_list
)
2195 const char *mask
= NULL
;
2196 long prev_dirpos
= 0;
2199 struct smb_filename
*smb_fname
= NULL
;
2200 struct smbd_dirptr_lanman2_state state
;
2202 uint64_t last_entry_off
= 0;
2206 state
.info_level
= info_level
;
2207 state
.check_mangled_names
= lp_manglednames(conn
->params
);
2208 state
.has_wild
= dptr_has_wild(dirptr
);
2209 state
.got_exact_match
= false;
2211 *out_of_space
= false;
2212 *got_exact_match
= false;
2214 p
= strrchr_m(path_mask
,'/');
2225 ok
= smbd_dirptr_get_entry(ctx
,
2231 smbd_dirptr_lanman2_match_fn
,
2232 smbd_dirptr_lanman2_mode_fn
,
2242 *got_exact_match
= state
.got_exact_match
;
2244 ok
= smbd_marshall_dir_entry(ctx
,
2249 state
.check_mangled_names
,
2250 requires_resume_key
,
2263 TALLOC_FREE(smb_fname
);
2264 if (*out_of_space
) {
2265 dptr_SeekDir(dirptr
, prev_dirpos
);
2272 *_last_entry_off
= last_entry_off
;
2276 static bool get_lanman2_dir_entry(TALLOC_CTX
*ctx
,
2277 connection_struct
*conn
,
2278 struct dptr_struct
*dirptr
,
2280 const char *path_mask
,
2283 bool requires_resume_key
,
2289 int space_remaining
,
2291 bool *got_exact_match
,
2292 int *last_entry_off
,
2293 struct ea_list
*name_list
)
2296 const bool do_pad
= true;
2298 if (info_level
>= 1 && info_level
<= 3) {
2299 /* No alignment on earlier info levels. */
2303 return smbd_dirptr_lanman2_entry(ctx
, conn
, dirptr
, flags2
,
2304 path_mask
, dirtype
, info_level
,
2305 requires_resume_key
, dont_descend
, ask_sharemode
,
2307 ppdata
, base_data
, end_data
,
2309 out_of_space
, got_exact_match
,
2310 last_entry_off
, name_list
);
2313 /****************************************************************************
2314 Reply to a TRANS2_FINDFIRST.
2315 ****************************************************************************/
2317 static void call_trans2findfirst(connection_struct
*conn
,
2318 struct smb_request
*req
,
2319 char **pparams
, int total_params
,
2320 char **ppdata
, int total_data
,
2321 unsigned int max_data_bytes
)
2323 /* We must be careful here that we don't return more than the
2324 allowed number of data bytes. If this means returning fewer than
2325 maxentries then so be it. We assume that the redirector has
2326 enough room for the fixed number of parameter bytes it has
2328 struct smb_filename
*smb_dname
= NULL
;
2329 char *params
= *pparams
;
2330 char *pdata
= *ppdata
;
2334 uint16 findfirst_flags
;
2335 bool close_after_first
;
2337 bool requires_resume_key
;
2339 char *directory
= NULL
;
2342 int last_entry_off
=0;
2346 bool finished
= False
;
2347 bool dont_descend
= False
;
2348 bool out_of_space
= False
;
2349 int space_remaining
;
2350 bool mask_contains_wcard
= False
;
2351 struct ea_list
*ea_list
= NULL
;
2352 NTSTATUS ntstatus
= NT_STATUS_OK
;
2353 bool ask_sharemode
= lp_parm_bool(SNUM(conn
), "smbd", "search ask sharemode", true);
2354 TALLOC_CTX
*ctx
= talloc_tos();
2355 struct dptr_struct
*dirptr
= NULL
;
2356 struct smbd_server_connection
*sconn
= req
->sconn
;
2357 uint32_t ucf_flags
= (UCF_SAVE_LCOMP
| UCF_ALWAYS_ALLOW_WCARD_LCOMP
);
2358 bool backup_priv
= false;
2360 if (total_params
< 13) {
2361 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2365 dirtype
= SVAL(params
,0);
2366 maxentries
= SVAL(params
,2);
2367 findfirst_flags
= SVAL(params
,4);
2368 close_after_first
= (findfirst_flags
& FLAG_TRANS2_FIND_CLOSE
);
2369 close_if_end
= (findfirst_flags
& FLAG_TRANS2_FIND_CLOSE_IF_END
);
2370 requires_resume_key
= (findfirst_flags
& FLAG_TRANS2_FIND_REQUIRE_RESUME
);
2371 backup_priv
= ((findfirst_flags
& FLAG_TRANS2_FIND_BACKUP_INTENT
) &&
2372 security_token_has_privilege(get_current_nttok(conn
),
2375 info_level
= SVAL(params
,6);
2377 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2378 close_if_end = %d requires_resume_key = %d backup_priv = %d level = 0x%x, max_data_bytes = %d\n",
2379 (unsigned int)dirtype
, maxentries
, close_after_first
, close_if_end
, requires_resume_key
,
2381 info_level
, max_data_bytes
));
2384 /* W2K3 seems to treat zero as 1. */
2388 switch (info_level
) {
2389 case SMB_FIND_INFO_STANDARD
:
2390 case SMB_FIND_EA_SIZE
:
2391 case SMB_FIND_EA_LIST
:
2392 case SMB_FIND_FILE_DIRECTORY_INFO
:
2393 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
2394 case SMB_FIND_FILE_NAMES_INFO
:
2395 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
2396 case SMB_FIND_ID_FULL_DIRECTORY_INFO
:
2397 case SMB_FIND_ID_BOTH_DIRECTORY_INFO
:
2399 case SMB_FIND_FILE_UNIX
:
2400 case SMB_FIND_FILE_UNIX_INFO2
:
2401 /* Always use filesystem for UNIX mtime query. */
2402 ask_sharemode
= false;
2403 if (!lp_unix_extensions()) {
2404 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2407 ucf_flags
|= UCF_UNIX_NAME_LOOKUP
;
2410 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2414 srvstr_get_path_wcard(ctx
, params
, req
->flags2
, &directory
,
2415 params
+12, total_params
- 12,
2416 STR_TERMINATE
, &ntstatus
, &mask_contains_wcard
);
2417 if (!NT_STATUS_IS_OK(ntstatus
)) {
2418 reply_nterror(req
, ntstatus
);
2424 ntstatus
= filename_convert_with_privilege(ctx
,
2429 &mask_contains_wcard
,
2432 ntstatus
= filename_convert(ctx
, conn
,
2433 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
2436 &mask_contains_wcard
,
2440 if (!NT_STATUS_IS_OK(ntstatus
)) {
2441 if (NT_STATUS_EQUAL(ntstatus
,NT_STATUS_PATH_NOT_COVERED
)) {
2442 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
2443 ERRSRV
, ERRbadpath
);
2446 reply_nterror(req
, ntstatus
);
2450 mask
= smb_dname
->original_lcomp
;
2452 directory
= smb_dname
->base_name
;
2454 p
= strrchr_m(directory
,'/');
2456 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2457 if((directory
[0] == '.') && (directory
[1] == '\0')) {
2458 mask
= talloc_strdup(ctx
,"*");
2460 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2463 mask_contains_wcard
= True
;
2469 if (p
== NULL
|| p
== directory
) {
2470 /* Ensure we don't have a directory name of "". */
2471 directory
= talloc_strdup(talloc_tos(), ".");
2473 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2478 DEBUG(5,("dir=%s, mask = %s\n",directory
, mask
));
2480 if (info_level
== SMB_FIND_EA_LIST
) {
2483 if (total_data
< 4) {
2484 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2488 ea_size
= IVAL(pdata
,0);
2489 if (ea_size
!= total_data
) {
2490 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2491 total_data=%u (should be %u)\n", (unsigned int)total_data
, (unsigned int)IVAL(pdata
,0) ));
2492 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2496 if (!lp_ea_support(SNUM(conn
))) {
2497 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
2501 /* Pull out the list of names. */
2502 ea_list
= read_ea_name_list(ctx
, pdata
+ 4, ea_size
- 4);
2504 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2509 if (max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
< max_data_bytes
) {
2510 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2514 *ppdata
= (char *)SMB_REALLOC(
2515 *ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
2516 if(*ppdata
== NULL
) {
2517 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2521 data_end
= pdata
+ max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
- 1;
2523 /* Realloc the params space */
2524 *pparams
= (char *)SMB_REALLOC(*pparams
, 10);
2525 if (*pparams
== NULL
) {
2526 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2531 /* Save the wildcard match and attribs we are using on this directory -
2532 needed as lanman2 assumes these are being saved between calls */
2534 ntstatus
= dptr_create(conn
,
2542 mask_contains_wcard
,
2546 if (!NT_STATUS_IS_OK(ntstatus
)) {
2547 reply_nterror(req
, ntstatus
);
2552 /* Remember this in case we have
2553 to do a findnext. */
2554 dptr_set_priv(dirptr
);
2557 dptr_num
= dptr_dnum(dirptr
);
2558 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num
, mask
, dirtype
));
2560 /* Initialize per TRANS2_FIND_FIRST operation data */
2561 dptr_init_search_op(dirptr
);
2563 /* We don't need to check for VOL here as this is returned by
2564 a different TRANS2 call. */
2566 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2567 directory
,lp_dontdescend(ctx
, SNUM(conn
))));
2568 if (in_list(directory
,lp_dontdescend(ctx
, SNUM(conn
)),conn
->case_sensitive
))
2569 dont_descend
= True
;
2572 space_remaining
= max_data_bytes
;
2573 out_of_space
= False
;
2575 for (i
=0;(i
<maxentries
) && !finished
&& !out_of_space
;i
++) {
2576 bool got_exact_match
= False
;
2578 /* this is a heuristic to avoid seeking the dirptr except when
2579 absolutely necessary. It allows for a filename of about 40 chars */
2580 if (space_remaining
< DIRLEN_GUESS
&& numentries
> 0) {
2581 out_of_space
= True
;
2584 finished
= !get_lanman2_dir_entry(ctx
,
2588 mask
,dirtype
,info_level
,
2589 requires_resume_key
,dont_descend
,
2592 space_remaining
, &out_of_space
,
2594 &last_entry_off
, ea_list
);
2597 if (finished
&& out_of_space
)
2600 if (!finished
&& !out_of_space
)
2604 * As an optimisation if we know we aren't looking
2605 * for a wildcard name (ie. the name matches the wildcard exactly)
2606 * then we can finish on any (first) match.
2607 * This speeds up large directory searches. JRA.
2613 /* Ensure space_remaining never goes -ve. */
2614 if (PTR_DIFF(p
,pdata
) > max_data_bytes
) {
2615 space_remaining
= 0;
2616 out_of_space
= true;
2618 space_remaining
= max_data_bytes
- PTR_DIFF(p
,pdata
);
2622 /* Check if we can close the dirptr */
2623 if(close_after_first
|| (finished
&& close_if_end
)) {
2624 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num
));
2625 dptr_close(sconn
, &dptr_num
);
2629 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2630 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2631 * the protocol level is less than NT1. Tested with smbclient. JRA.
2632 * This should fix the OS/2 client bug #2335.
2635 if(numentries
== 0) {
2636 dptr_close(sconn
, &dptr_num
);
2637 if (get_Protocol() < PROTOCOL_NT1
) {
2638 reply_force_doserror(req
, ERRDOS
, ERRnofiles
);
2641 reply_botherror(req
, NT_STATUS_NO_SUCH_FILE
,
2642 ERRDOS
, ERRbadfile
);
2647 /* At this point pdata points to numentries directory entries. */
2649 /* Set up the return parameter block */
2650 SSVAL(params
,0,dptr_num
);
2651 SSVAL(params
,2,numentries
);
2652 SSVAL(params
,4,finished
);
2653 SSVAL(params
,6,0); /* Never an EA error */
2654 SSVAL(params
,8,last_entry_off
);
2656 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 10, pdata
, PTR_DIFF(p
,pdata
),
2659 if ((! *directory
) && dptr_path(sconn
, dptr_num
)) {
2660 directory
= talloc_strdup(talloc_tos(),dptr_path(sconn
, dptr_num
));
2662 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2666 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2667 smb_fn_name(req
->cmd
),
2668 mask
, directory
, dirtype
, numentries
) );
2671 * Force a name mangle here to ensure that the
2672 * mask as an 8.3 name is top of the mangled cache.
2673 * The reasons for this are subtle. Don't remove
2674 * this code unless you know what you are doing
2675 * (see PR#13758). JRA.
2678 if(!mangle_is_8_3_wildcards( mask
, False
, conn
->params
)) {
2679 char mangled_name
[13];
2680 name_to_8_3(mask
, mangled_name
, True
, conn
->params
);
2688 TALLOC_FREE(smb_dname
);
2692 /****************************************************************************
2693 Reply to a TRANS2_FINDNEXT.
2694 ****************************************************************************/
2696 static void call_trans2findnext(connection_struct
*conn
,
2697 struct smb_request
*req
,
2698 char **pparams
, int total_params
,
2699 char **ppdata
, int total_data
,
2700 unsigned int max_data_bytes
)
2702 /* We must be careful here that we don't return more than the
2703 allowed number of data bytes. If this means returning fewer than
2704 maxentries then so be it. We assume that the redirector has
2705 enough room for the fixed number of parameter bytes it has
2707 char *params
= *pparams
;
2708 char *pdata
= *ppdata
;
2714 uint16 findnext_flags
;
2715 bool close_after_request
;
2717 bool requires_resume_key
;
2719 bool mask_contains_wcard
= False
;
2720 char *resume_name
= NULL
;
2721 const char *mask
= NULL
;
2722 const char *directory
= NULL
;
2726 int i
, last_entry_off
=0;
2727 bool finished
= False
;
2728 bool dont_descend
= False
;
2729 bool out_of_space
= False
;
2730 int space_remaining
;
2731 struct ea_list
*ea_list
= NULL
;
2732 NTSTATUS ntstatus
= NT_STATUS_OK
;
2733 bool ask_sharemode
= lp_parm_bool(SNUM(conn
), "smbd", "search ask sharemode", true);
2734 TALLOC_CTX
*ctx
= talloc_tos();
2735 struct dptr_struct
*dirptr
;
2736 struct smbd_server_connection
*sconn
= req
->sconn
;
2737 bool backup_priv
= false;
2739 if (total_params
< 13) {
2740 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2744 dptr_num
= SVAL(params
,0);
2745 maxentries
= SVAL(params
,2);
2746 info_level
= SVAL(params
,4);
2747 resume_key
= IVAL(params
,6);
2748 findnext_flags
= SVAL(params
,10);
2749 close_after_request
= (findnext_flags
& FLAG_TRANS2_FIND_CLOSE
);
2750 close_if_end
= (findnext_flags
& FLAG_TRANS2_FIND_CLOSE_IF_END
);
2751 requires_resume_key
= (findnext_flags
& FLAG_TRANS2_FIND_REQUIRE_RESUME
);
2752 continue_bit
= (findnext_flags
& FLAG_TRANS2_FIND_CONTINUE
);
2754 if (!continue_bit
) {
2755 /* We only need resume_name if continue_bit is zero. */
2756 srvstr_get_path_wcard(ctx
, params
, req
->flags2
, &resume_name
,
2758 total_params
- 12, STR_TERMINATE
, &ntstatus
,
2759 &mask_contains_wcard
);
2760 if (!NT_STATUS_IS_OK(ntstatus
)) {
2761 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2762 complain (it thinks we're asking for the directory above the shared
2763 path or an invalid name). Catch this as the resume name is only compared, never used in
2764 a file access. JRA. */
2765 srvstr_pull_talloc(ctx
, params
, req
->flags2
,
2766 &resume_name
, params
+12,
2770 if (!resume_name
|| !(ISDOT(resume_name
) || ISDOTDOT(resume_name
))) {
2771 reply_nterror(req
, ntstatus
);
2777 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2778 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2779 resume_key = %d resume name = %s continue=%d level = %d\n",
2780 dptr_num
, max_data_bytes
, maxentries
, close_after_request
, close_if_end
,
2781 requires_resume_key
, resume_key
,
2782 resume_name
? resume_name
: "(NULL)", continue_bit
, info_level
));
2785 /* W2K3 seems to treat zero as 1. */
2789 switch (info_level
) {
2790 case SMB_FIND_INFO_STANDARD
:
2791 case SMB_FIND_EA_SIZE
:
2792 case SMB_FIND_EA_LIST
:
2793 case SMB_FIND_FILE_DIRECTORY_INFO
:
2794 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
2795 case SMB_FIND_FILE_NAMES_INFO
:
2796 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
2797 case SMB_FIND_ID_FULL_DIRECTORY_INFO
:
2798 case SMB_FIND_ID_BOTH_DIRECTORY_INFO
:
2800 case SMB_FIND_FILE_UNIX
:
2801 case SMB_FIND_FILE_UNIX_INFO2
:
2802 /* Always use filesystem for UNIX mtime query. */
2803 ask_sharemode
= false;
2804 if (!lp_unix_extensions()) {
2805 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2810 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2814 if (info_level
== SMB_FIND_EA_LIST
) {
2817 if (total_data
< 4) {
2818 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2822 ea_size
= IVAL(pdata
,0);
2823 if (ea_size
!= total_data
) {
2824 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2825 total_data=%u (should be %u)\n", (unsigned int)total_data
, (unsigned int)IVAL(pdata
,0) ));
2826 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2830 if (!lp_ea_support(SNUM(conn
))) {
2831 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
2835 /* Pull out the list of names. */
2836 ea_list
= read_ea_name_list(ctx
, pdata
+ 4, ea_size
- 4);
2838 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2843 if (max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
< max_data_bytes
) {
2844 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2848 *ppdata
= (char *)SMB_REALLOC(
2849 *ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
2850 if(*ppdata
== NULL
) {
2851 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2856 data_end
= pdata
+ max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
- 1;
2858 /* Realloc the params space */
2859 *pparams
= (char *)SMB_REALLOC(*pparams
, 6*SIZEOFWORD
);
2860 if(*pparams
== NULL
) {
2861 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2867 /* Check that the dptr is valid */
2868 if(!(dirptr
= dptr_fetch_lanman2(sconn
, dptr_num
))) {
2869 reply_nterror(req
, STATUS_NO_MORE_FILES
);
2873 directory
= dptr_path(sconn
, dptr_num
);
2875 /* Get the wildcard mask from the dptr */
2876 if((mask
= dptr_wcard(sconn
, dptr_num
))== NULL
) {
2877 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num
));
2878 reply_nterror(req
, STATUS_NO_MORE_FILES
);
2882 /* Get the attr mask from the dptr */
2883 dirtype
= dptr_attr(sconn
, dptr_num
);
2885 backup_priv
= dptr_get_priv(dirptr
);
2887 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld) "
2888 "backup_priv = %d\n",
2889 dptr_num
, mask
, dirtype
,
2891 dptr_TellDir(dirptr
),
2894 /* Initialize per TRANS2_FIND_NEXT operation data */
2895 dptr_init_search_op(dirptr
);
2897 /* We don't need to check for VOL here as this is returned by
2898 a different TRANS2 call. */
2900 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2901 directory
,lp_dontdescend(ctx
, SNUM(conn
))));
2902 if (in_list(directory
,lp_dontdescend(ctx
, SNUM(conn
)),conn
->case_sensitive
))
2903 dont_descend
= True
;
2906 space_remaining
= max_data_bytes
;
2907 out_of_space
= False
;
2914 * Seek to the correct position. We no longer use the resume key but
2915 * depend on the last file name instead.
2918 if(!continue_bit
&& resume_name
&& *resume_name
) {
2921 long current_pos
= 0;
2923 * Remember, name_to_8_3 is called by
2924 * get_lanman2_dir_entry(), so the resume name
2925 * could be mangled. Ensure we check the unmangled name.
2928 if (mangle_is_mangled(resume_name
, conn
->params
)) {
2929 char *new_resume_name
= NULL
;
2930 mangle_lookup_name_from_8_3(ctx
,
2934 if (new_resume_name
) {
2935 resume_name
= new_resume_name
;
2940 * Fix for NT redirector problem triggered by resume key indexes
2941 * changing between directory scans. We now return a resume key of 0
2942 * and instead look for the filename to continue from (also given
2943 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2944 * findfirst/findnext (as is usual) then the directory pointer
2945 * should already be at the correct place.
2948 finished
= !dptr_SearchDir(dirptr
, resume_name
, ¤t_pos
, &st
);
2949 } /* end if resume_name && !continue_bit */
2951 for (i
=0;(i
<(int)maxentries
) && !finished
&& !out_of_space
;i
++) {
2952 bool got_exact_match
= False
;
2954 /* this is a heuristic to avoid seeking the dirptr except when
2955 absolutely necessary. It allows for a filename of about 40 chars */
2956 if (space_remaining
< DIRLEN_GUESS
&& numentries
> 0) {
2957 out_of_space
= True
;
2960 finished
= !get_lanman2_dir_entry(ctx
,
2964 mask
,dirtype
,info_level
,
2965 requires_resume_key
,dont_descend
,
2968 space_remaining
, &out_of_space
,
2970 &last_entry_off
, ea_list
);
2973 if (finished
&& out_of_space
)
2976 if (!finished
&& !out_of_space
)
2980 * As an optimisation if we know we aren't looking
2981 * for a wildcard name (ie. the name matches the wildcard exactly)
2982 * then we can finish on any (first) match.
2983 * This speeds up large directory searches. JRA.
2989 space_remaining
= max_data_bytes
- PTR_DIFF(p
,pdata
);
2992 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2993 smb_fn_name(req
->cmd
),
2994 mask
, directory
, dirtype
, numentries
) );
2996 /* Check if we can close the dirptr */
2997 if(close_after_request
|| (finished
&& close_if_end
)) {
2998 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num
));
2999 dptr_close(sconn
, &dptr_num
); /* This frees up the saved mask */
3006 /* Set up the return parameter block */
3007 SSVAL(params
,0,numentries
);
3008 SSVAL(params
,2,finished
);
3009 SSVAL(params
,4,0); /* Never an EA error */
3010 SSVAL(params
,6,last_entry_off
);
3012 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 8, pdata
, PTR_DIFF(p
,pdata
),
3018 unsigned char *create_volume_objectid(connection_struct
*conn
, unsigned char objid
[16])
3020 E_md4hash(lp_servicename(talloc_tos(), SNUM(conn
)),objid
);
3024 static void samba_extended_info_version(struct smb_extended_info
*extended_info
)
3026 SMB_ASSERT(extended_info
!= NULL
);
3028 extended_info
->samba_magic
= SAMBA_EXTENDED_INFO_MAGIC
;
3029 extended_info
->samba_version
= ((SAMBA_VERSION_MAJOR
& 0xff) << 24)
3030 | ((SAMBA_VERSION_MINOR
& 0xff) << 16)
3031 | ((SAMBA_VERSION_RELEASE
& 0xff) << 8);
3032 #ifdef SAMBA_VERSION_REVISION
3033 extended_info
->samba_version
|= (tolower(*SAMBA_VERSION_REVISION
) - 'a' + 1) & 0xff;
3035 extended_info
->samba_subversion
= 0;
3036 #ifdef SAMBA_VERSION_RC_RELEASE
3037 extended_info
->samba_subversion
|= (SAMBA_VERSION_RC_RELEASE
& 0xff) << 24;
3039 #ifdef SAMBA_VERSION_PRE_RELEASE
3040 extended_info
->samba_subversion
|= (SAMBA_VERSION_PRE_RELEASE
& 0xff) << 16;
3043 #ifdef SAMBA_VERSION_VENDOR_PATCH
3044 extended_info
->samba_subversion
|= (SAMBA_VERSION_VENDOR_PATCH
& 0xffff);
3046 extended_info
->samba_gitcommitdate
= 0;
3047 #ifdef SAMBA_VERSION_COMMIT_TIME
3048 unix_to_nt_time(&extended_info
->samba_gitcommitdate
, SAMBA_VERSION_COMMIT_TIME
);
3051 memset(extended_info
->samba_version_string
, 0,
3052 sizeof(extended_info
->samba_version_string
));
3054 snprintf (extended_info
->samba_version_string
,
3055 sizeof(extended_info
->samba_version_string
),
3056 "%s", samba_version_string());
3059 NTSTATUS
smbd_do_qfsinfo(connection_struct
*conn
,
3060 TALLOC_CTX
*mem_ctx
,
3061 uint16_t info_level
,
3063 unsigned int max_data_bytes
,
3064 struct smb_filename
*fname
,
3068 char *pdata
, *end_data
;
3069 int data_len
= 0, len
;
3070 const char *vname
= volume_label(talloc_tos(), SNUM(conn
));
3071 int snum
= SNUM(conn
);
3072 char *fstype
= lp_fstype(talloc_tos(), SNUM(conn
));
3073 char *filename
= NULL
;
3074 uint32 additional_flags
= 0;
3075 struct smb_filename smb_fname
;
3077 NTSTATUS status
= NT_STATUS_OK
;
3079 if (fname
== NULL
|| fname
->base_name
== NULL
) {
3082 filename
= fname
->base_name
;
3086 if (info_level
!= SMB_QUERY_CIFS_UNIX_INFO
) {
3087 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
3088 "info level (0x%x) on IPC$.\n",
3089 (unsigned int)info_level
));
3090 return NT_STATUS_ACCESS_DENIED
;
3094 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level
));
3096 ZERO_STRUCT(smb_fname
);
3097 smb_fname
.base_name
= discard_const_p(char, filename
);
3099 if(SMB_VFS_STAT(conn
, &smb_fname
) != 0) {
3100 DEBUG(2,("stat of . failed (%s)\n", strerror(errno
)));
3101 return map_nt_error_from_unix(errno
);
3106 if (max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
< max_data_bytes
) {
3107 return NT_STATUS_INVALID_PARAMETER
;
3110 *ppdata
= (char *)SMB_REALLOC(
3111 *ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
3112 if (*ppdata
== NULL
) {
3113 return NT_STATUS_NO_MEMORY
;
3117 memset((char *)pdata
,'\0',max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
3118 end_data
= pdata
+ max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
- 1;
3120 switch (info_level
) {
3121 case SMB_INFO_ALLOCATION
:
3123 uint64_t dfree
,dsize
,bsize
,block_size
,sectors_per_unit
,bytes_per_sector
;
3125 if (get_dfree_info(conn
,filename
,False
,&bsize
,&dfree
,&dsize
) == (uint64_t)-1) {
3126 return map_nt_error_from_unix(errno
);
3129 block_size
= lp_block_size(snum
);
3130 if (bsize
< block_size
) {
3131 uint64_t factor
= block_size
/bsize
;
3136 if (bsize
> block_size
) {
3137 uint64_t factor
= bsize
/block_size
;
3142 bytes_per_sector
= 512;
3143 sectors_per_unit
= bsize
/bytes_per_sector
;
3145 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
3146 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st
.st_ex_dev
, (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
3147 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
3149 SIVAL(pdata
,l1_idFileSystem
,st
.st_ex_dev
);
3150 SIVAL(pdata
,l1_cSectorUnit
,sectors_per_unit
);
3151 SIVAL(pdata
,l1_cUnit
,dsize
);
3152 SIVAL(pdata
,l1_cUnitAvail
,dfree
);
3153 SSVAL(pdata
,l1_cbSector
,bytes_per_sector
);
3157 case SMB_INFO_VOLUME
:
3158 /* Return volume name */
3160 * Add volume serial number - hash of a combination of
3161 * the called hostname and the service name.
3163 SIVAL(pdata
,0,str_checksum(lp_servicename(talloc_tos(), snum
)) ^ (str_checksum(get_local_machine_name())<<16) );
3165 * Win2k3 and previous mess this up by sending a name length
3166 * one byte short. I believe only older clients (OS/2 Win9x) use
3167 * this call so try fixing this by adding a terminating null to
3168 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
3172 pdata
+l2_vol_szVolLabel
, vname
,
3173 PTR_DIFF(end_data
, pdata
+l2_vol_szVolLabel
),
3174 STR_NOALIGN
|STR_TERMINATE
);
3175 SCVAL(pdata
,l2_vol_cch
,len
);
3176 data_len
= l2_vol_szVolLabel
+ len
;
3177 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %d, name = %s\n",
3178 (unsigned)convert_timespec_to_time_t(st
.st_ex_ctime
),
3182 case SMB_QUERY_FS_ATTRIBUTE_INFO
:
3183 case SMB_FS_ATTRIBUTE_INFORMATION
:
3185 additional_flags
= 0;
3186 #if defined(HAVE_SYS_QUOTAS)
3187 additional_flags
|= FILE_VOLUME_QUOTAS
;
3190 if(lp_nt_acl_support(SNUM(conn
))) {
3191 additional_flags
|= FILE_PERSISTENT_ACLS
;
3194 /* Capabilities are filled in at connection time through STATVFS call */
3195 additional_flags
|= conn
->fs_capabilities
;
3196 additional_flags
|= lp_parm_int(conn
->params
->service
,
3197 "share", "fake_fscaps",
3200 SIVAL(pdata
,0,FILE_CASE_PRESERVED_NAMES
|FILE_CASE_SENSITIVE_SEARCH
|
3201 FILE_SUPPORTS_OBJECT_IDS
|FILE_UNICODE_ON_DISK
|
3202 additional_flags
); /* FS ATTRIBUTES */
3204 SIVAL(pdata
,4,255); /* Max filename component length */
3205 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
3206 and will think we can't do long filenames */
3207 len
= srvstr_push(pdata
, flags2
, pdata
+12, fstype
,
3208 PTR_DIFF(end_data
, pdata
+12),
3211 data_len
= 12 + len
;
3212 if (max_data_bytes
>= 16 && data_len
> max_data_bytes
) {
3213 /* the client only requested a portion of the
3215 data_len
= max_data_bytes
;
3216 status
= STATUS_BUFFER_OVERFLOW
;
3220 case SMB_QUERY_FS_LABEL_INFO
:
3221 case SMB_FS_LABEL_INFORMATION
:
3222 len
= srvstr_push(pdata
, flags2
, pdata
+4, vname
,
3223 PTR_DIFF(end_data
, pdata
+4), 0);
3228 case SMB_QUERY_FS_VOLUME_INFO
:
3229 case SMB_FS_VOLUME_INFORMATION
:
3232 * Add volume serial number - hash of a combination of
3233 * the called hostname and the service name.
3235 SIVAL(pdata
,8,str_checksum(lp_servicename(talloc_tos(), snum
)) ^
3236 (str_checksum(get_local_machine_name())<<16));
3238 /* Max label len is 32 characters. */
3239 len
= srvstr_push(pdata
, flags2
, pdata
+18, vname
,
3240 PTR_DIFF(end_data
, pdata
+18),
3242 SIVAL(pdata
,12,len
);
3245 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3246 (int)strlen(vname
),vname
,
3247 lp_servicename(talloc_tos(), snum
)));
3248 if (max_data_bytes
>= 24 && data_len
> max_data_bytes
) {
3249 /* the client only requested a portion of the
3251 data_len
= max_data_bytes
;
3252 status
= STATUS_BUFFER_OVERFLOW
;
3256 case SMB_QUERY_FS_SIZE_INFO
:
3257 case SMB_FS_SIZE_INFORMATION
:
3259 uint64_t dfree
,dsize
,bsize
,block_size
,sectors_per_unit
,bytes_per_sector
;
3261 if (get_dfree_info(conn
,filename
,False
,&bsize
,&dfree
,&dsize
) == (uint64_t)-1) {
3262 return map_nt_error_from_unix(errno
);
3264 block_size
= lp_block_size(snum
);
3265 if (bsize
< block_size
) {
3266 uint64_t factor
= block_size
/bsize
;
3271 if (bsize
> block_size
) {
3272 uint64_t factor
= bsize
/block_size
;
3277 bytes_per_sector
= 512;
3278 sectors_per_unit
= bsize
/bytes_per_sector
;
3279 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3280 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
3281 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
3282 SBIG_UINT(pdata
,0,dsize
);
3283 SBIG_UINT(pdata
,8,dfree
);
3284 SIVAL(pdata
,16,sectors_per_unit
);
3285 SIVAL(pdata
,20,bytes_per_sector
);
3289 case SMB_FS_FULL_SIZE_INFORMATION
:
3291 uint64_t dfree
,dsize
,bsize
,block_size
,sectors_per_unit
,bytes_per_sector
;
3293 if (get_dfree_info(conn
,filename
,False
,&bsize
,&dfree
,&dsize
) == (uint64_t)-1) {
3294 return map_nt_error_from_unix(errno
);
3296 block_size
= lp_block_size(snum
);
3297 if (bsize
< block_size
) {
3298 uint64_t factor
= block_size
/bsize
;
3303 if (bsize
> block_size
) {
3304 uint64_t factor
= bsize
/block_size
;
3309 bytes_per_sector
= 512;
3310 sectors_per_unit
= bsize
/bytes_per_sector
;
3311 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3312 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
3313 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
3314 SBIG_UINT(pdata
,0,dsize
); /* Total Allocation units. */
3315 SBIG_UINT(pdata
,8,dfree
); /* Caller available allocation units. */
3316 SBIG_UINT(pdata
,16,dfree
); /* Actual available allocation units. */
3317 SIVAL(pdata
,24,sectors_per_unit
); /* Sectors per allocation unit. */
3318 SIVAL(pdata
,28,bytes_per_sector
); /* Bytes per sector. */
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
);
3336 #ifdef HAVE_SYS_QUOTAS
3337 case SMB_FS_QUOTA_INFORMATION
:
3339 * what we have to send --metze:
3341 * Unknown1: 24 NULL bytes
3342 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3343 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3344 * Quota Flags: 2 byte :
3345 * Unknown3: 6 NULL bytes
3349 * details for Quota Flags:
3351 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3352 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3353 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3354 * 0x0001 Enable Quotas: enable quota for this fs
3358 /* we need to fake up a fsp here,
3359 * because its not send in this call
3362 SMB_NTQUOTA_STRUCT quotas
;
3365 ZERO_STRUCT(quotas
);
3368 fsp
.fnum
= FNUM_FIELD_INVALID
;
3371 if (get_current_uid(conn
) != 0) {
3372 DEBUG(0,("get_user_quota: access_denied "
3373 "service [%s] user [%s]\n",
3374 lp_servicename(talloc_tos(), SNUM(conn
)),
3375 conn
->session_info
->unix_info
->unix_name
));
3376 return NT_STATUS_ACCESS_DENIED
;
3379 if (vfs_get_ntquota(&fsp
, SMB_USER_FS_QUOTA_TYPE
, NULL
, "as
)!=0) {
3380 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn
))));
3381 return map_nt_error_from_unix(errno
);
3386 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3387 lp_servicename(talloc_tos(), SNUM(conn
))));
3389 /* Unknown1 24 NULL bytes*/
3390 SBIG_UINT(pdata
,0,(uint64_t)0);
3391 SBIG_UINT(pdata
,8,(uint64_t)0);
3392 SBIG_UINT(pdata
,16,(uint64_t)0);
3394 /* Default Soft Quota 8 bytes */
3395 SBIG_UINT(pdata
,24,quotas
.softlim
);
3397 /* Default Hard Quota 8 bytes */
3398 SBIG_UINT(pdata
,32,quotas
.hardlim
);
3400 /* Quota flag 2 bytes */
3401 SSVAL(pdata
,40,quotas
.qflags
);
3403 /* Unknown3 6 NULL bytes */
3409 #endif /* HAVE_SYS_QUOTAS */
3410 case SMB_FS_OBJECTID_INFORMATION
:
3412 unsigned char objid
[16];
3413 struct smb_extended_info extended_info
;
3414 memcpy(pdata
,create_volume_objectid(conn
, objid
),16);
3415 samba_extended_info_version (&extended_info
);
3416 SIVAL(pdata
,16,extended_info
.samba_magic
);
3417 SIVAL(pdata
,20,extended_info
.samba_version
);
3418 SIVAL(pdata
,24,extended_info
.samba_subversion
);
3419 SBIG_UINT(pdata
,28,extended_info
.samba_gitcommitdate
);
3420 memcpy(pdata
+36,extended_info
.samba_version_string
,28);
3426 * Query the version and capabilities of the CIFS UNIX extensions
3430 case SMB_QUERY_CIFS_UNIX_INFO
:
3432 bool large_write
= lp_min_receive_file_size() &&
3433 !srv_is_signing_active(conn
->sconn
);
3434 bool large_read
= !srv_is_signing_active(conn
->sconn
);
3435 int encrypt_caps
= 0;
3437 if (!lp_unix_extensions()) {
3438 return NT_STATUS_INVALID_LEVEL
;
3441 switch (conn
->encrypt_level
) {
3442 case SMB_SIGNING_OFF
:
3445 case SMB_SIGNING_IF_REQUIRED
:
3446 case SMB_SIGNING_DEFAULT
:
3447 encrypt_caps
= CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP
;
3449 case SMB_SIGNING_REQUIRED
:
3450 encrypt_caps
= CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP
|
3451 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP
;
3452 large_write
= false;
3458 SSVAL(pdata
,0,CIFS_UNIX_MAJOR_VERSION
);
3459 SSVAL(pdata
,2,CIFS_UNIX_MINOR_VERSION
);
3461 /* We have POSIX ACLs, pathname, encryption,
3462 * large read/write, and locking capability. */
3464 SBIG_UINT(pdata
,4,((uint64_t)(
3465 CIFS_UNIX_POSIX_ACLS_CAP
|
3466 CIFS_UNIX_POSIX_PATHNAMES_CAP
|
3467 CIFS_UNIX_FCNTL_LOCKS_CAP
|
3468 CIFS_UNIX_EXTATTR_CAP
|
3469 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP
|
3471 (large_read
? CIFS_UNIX_LARGE_READ_CAP
: 0) |
3473 CIFS_UNIX_LARGE_WRITE_CAP
: 0))));
3477 case SMB_QUERY_POSIX_FS_INFO
:
3480 vfs_statvfs_struct svfs
;
3482 if (!lp_unix_extensions()) {
3483 return NT_STATUS_INVALID_LEVEL
;
3486 rc
= SMB_VFS_STATVFS(conn
, filename
, &svfs
);
3490 SIVAL(pdata
,0,svfs
.OptimalTransferSize
);
3491 SIVAL(pdata
,4,svfs
.BlockSize
);
3492 SBIG_UINT(pdata
,8,svfs
.TotalBlocks
);
3493 SBIG_UINT(pdata
,16,svfs
.BlocksAvail
);
3494 SBIG_UINT(pdata
,24,svfs
.UserBlocksAvail
);
3495 SBIG_UINT(pdata
,32,svfs
.TotalFileNodes
);
3496 SBIG_UINT(pdata
,40,svfs
.FreeFileNodes
);
3497 SBIG_UINT(pdata
,48,svfs
.FsIdentifier
);
3498 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3500 } else if (rc
== EOPNOTSUPP
) {
3501 return NT_STATUS_INVALID_LEVEL
;
3502 #endif /* EOPNOTSUPP */
3504 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn
))));
3505 return NT_STATUS_DOS(ERRSRV
, ERRerror
);
3510 case SMB_QUERY_POSIX_WHOAMI
:
3516 if (!lp_unix_extensions()) {
3517 return NT_STATUS_INVALID_LEVEL
;
3520 if (max_data_bytes
< 40) {
3521 return NT_STATUS_BUFFER_TOO_SMALL
;
3524 if (security_session_user_level(conn
->session_info
, NULL
) < SECURITY_USER
) {
3525 flags
|= SMB_WHOAMI_GUEST
;
3528 /* NOTE: 8 bytes for UID/GID, irrespective of native
3529 * platform size. This matches
3530 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3532 data_len
= 4 /* flags */
3539 + 4 /* pad/reserved */
3540 + (conn
->session_info
->unix_token
->ngroups
* 8)
3542 + (conn
->session_info
->security_token
->num_sids
*
3546 SIVAL(pdata
, 0, flags
);
3547 SIVAL(pdata
, 4, SMB_WHOAMI_MASK
);
3549 (uint64_t)conn
->session_info
->unix_token
->uid
);
3550 SBIG_UINT(pdata
, 16,
3551 (uint64_t)conn
->session_info
->unix_token
->gid
);
3554 if (data_len
>= max_data_bytes
) {
3555 /* Potential overflow, skip the GIDs and SIDs. */
3557 SIVAL(pdata
, 24, 0); /* num_groups */
3558 SIVAL(pdata
, 28, 0); /* num_sids */
3559 SIVAL(pdata
, 32, 0); /* num_sid_bytes */
3560 SIVAL(pdata
, 36, 0); /* reserved */
3566 SIVAL(pdata
, 24, conn
->session_info
->unix_token
->ngroups
);
3567 SIVAL(pdata
, 28, conn
->session_info
->security_token
->num_sids
);
3569 /* We walk the SID list twice, but this call is fairly
3570 * infrequent, and I don't expect that it's performance
3571 * sensitive -- jpeach
3573 for (i
= 0, sid_bytes
= 0;
3574 i
< conn
->session_info
->security_token
->num_sids
; ++i
) {
3575 sid_bytes
+= ndr_size_dom_sid(
3576 &conn
->session_info
->security_token
->sids
[i
],
3580 /* SID list byte count */
3581 SIVAL(pdata
, 32, sid_bytes
);
3583 /* 4 bytes pad/reserved - must be zero */
3584 SIVAL(pdata
, 36, 0);
3588 for (i
= 0; i
< conn
->session_info
->unix_token
->ngroups
; ++i
) {
3589 SBIG_UINT(pdata
, data_len
,
3590 (uint64_t)conn
->session_info
->unix_token
->groups
[i
]);
3596 i
< conn
->session_info
->security_token
->num_sids
; ++i
) {
3597 int sid_len
= ndr_size_dom_sid(
3598 &conn
->session_info
->security_token
->sids
[i
],
3601 sid_linearize(pdata
+ data_len
, sid_len
,
3602 &conn
->session_info
->security_token
->sids
[i
]);
3603 data_len
+= sid_len
;
3609 case SMB_MAC_QUERY_FS_INFO
:
3611 * Thursby MAC extension... ONLY on NTFS filesystems
3612 * once we do streams then we don't need this
3614 if (strequal(lp_fstype(talloc_tos(), SNUM(conn
)),"NTFS")) {
3616 SIVAL(pdata
,84,0x100); /* Don't support mac... */
3621 return NT_STATUS_INVALID_LEVEL
;
3624 *ret_data_len
= data_len
;
3628 /****************************************************************************
3629 Reply to a TRANS2_QFSINFO (query filesystem info).
3630 ****************************************************************************/
3632 static void call_trans2qfsinfo(connection_struct
*conn
,
3633 struct smb_request
*req
,
3634 char **pparams
, int total_params
,
3635 char **ppdata
, int total_data
,
3636 unsigned int max_data_bytes
)
3638 char *params
= *pparams
;
3639 uint16_t info_level
;
3643 if (total_params
< 2) {
3644 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3648 info_level
= SVAL(params
,0);
3650 if (ENCRYPTION_REQUIRED(conn
) && !req
->encrypted
) {
3651 if (info_level
!= SMB_QUERY_CIFS_UNIX_INFO
) {
3652 DEBUG(0,("call_trans2qfsinfo: encryption required "
3653 "and info level 0x%x sent.\n",
3654 (unsigned int)info_level
));
3655 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3660 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level
));
3662 status
= smbd_do_qfsinfo(conn
, req
,
3668 if (!NT_STATUS_IS_OK(status
)) {
3669 reply_nterror(req
, status
);
3673 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 0, *ppdata
, data_len
,
3676 DEBUG( 4, ( "%s info_level = %d\n",
3677 smb_fn_name(req
->cmd
), info_level
) );
3682 /****************************************************************************
3683 Reply to a TRANS2_SETFSINFO (set filesystem info).
3684 ****************************************************************************/
3686 static void call_trans2setfsinfo(connection_struct
*conn
,
3687 struct smb_request
*req
,
3688 char **pparams
, int total_params
,
3689 char **ppdata
, int total_data
,
3690 unsigned int max_data_bytes
)
3692 struct smbd_server_connection
*sconn
= req
->sconn
;
3693 char *pdata
= *ppdata
;
3694 char *params
= *pparams
;
3697 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",
3698 lp_servicename(talloc_tos(), SNUM(conn
))));
3701 if (total_params
< 4) {
3702 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3704 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3708 info_level
= SVAL(params
,2);
3711 if (info_level
!= SMB_REQUEST_TRANSPORT_ENCRYPTION
&&
3712 info_level
!= SMB_SET_CIFS_UNIX_INFO
) {
3713 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3714 "info level (0x%x) on IPC$.\n",
3715 (unsigned int)info_level
));
3716 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3721 if (ENCRYPTION_REQUIRED(conn
) && !req
->encrypted
) {
3722 if (info_level
!= SMB_REQUEST_TRANSPORT_ENCRYPTION
) {
3723 DEBUG(0,("call_trans2setfsinfo: encryption required "
3724 "and info level 0x%x sent.\n",
3725 (unsigned int)info_level
));
3726 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3731 switch(info_level
) {
3732 case SMB_SET_CIFS_UNIX_INFO
:
3733 if (!lp_unix_extensions()) {
3734 DEBUG(2,("call_trans2setfsinfo: "
3735 "SMB_SET_CIFS_UNIX_INFO is invalid with "
3736 "unix extensions off\n"));
3738 NT_STATUS_INVALID_LEVEL
);
3742 /* There should be 12 bytes of capabilities set. */
3743 if (total_data
< 12) {
3746 NT_STATUS_INVALID_PARAMETER
);
3749 sconn
->smb1
.unix_info
.client_major
= SVAL(pdata
,0);
3750 sconn
->smb1
.unix_info
.client_minor
= SVAL(pdata
,2);
3751 sconn
->smb1
.unix_info
.client_cap_low
= IVAL(pdata
,4);
3752 sconn
->smb1
.unix_info
.client_cap_high
= IVAL(pdata
,8);
3753 /* Just print these values for now. */
3754 DEBUG(10, ("call_trans2setfsinfo: set unix_info info. "
3755 "major = %u, minor = %u cap_low = 0x%x, "
3757 (unsigned int)sconn
->
3758 smb1
.unix_info
.client_major
,
3759 (unsigned int)sconn
->
3760 smb1
.unix_info
.client_minor
,
3761 (unsigned int)sconn
->
3762 smb1
.unix_info
.client_cap_low
,
3763 (unsigned int)sconn
->
3764 smb1
.unix_info
.client_cap_high
));
3766 /* Here is where we must switch to posix pathname processing... */
3767 if (sconn
->smb1
.unix_info
.client_cap_low
& CIFS_UNIX_POSIX_PATHNAMES_CAP
) {
3768 lp_set_posix_pathnames();
3769 mangle_change_to_posix();
3772 if ((sconn
->smb1
.unix_info
.client_cap_low
& CIFS_UNIX_FCNTL_LOCKS_CAP
) &&
3773 !(sconn
->smb1
.unix_info
.client_cap_low
& CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP
)) {
3774 /* Client that knows how to do posix locks,
3775 * but not posix open/mkdir operations. Set a
3776 * default type for read/write checks. */
3778 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK
);
3783 case SMB_REQUEST_TRANSPORT_ENCRYPTION
:
3786 size_t param_len
= 0;
3787 size_t data_len
= total_data
;
3789 if (!lp_unix_extensions()) {
3792 NT_STATUS_INVALID_LEVEL
);
3796 if (lp_smb_encrypt(SNUM(conn
)) == SMB_SIGNING_OFF
) {
3799 NT_STATUS_NOT_SUPPORTED
);
3803 if (req
->sconn
->smb1
.echo_handler
.trusted_fde
) {
3804 DEBUG( 2,("call_trans2setfsinfo: "
3805 "request transport encryption disabled"
3806 "with 'fork echo handler = yes'\n"));
3809 NT_STATUS_NOT_SUPPORTED
);
3813 DEBUG( 4,("call_trans2setfsinfo: "
3814 "request transport encryption.\n"));
3816 status
= srv_request_encryption_setup(conn
,
3817 (unsigned char **)ppdata
,
3819 (unsigned char **)pparams
,
3822 if (!NT_STATUS_EQUAL(status
, NT_STATUS_MORE_PROCESSING_REQUIRED
) &&
3823 !NT_STATUS_IS_OK(status
)) {
3824 reply_nterror(req
, status
);
3828 send_trans2_replies(conn
, req
,
3836 if (NT_STATUS_IS_OK(status
)) {
3837 /* Server-side transport
3838 * encryption is now *on*. */
3839 status
= srv_encryption_start(conn
);
3840 if (!NT_STATUS_IS_OK(status
)) {
3841 char *reason
= talloc_asprintf(talloc_tos(),
3842 "Failure in setting "
3843 "up encrypted transport: %s",
3845 exit_server_cleanly(reason
);
3851 case SMB_FS_QUOTA_INFORMATION
:
3853 files_struct
*fsp
= NULL
;
3854 SMB_NTQUOTA_STRUCT quotas
;
3856 ZERO_STRUCT(quotas
);
3859 if ((get_current_uid(conn
) != 0) || !CAN_WRITE(conn
)) {
3860 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3861 lp_servicename(talloc_tos(), SNUM(conn
)),
3862 conn
->session_info
->unix_info
->unix_name
));
3863 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3867 /* note: normaly there're 48 bytes,
3868 * but we didn't use the last 6 bytes for now
3871 fsp
= file_fsp(req
, SVAL(params
,0));
3873 if (!check_fsp_ntquota_handle(conn
, req
,
3875 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3877 req
, NT_STATUS_INVALID_HANDLE
);
3881 if (total_data
< 42) {
3882 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3886 NT_STATUS_INVALID_PARAMETER
);
3890 /* unknown_1 24 NULL bytes in pdata*/
3892 /* the soft quotas 8 bytes (uint64_t)*/
3893 quotas
.softlim
= BVAL(pdata
,24);
3895 /* the hard quotas 8 bytes (uint64_t)*/
3896 quotas
.hardlim
= BVAL(pdata
,32);
3898 /* quota_flags 2 bytes **/
3899 quotas
.qflags
= SVAL(pdata
,40);
3901 /* unknown_2 6 NULL bytes follow*/
3903 /* now set the quotas */
3904 if (vfs_set_ntquota(fsp
, SMB_USER_FS_QUOTA_TYPE
, NULL
, "as
)!=0) {
3905 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn
))));
3906 reply_nterror(req
, map_nt_error_from_unix(errno
));
3913 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3915 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
3921 * sending this reply works fine,
3922 * but I'm not sure it's the same
3923 * like windows do...
3926 reply_outbuf(req
, 10, 0);
3929 #if defined(HAVE_POSIX_ACLS)
3930 /****************************************************************************
3931 Utility function to count the number of entries in a POSIX acl.
3932 ****************************************************************************/
3934 static unsigned int count_acl_entries(connection_struct
*conn
, SMB_ACL_T posix_acl
)
3936 unsigned int ace_count
= 0;
3937 int entry_id
= SMB_ACL_FIRST_ENTRY
;
3938 SMB_ACL_ENTRY_T entry
;
3940 while ( posix_acl
&& (sys_acl_get_entry(posix_acl
, entry_id
, &entry
) == 1)) {
3942 if (entry_id
== SMB_ACL_FIRST_ENTRY
) {
3943 entry_id
= SMB_ACL_NEXT_ENTRY
;
3950 /****************************************************************************
3951 Utility function to marshall a POSIX acl into wire format.
3952 ****************************************************************************/
3954 static bool marshall_posix_acl(connection_struct
*conn
, char *pdata
, SMB_STRUCT_STAT
*pst
, SMB_ACL_T posix_acl
)
3956 int entry_id
= SMB_ACL_FIRST_ENTRY
;
3957 SMB_ACL_ENTRY_T entry
;
3959 while ( posix_acl
&& (sys_acl_get_entry(posix_acl
, entry_id
, &entry
) == 1)) {
3960 SMB_ACL_TAG_T tagtype
;
3961 SMB_ACL_PERMSET_T permset
;
3962 unsigned char perms
= 0;
3963 unsigned int own_grp
;
3966 if (entry_id
== SMB_ACL_FIRST_ENTRY
) {
3967 entry_id
= SMB_ACL_NEXT_ENTRY
;
3970 if (sys_acl_get_tag_type(entry
, &tagtype
) == -1) {
3971 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3975 if (sys_acl_get_permset(entry
, &permset
) == -1) {
3976 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3980 perms
|= (sys_acl_get_perm(permset
, SMB_ACL_READ
) ? SMB_POSIX_ACL_READ
: 0);
3981 perms
|= (sys_acl_get_perm(permset
, SMB_ACL_WRITE
) ? SMB_POSIX_ACL_WRITE
: 0);
3982 perms
|= (sys_acl_get_perm(permset
, SMB_ACL_EXECUTE
) ? SMB_POSIX_ACL_EXECUTE
: 0);
3984 SCVAL(pdata
,1,perms
);
3987 case SMB_ACL_USER_OBJ
:
3988 SCVAL(pdata
,0,SMB_POSIX_ACL_USER_OBJ
);
3989 own_grp
= (unsigned int)pst
->st_ex_uid
;
3990 SIVAL(pdata
,2,own_grp
);
3995 uid_t
*puid
= (uid_t
*)sys_acl_get_qualifier(entry
);
3997 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
4000 own_grp
= (unsigned int)*puid
;
4001 SCVAL(pdata
,0,SMB_POSIX_ACL_USER
);
4002 SIVAL(pdata
,2,own_grp
);
4006 case SMB_ACL_GROUP_OBJ
:
4007 SCVAL(pdata
,0,SMB_POSIX_ACL_GROUP_OBJ
);
4008 own_grp
= (unsigned int)pst
->st_ex_gid
;
4009 SIVAL(pdata
,2,own_grp
);
4014 gid_t
*pgid
= (gid_t
*)sys_acl_get_qualifier(entry
);
4016 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
4019 own_grp
= (unsigned int)*pgid
;
4020 SCVAL(pdata
,0,SMB_POSIX_ACL_GROUP
);
4021 SIVAL(pdata
,2,own_grp
);
4026 SCVAL(pdata
,0,SMB_POSIX_ACL_MASK
);
4027 SIVAL(pdata
,2,0xFFFFFFFF);
4028 SIVAL(pdata
,6,0xFFFFFFFF);
4031 SCVAL(pdata
,0,SMB_POSIX_ACL_OTHER
);
4032 SIVAL(pdata
,2,0xFFFFFFFF);
4033 SIVAL(pdata
,6,0xFFFFFFFF);
4036 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
4039 pdata
+= SMB_POSIX_ACL_ENTRY_SIZE
;
4046 /****************************************************************************
4047 Store the FILE_UNIX_BASIC info.
4048 ****************************************************************************/
4050 static char *store_file_unix_basic(connection_struct
*conn
,
4053 const SMB_STRUCT_STAT
*psbuf
)
4055 uint64_t file_index
= get_FileIndex(conn
, psbuf
);
4058 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
4059 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf
->st_ex_mode
));
4061 SOFF_T(pdata
,0,get_file_size_stat(psbuf
)); /* File size 64 Bit */
4064 SOFF_T(pdata
,0,SMB_VFS_GET_ALLOC_SIZE(conn
,fsp
,psbuf
)); /* Number of bytes used on disk - 64 Bit */
4067 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER
, pdata
, psbuf
->st_ex_ctime
); /* Change Time 64 Bit */
4068 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER
,pdata
+8, psbuf
->st_ex_atime
); /* Last access time 64 Bit */
4069 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER
, pdata
+16, psbuf
->st_ex_mtime
); /* Last modification time 64 Bit */
4072 SIVAL(pdata
,0,psbuf
->st_ex_uid
); /* user id for the owner */
4076 SIVAL(pdata
,0,psbuf
->st_ex_gid
); /* group id of owner */
4080 SIVAL(pdata
,0,unix_filetype(psbuf
->st_ex_mode
));
4083 if (S_ISBLK(psbuf
->st_ex_mode
) || S_ISCHR(psbuf
->st_ex_mode
)) {
4084 devno
= psbuf
->st_ex_rdev
;
4086 devno
= psbuf
->st_ex_dev
;
4089 SIVAL(pdata
,0,unix_dev_major(devno
)); /* Major device number if type is device */
4093 SIVAL(pdata
,0,unix_dev_minor(devno
)); /* Minor device number if type is device */
4097 SINO_T_VAL(pdata
,0,(SMB_INO_T
)file_index
); /* inode number */
4100 SIVAL(pdata
,0, unix_perms_to_wire(psbuf
->st_ex_mode
)); /* Standard UNIX file permissions */
4104 SIVAL(pdata
,0,psbuf
->st_ex_nlink
); /* number of hard links */
4111 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
4112 * the chflags(2) (or equivalent) flags.
4114 * XXX: this really should be behind the VFS interface. To do this, we would
4115 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
4116 * Each VFS module could then implement its own mapping as appropriate for the
4117 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
4119 static const struct {unsigned stat_fflag
; unsigned smb_fflag
;}
4123 { UF_NODUMP
, EXT_DO_NOT_BACKUP
},
4127 { UF_IMMUTABLE
, EXT_IMMUTABLE
},
4131 { UF_APPEND
, EXT_OPEN_APPEND_ONLY
},
4135 { UF_HIDDEN
, EXT_HIDDEN
},
4138 /* Do not remove. We need to guarantee that this array has at least one
4139 * entry to build on HP-UX.
4145 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT
*psbuf
,
4146 uint32
*smb_fflags
, uint32
*smb_fmask
)
4150 for (i
= 0; i
< ARRAY_SIZE(info2_flags_map
); ++i
) {
4151 *smb_fmask
|= info2_flags_map
[i
].smb_fflag
;
4152 if (psbuf
->st_ex_flags
& info2_flags_map
[i
].stat_fflag
) {
4153 *smb_fflags
|= info2_flags_map
[i
].smb_fflag
;
4158 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT
*psbuf
,
4159 const uint32 smb_fflags
,
4160 const uint32 smb_fmask
,
4163 uint32 max_fmask
= 0;
4166 *stat_fflags
= psbuf
->st_ex_flags
;
4168 /* For each flags requested in smb_fmask, check the state of the
4169 * corresponding flag in smb_fflags and set or clear the matching
4173 for (i
= 0; i
< ARRAY_SIZE(info2_flags_map
); ++i
) {
4174 max_fmask
|= info2_flags_map
[i
].smb_fflag
;
4175 if (smb_fmask
& info2_flags_map
[i
].smb_fflag
) {
4176 if (smb_fflags
& info2_flags_map
[i
].smb_fflag
) {
4177 *stat_fflags
|= info2_flags_map
[i
].stat_fflag
;
4179 *stat_fflags
&= ~info2_flags_map
[i
].stat_fflag
;
4184 /* If smb_fmask is asking to set any bits that are not supported by
4185 * our flag mappings, we should fail.
4187 if ((smb_fmask
& max_fmask
) != smb_fmask
) {
4195 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
4196 * of file flags and birth (create) time.
4198 static char *store_file_unix_basic_info2(connection_struct
*conn
,
4201 const SMB_STRUCT_STAT
*psbuf
)
4203 uint32 file_flags
= 0;
4204 uint32 flags_mask
= 0;
4206 pdata
= store_file_unix_basic(conn
, pdata
, fsp
, psbuf
);
4208 /* Create (birth) time 64 bit */
4209 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER
,pdata
, psbuf
->st_ex_btime
);
4212 map_info2_flags_from_sbuf(psbuf
, &file_flags
, &flags_mask
);
4213 SIVAL(pdata
, 0, file_flags
); /* flags */
4214 SIVAL(pdata
, 4, flags_mask
); /* mask */
4220 static NTSTATUS
marshall_stream_info(unsigned int num_streams
,
4221 const struct stream_struct
*streams
,
4223 unsigned int max_data_bytes
,
4224 unsigned int *data_size
)
4227 unsigned int ofs
= 0;
4229 for (i
= 0; i
< num_streams
; i
++) {
4230 unsigned int next_offset
;
4232 smb_ucs2_t
*namebuf
;
4234 if (!push_ucs2_talloc(talloc_tos(), &namebuf
,
4235 streams
[i
].name
, &namelen
) ||
4238 return NT_STATUS_INVALID_PARAMETER
;
4242 * name_buf is now null-terminated, we need to marshall as not
4249 * We cannot overflow ...
4251 if ((ofs
+ 24 + namelen
) > max_data_bytes
) {
4252 DEBUG(10, ("refusing to overflow reply at stream %u\n",
4254 TALLOC_FREE(namebuf
);
4255 return STATUS_BUFFER_OVERFLOW
;
4258 SIVAL(data
, ofs
+4, namelen
);
4259 SOFF_T(data
, ofs
+8, streams
[i
].size
);
4260 SOFF_T(data
, ofs
+16, streams
[i
].alloc_size
);
4261 memcpy(data
+ofs
+24, namebuf
, namelen
);
4262 TALLOC_FREE(namebuf
);
4264 next_offset
= ofs
+ 24 + namelen
;
4266 if (i
== num_streams
-1) {
4267 SIVAL(data
, ofs
, 0);
4270 unsigned int align
= ndr_align_size(next_offset
, 8);
4272 if ((next_offset
+ align
) > max_data_bytes
) {
4273 DEBUG(10, ("refusing to overflow align "
4274 "reply at stream %u\n",
4276 TALLOC_FREE(namebuf
);
4277 return STATUS_BUFFER_OVERFLOW
;
4280 memset(data
+next_offset
, 0, align
);
4281 next_offset
+= align
;
4283 SIVAL(data
, ofs
, next_offset
- ofs
);
4290 DEBUG(10, ("max_data: %u, data_size: %u\n", max_data_bytes
, ofs
));
4294 return NT_STATUS_OK
;
4297 /****************************************************************************
4298 Reply to a TRANSACT2_QFILEINFO on a PIPE !
4299 ****************************************************************************/
4301 static void call_trans2qpipeinfo(connection_struct
*conn
,
4302 struct smb_request
*req
,
4303 unsigned int tran_call
,
4304 char **pparams
, int total_params
,
4305 char **ppdata
, int total_data
,
4306 unsigned int max_data_bytes
)
4308 char *params
= *pparams
;
4309 char *pdata
= *ppdata
;
4310 unsigned int data_size
= 0;
4311 unsigned int param_size
= 2;
4316 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4320 if (total_params
< 4) {
4321 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4325 fsp
= file_fsp(req
, SVAL(params
,0));
4326 if (!fsp_is_np(fsp
)) {
4327 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
4331 info_level
= SVAL(params
,2);
4333 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
4334 if (*pparams
== NULL
) {
4335 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
4340 if (max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
< max_data_bytes
) {
4341 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4344 data_size
= max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
;
4345 *ppdata
= (char *)SMB_REALLOC(*ppdata
, data_size
);
4346 if (*ppdata
== NULL
) {
4347 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
4352 switch (info_level
) {
4353 case SMB_FILE_STANDARD_INFORMATION
:
4355 SOFF_T(pdata
,0,4096LL);
4362 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
4366 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, param_size
, *ppdata
, data_size
,
4372 NTSTATUS
smbd_do_qfilepathinfo(connection_struct
*conn
,
4373 TALLOC_CTX
*mem_ctx
,
4374 uint16_t info_level
,
4376 struct smb_filename
*smb_fname
,
4377 bool delete_pending
,
4378 struct timespec write_time_ts
,
4379 struct ea_list
*ea_list
,
4380 int lock_data_count
,
4383 unsigned int max_data_bytes
,
4385 unsigned int *pdata_size
)
4387 char *pdata
= *ppdata
;
4388 char *dstart
, *dend
;
4389 unsigned int data_size
;
4390 struct timespec create_time_ts
, mtime_ts
, atime_ts
, ctime_ts
;
4391 time_t create_time
, mtime
, atime
, c_time
;
4392 SMB_STRUCT_STAT
*psbuf
= &smb_fname
->st
;
4399 uint64_t file_size
= 0;
4401 uint64_t allocation_size
= 0;
4402 uint64_t file_index
= 0;
4403 uint32_t access_mask
= 0;
4405 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
4406 return NT_STATUS_INVALID_LEVEL
;
4409 DEBUG(5,("smbd_do_qfilepathinfo: %s (%s) level=%d max_data=%u\n",
4410 smb_fname_str_dbg(smb_fname
),
4412 info_level
, max_data_bytes
));
4414 mode
= dos_mode(conn
, smb_fname
);
4415 nlink
= psbuf
->st_ex_nlink
;
4417 if (nlink
&& (mode
&FILE_ATTRIBUTE_DIRECTORY
)) {
4421 if ((nlink
> 0) && delete_pending
) {
4425 if (max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
< max_data_bytes
) {
4426 return NT_STATUS_INVALID_PARAMETER
;
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
);
4524 switch (info_level
) {
4525 case SMB_INFO_STANDARD
:
4526 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4528 srv_put_dos_date2(pdata
,l1_fdateCreation
,create_time
);
4529 srv_put_dos_date2(pdata
,l1_fdateLastAccess
,atime
);
4530 srv_put_dos_date2(pdata
,l1_fdateLastWrite
,mtime
); /* write time */
4531 SIVAL(pdata
,l1_cbFile
,(uint32
)file_size
);
4532 SIVAL(pdata
,l1_cbFileAlloc
,(uint32
)allocation_size
);
4533 SSVAL(pdata
,l1_attrFile
,mode
);
4536 case SMB_INFO_QUERY_EA_SIZE
:
4538 unsigned int ea_size
=
4539 estimate_ea_size(conn
, fsp
,
4541 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4543 srv_put_dos_date2(pdata
,0,create_time
);
4544 srv_put_dos_date2(pdata
,4,atime
);
4545 srv_put_dos_date2(pdata
,8,mtime
); /* write time */
4546 SIVAL(pdata
,12,(uint32
)file_size
);
4547 SIVAL(pdata
,16,(uint32
)allocation_size
);
4548 SSVAL(pdata
,20,mode
);
4549 SIVAL(pdata
,22,ea_size
);
4553 case SMB_INFO_IS_NAME_VALID
:
4554 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4556 /* os/2 needs this ? really ?*/
4557 return NT_STATUS_DOS(ERRDOS
, ERRbadfunc
);
4559 /* This is only reached for qpathinfo */
4563 case SMB_INFO_QUERY_EAS_FROM_LIST
:
4565 size_t total_ea_len
= 0;
4566 struct ea_list
*ea_file_list
= NULL
;
4567 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4570 get_ea_list_from_file(mem_ctx
, conn
, fsp
,
4572 &total_ea_len
, &ea_file_list
);
4573 if (!NT_STATUS_IS_OK(status
)) {
4577 ea_list
= ea_list_union(ea_list
, ea_file_list
, &total_ea_len
);
4579 if (!ea_list
|| (total_ea_len
> data_size
)) {
4581 SIVAL(pdata
,0,4); /* EA List Length must be set to 4 if no EA's. */
4585 data_size
= fill_ea_buffer(mem_ctx
, pdata
, data_size
, conn
, ea_list
);
4589 case SMB_INFO_QUERY_ALL_EAS
:
4591 /* We have data_size bytes to put EA's into. */
4592 size_t total_ea_len
= 0;
4593 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4595 status
= get_ea_list_from_file(mem_ctx
, conn
, fsp
,
4597 &total_ea_len
, &ea_list
);
4598 if (!NT_STATUS_IS_OK(status
)) {
4602 if (!ea_list
|| (total_ea_len
> data_size
)) {
4604 SIVAL(pdata
,0,4); /* EA List Length must be set to 4 if no EA's. */
4608 data_size
= fill_ea_buffer(mem_ctx
, pdata
, data_size
, conn
, ea_list
);
4612 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
4614 /* This is FileFullEaInformation - 0xF which maps to
4615 * 1015 (decimal) in smbd_do_setfilepathinfo. */
4617 /* We have data_size bytes to put EA's into. */
4618 size_t total_ea_len
= 0;
4619 struct ea_list
*ea_file_list
= NULL
;
4621 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
4623 /*TODO: add filtering and index handling */
4626 get_ea_list_from_file(mem_ctx
, conn
, fsp
,
4628 &total_ea_len
, &ea_file_list
);
4629 if (!NT_STATUS_IS_OK(status
)) {
4632 if (!ea_file_list
) {
4633 return NT_STATUS_NO_EAS_ON_FILE
;
4636 status
= fill_ea_chained_buffer(mem_ctx
,
4640 conn
, ea_file_list
);
4641 if (!NT_STATUS_IS_OK(status
)) {
4647 case SMB_FILE_BASIC_INFORMATION
:
4648 case SMB_QUERY_FILE_BASIC_INFO
:
4650 if (info_level
== SMB_QUERY_FILE_BASIC_INFO
) {
4651 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4652 data_size
= 36; /* w95 returns 40 bytes not 36 - why ?. */
4654 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4658 put_long_date_timespec(conn
->ts_res
,pdata
,create_time_ts
);
4659 put_long_date_timespec(conn
->ts_res
,pdata
+8,atime_ts
);
4660 put_long_date_timespec(conn
->ts_res
,pdata
+16,mtime_ts
); /* write time */
4661 put_long_date_timespec(conn
->ts_res
,pdata
+24,ctime_ts
); /* change time */
4662 SIVAL(pdata
,32,mode
);
4664 DEBUG(5,("SMB_QFBI - "));
4665 DEBUG(5,("create: %s ", ctime(&create_time
)));
4666 DEBUG(5,("access: %s ", ctime(&atime
)));
4667 DEBUG(5,("write: %s ", ctime(&mtime
)));
4668 DEBUG(5,("change: %s ", ctime(&c_time
)));
4669 DEBUG(5,("mode: %x\n", mode
));
4672 case SMB_FILE_STANDARD_INFORMATION
:
4673 case SMB_QUERY_FILE_STANDARD_INFO
:
4675 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4677 SOFF_T(pdata
,0,allocation_size
);
4678 SOFF_T(pdata
,8,file_size
);
4679 SIVAL(pdata
,16,nlink
);
4680 SCVAL(pdata
,20,delete_pending
?1:0);
4681 SCVAL(pdata
,21,(mode
&FILE_ATTRIBUTE_DIRECTORY
)?1:0);
4682 SSVAL(pdata
,22,0); /* Padding. */
4685 case SMB_FILE_EA_INFORMATION
:
4686 case SMB_QUERY_FILE_EA_INFO
:
4688 unsigned int ea_size
=
4689 estimate_ea_size(conn
, fsp
, smb_fname
);
4690 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4692 SIVAL(pdata
,0,ea_size
);
4696 /* Get the 8.3 name - used if NT SMB was negotiated. */
4697 case SMB_QUERY_FILE_ALT_NAME_INFO
:
4698 case SMB_FILE_ALTERNATE_NAME_INFORMATION
:
4701 char mangled_name
[13];
4702 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4703 if (!name_to_8_3(base_name
,mangled_name
,
4704 True
,conn
->params
)) {
4705 return NT_STATUS_NO_MEMORY
;
4707 len
= srvstr_push(dstart
, flags2
,
4708 pdata
+4, mangled_name
,
4709 PTR_DIFF(dend
, pdata
+4),
4711 data_size
= 4 + len
;
4716 case SMB_QUERY_FILE_NAME_INFO
:
4720 this must be *exactly* right for ACLs on mapped drives to work
4722 len
= srvstr_push(dstart
, flags2
,
4724 PTR_DIFF(dend
, pdata
+4),
4726 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4727 data_size
= 4 + len
;
4732 case SMB_FILE_ALLOCATION_INFORMATION
:
4733 case SMB_QUERY_FILE_ALLOCATION_INFO
:
4734 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4736 SOFF_T(pdata
,0,allocation_size
);
4739 case SMB_FILE_END_OF_FILE_INFORMATION
:
4740 case SMB_QUERY_FILE_END_OF_FILEINFO
:
4741 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4743 SOFF_T(pdata
,0,file_size
);
4746 case SMB_QUERY_FILE_ALL_INFO
:
4747 case SMB_FILE_ALL_INFORMATION
:
4750 unsigned int ea_size
=
4751 estimate_ea_size(conn
, fsp
, smb_fname
);
4752 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4753 put_long_date_timespec(conn
->ts_res
,pdata
,create_time_ts
);
4754 put_long_date_timespec(conn
->ts_res
,pdata
+8,atime_ts
);
4755 put_long_date_timespec(conn
->ts_res
,pdata
+16,mtime_ts
); /* write time */
4756 put_long_date_timespec(conn
->ts_res
,pdata
+24,ctime_ts
); /* change time */
4757 SIVAL(pdata
,32,mode
);
4758 SIVAL(pdata
,36,0); /* padding. */
4760 SOFF_T(pdata
,0,allocation_size
);
4761 SOFF_T(pdata
,8,file_size
);
4762 SIVAL(pdata
,16,nlink
);
4763 SCVAL(pdata
,20,delete_pending
);
4764 SCVAL(pdata
,21,(mode
&FILE_ATTRIBUTE_DIRECTORY
)?1:0);
4767 SIVAL(pdata
,0,ea_size
);
4768 pdata
+= 4; /* EA info */
4769 len
= srvstr_push(dstart
, flags2
,
4771 PTR_DIFF(dend
, pdata
+4),
4775 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4779 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
4782 unsigned int ea_size
=
4783 estimate_ea_size(conn
, fsp
, smb_fname
);
4784 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
4785 put_long_date_timespec(conn
->ts_res
,pdata
+0x00,create_time_ts
);
4786 put_long_date_timespec(conn
->ts_res
,pdata
+0x08,atime_ts
);
4787 put_long_date_timespec(conn
->ts_res
,pdata
+0x10,mtime_ts
); /* write time */
4788 put_long_date_timespec(conn
->ts_res
,pdata
+0x18,ctime_ts
); /* change time */
4789 SIVAL(pdata
, 0x20, mode
);
4790 SIVAL(pdata
, 0x24, 0); /* padding. */
4791 SBVAL(pdata
, 0x28, allocation_size
);
4792 SBVAL(pdata
, 0x30, file_size
);
4793 SIVAL(pdata
, 0x38, nlink
);
4794 SCVAL(pdata
, 0x3C, delete_pending
);
4795 SCVAL(pdata
, 0x3D, (mode
&FILE_ATTRIBUTE_DIRECTORY
)?1:0);
4796 SSVAL(pdata
, 0x3E, 0); /* padding */
4797 SBVAL(pdata
, 0x40, file_index
);
4798 SIVAL(pdata
, 0x48, ea_size
);
4799 SIVAL(pdata
, 0x4C, access_mask
);
4800 SBVAL(pdata
, 0x50, pos
);
4801 SIVAL(pdata
, 0x58, mode
); /*TODO: mode != mode fix this!!! */
4802 SIVAL(pdata
, 0x5C, 0); /* No alignment needed. */
4806 len
= srvstr_push(dstart
, flags2
,
4808 PTR_DIFF(dend
, pdata
+4),
4812 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4815 case SMB_FILE_INTERNAL_INFORMATION
:
4817 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4818 SBVAL(pdata
, 0, file_index
);
4822 case SMB_FILE_ACCESS_INFORMATION
:
4823 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4824 SIVAL(pdata
, 0, access_mask
);
4828 case SMB_FILE_NAME_INFORMATION
:
4829 /* Pathname with leading '\'. */
4832 byte_len
= dos_PutUniCode(pdata
+4,dos_fname
,(size_t)max_data_bytes
,False
);
4833 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4834 SIVAL(pdata
,0,byte_len
);
4835 data_size
= 4 + byte_len
;
4839 case SMB_FILE_DISPOSITION_INFORMATION
:
4840 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4842 SCVAL(pdata
,0,delete_pending
);
4845 case SMB_FILE_POSITION_INFORMATION
:
4846 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4848 SOFF_T(pdata
,0,pos
);
4851 case SMB_FILE_MODE_INFORMATION
:
4852 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4853 SIVAL(pdata
,0,mode
);
4857 case SMB_FILE_ALIGNMENT_INFORMATION
:
4858 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4859 SIVAL(pdata
,0,0); /* No alignment needed. */
4864 * NT4 server just returns "invalid query" to this - if we try
4865 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4868 /* The first statement above is false - verified using Thursby
4869 * client against NT4 -- gcolley.
4871 case SMB_QUERY_FILE_STREAM_INFO
:
4872 case SMB_FILE_STREAM_INFORMATION
: {
4873 unsigned int num_streams
= 0;
4874 struct stream_struct
*streams
= NULL
;
4876 DEBUG(10,("smbd_do_qfilepathinfo: "
4877 "SMB_FILE_STREAM_INFORMATION\n"));
4879 if (is_ntfs_stream_smb_fname(smb_fname
)) {
4880 return NT_STATUS_INVALID_PARAMETER
;
4883 status
= vfs_streaminfo(conn
, fsp
, smb_fname
->base_name
,
4884 talloc_tos(), &num_streams
, &streams
);
4886 if (!NT_STATUS_IS_OK(status
)) {
4887 DEBUG(10, ("could not get stream info: %s\n",
4888 nt_errstr(status
)));
4892 status
= marshall_stream_info(num_streams
, streams
,
4893 pdata
, max_data_bytes
,
4896 if (!NT_STATUS_IS_OK(status
)) {
4897 DEBUG(10, ("marshall_stream_info failed: %s\n",
4898 nt_errstr(status
)));
4899 TALLOC_FREE(streams
);
4903 TALLOC_FREE(streams
);
4907 case SMB_QUERY_COMPRESSION_INFO
:
4908 case SMB_FILE_COMPRESSION_INFORMATION
:
4909 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4910 SOFF_T(pdata
,0,file_size
);
4911 SIVAL(pdata
,8,0); /* ??? */
4912 SIVAL(pdata
,12,0); /* ??? */
4916 case SMB_FILE_NETWORK_OPEN_INFORMATION
:
4917 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4918 put_long_date_timespec(conn
->ts_res
,pdata
,create_time_ts
);
4919 put_long_date_timespec(conn
->ts_res
,pdata
+8,atime_ts
);
4920 put_long_date_timespec(conn
->ts_res
,pdata
+16,mtime_ts
); /* write time */
4921 put_long_date_timespec(conn
->ts_res
,pdata
+24,ctime_ts
); /* change time */
4922 SOFF_T(pdata
,32,allocation_size
);
4923 SOFF_T(pdata
,40,file_size
);
4924 SIVAL(pdata
,48,mode
);
4925 SIVAL(pdata
,52,0); /* ??? */
4929 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION
:
4930 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4931 SIVAL(pdata
,0,mode
);
4937 * CIFS UNIX Extensions.
4940 case SMB_QUERY_FILE_UNIX_BASIC
:
4942 pdata
= store_file_unix_basic(conn
, pdata
, fsp
, psbuf
);
4943 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4945 DEBUG(4,("smbd_do_qfilepathinfo: "
4946 "SMB_QUERY_FILE_UNIX_BASIC\n"));
4947 dump_data(4, (uint8_t *)(*ppdata
), data_size
);
4951 case SMB_QUERY_FILE_UNIX_INFO2
:
4953 pdata
= store_file_unix_basic_info2(conn
, pdata
, fsp
, psbuf
);
4954 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4958 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4960 for (i
=0; i
<100; i
++)
4961 DEBUG(4,("%d=%x, ",i
, (*ppdata
)[i
]));
4967 case SMB_QUERY_FILE_UNIX_LINK
:
4970 char *buffer
= talloc_array(mem_ctx
, char, PATH_MAX
+1);
4973 return NT_STATUS_NO_MEMORY
;
4976 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4978 if(!S_ISLNK(psbuf
->st_ex_mode
)) {
4979 return NT_STATUS_DOS(ERRSRV
, ERRbadlink
);
4982 return NT_STATUS_DOS(ERRDOS
, ERRbadlink
);
4984 len
= SMB_VFS_READLINK(conn
,
4985 smb_fname
->base_name
,
4988 return map_nt_error_from_unix(errno
);
4991 len
= srvstr_push(dstart
, flags2
,
4993 PTR_DIFF(dend
, pdata
),
4996 data_size
= PTR_DIFF(pdata
,(*ppdata
));
5001 #if defined(HAVE_POSIX_ACLS)
5002 case SMB_QUERY_POSIX_ACL
:
5004 SMB_ACL_T file_acl
= NULL
;
5005 SMB_ACL_T def_acl
= NULL
;
5006 uint16 num_file_acls
= 0;
5007 uint16 num_def_acls
= 0;
5009 if (fsp
&& fsp
->fh
->fd
!= -1) {
5010 file_acl
= SMB_VFS_SYS_ACL_GET_FD(fsp
,
5014 SMB_VFS_SYS_ACL_GET_FILE(conn
,
5015 smb_fname
->base_name
,
5016 SMB_ACL_TYPE_ACCESS
,
5020 if (file_acl
== NULL
&& no_acl_syscall_error(errno
)) {
5021 DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
5022 "not implemented on "
5023 "filesystem containing %s\n",
5024 smb_fname
->base_name
));
5025 return NT_STATUS_NOT_IMPLEMENTED
;
5028 if (S_ISDIR(psbuf
->st_ex_mode
)) {
5029 if (fsp
&& fsp
->is_directory
) {
5031 SMB_VFS_SYS_ACL_GET_FILE(
5033 fsp
->fsp_name
->base_name
,
5034 SMB_ACL_TYPE_DEFAULT
,
5038 SMB_VFS_SYS_ACL_GET_FILE(
5040 smb_fname
->base_name
,
5041 SMB_ACL_TYPE_DEFAULT
,
5044 def_acl
= free_empty_sys_acl(conn
, def_acl
);
5047 num_file_acls
= count_acl_entries(conn
, file_acl
);
5048 num_def_acls
= count_acl_entries(conn
, def_acl
);
5050 if ( data_size
< (num_file_acls
+ num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
+ SMB_POSIX_ACL_HEADER_SIZE
) {
5051 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
5053 (unsigned int)((num_file_acls
+ num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
+
5054 SMB_POSIX_ACL_HEADER_SIZE
) ));
5056 TALLOC_FREE(file_acl
);
5059 TALLOC_FREE(def_acl
);
5061 return NT_STATUS_BUFFER_TOO_SMALL
;
5064 SSVAL(pdata
,0,SMB_POSIX_ACL_VERSION
);
5065 SSVAL(pdata
,2,num_file_acls
);
5066 SSVAL(pdata
,4,num_def_acls
);
5067 if (!marshall_posix_acl(conn
, pdata
+ SMB_POSIX_ACL_HEADER_SIZE
, psbuf
, file_acl
)) {
5069 TALLOC_FREE(file_acl
);
5072 TALLOC_FREE(def_acl
);
5074 return NT_STATUS_INTERNAL_ERROR
;
5076 if (!marshall_posix_acl(conn
, pdata
+ SMB_POSIX_ACL_HEADER_SIZE
+ (num_file_acls
*SMB_POSIX_ACL_ENTRY_SIZE
), psbuf
, def_acl
)) {
5078 TALLOC_FREE(file_acl
);
5081 TALLOC_FREE(def_acl
);
5083 return NT_STATUS_INTERNAL_ERROR
;
5087 TALLOC_FREE(file_acl
);
5090 TALLOC_FREE(def_acl
);
5092 data_size
= (num_file_acls
+ num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
+ SMB_POSIX_ACL_HEADER_SIZE
;
5098 case SMB_QUERY_POSIX_LOCK
:
5103 enum brl_type lock_type
;
5105 /* We need an open file with a real fd for this. */
5106 if (!fsp
|| fsp
->fh
->fd
== -1) {
5107 return NT_STATUS_INVALID_LEVEL
;
5110 if (lock_data_count
!= POSIX_LOCK_DATA_SIZE
) {
5111 return NT_STATUS_INVALID_PARAMETER
;
5114 switch (SVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
)) {
5115 case POSIX_LOCK_TYPE_READ
:
5116 lock_type
= READ_LOCK
;
5118 case POSIX_LOCK_TYPE_WRITE
:
5119 lock_type
= WRITE_LOCK
;
5121 case POSIX_LOCK_TYPE_UNLOCK
:
5123 /* There's no point in asking for an unlock... */
5124 return NT_STATUS_INVALID_PARAMETER
;
5127 smblctx
= (uint64_t)IVAL(pdata
, POSIX_LOCK_PID_OFFSET
);
5128 #if defined(HAVE_LONGLONG)
5129 offset
= (((uint64_t) IVAL(pdata
,(POSIX_LOCK_START_OFFSET
+4))) << 32) |
5130 ((uint64_t) IVAL(pdata
,POSIX_LOCK_START_OFFSET
));
5131 count
= (((uint64_t) IVAL(pdata
,(POSIX_LOCK_LEN_OFFSET
+4))) << 32) |
5132 ((uint64_t) IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
));
5133 #else /* HAVE_LONGLONG */
5134 offset
= (uint64_t)IVAL(pdata
,POSIX_LOCK_START_OFFSET
);
5135 count
= (uint64_t)IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
);
5136 #endif /* HAVE_LONGLONG */
5138 status
= query_lock(fsp
,
5145 if (ERROR_WAS_LOCK_DENIED(status
)) {
5146 /* Here we need to report who has it locked... */
5147 data_size
= POSIX_LOCK_DATA_SIZE
;
5149 SSVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
, lock_type
);
5150 SSVAL(pdata
, POSIX_LOCK_FLAGS_OFFSET
, 0);
5151 SIVAL(pdata
, POSIX_LOCK_PID_OFFSET
, (uint32_t)smblctx
);
5152 #if defined(HAVE_LONGLONG)
5153 SIVAL(pdata
, POSIX_LOCK_START_OFFSET
, (uint32
)(offset
& 0xFFFFFFFF));
5154 SIVAL(pdata
, POSIX_LOCK_START_OFFSET
+ 4, (uint32
)((offset
>> 32) & 0xFFFFFFFF));
5155 SIVAL(pdata
, POSIX_LOCK_LEN_OFFSET
, (uint32
)(count
& 0xFFFFFFFF));
5156 SIVAL(pdata
, POSIX_LOCK_LEN_OFFSET
+ 4, (uint32
)((count
>> 32) & 0xFFFFFFFF));
5157 #else /* HAVE_LONGLONG */
5158 SIVAL(pdata
, POSIX_LOCK_START_OFFSET
, offset
);
5159 SIVAL(pdata
, POSIX_LOCK_LEN_OFFSET
, count
);
5160 #endif /* HAVE_LONGLONG */
5162 } else if (NT_STATUS_IS_OK(status
)) {
5163 /* For success we just return a copy of what we sent
5164 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
5165 data_size
= POSIX_LOCK_DATA_SIZE
;
5166 memcpy(pdata
, lock_data
, POSIX_LOCK_DATA_SIZE
);
5167 SSVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
, POSIX_LOCK_TYPE_UNLOCK
);
5175 return NT_STATUS_INVALID_LEVEL
;
5178 *pdata_size
= data_size
;
5179 return NT_STATUS_OK
;
5182 /****************************************************************************
5183 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
5184 file name or file id).
5185 ****************************************************************************/
5187 static void call_trans2qfilepathinfo(connection_struct
*conn
,
5188 struct smb_request
*req
,
5189 unsigned int tran_call
,
5190 char **pparams
, int total_params
,
5191 char **ppdata
, int total_data
,
5192 unsigned int max_data_bytes
)
5194 char *params
= *pparams
;
5195 char *pdata
= *ppdata
;
5197 unsigned int data_size
= 0;
5198 unsigned int param_size
= 2;
5199 struct smb_filename
*smb_fname
= NULL
;
5200 bool delete_pending
= False
;
5201 struct timespec write_time_ts
;
5202 files_struct
*fsp
= NULL
;
5203 struct file_id fileid
;
5204 struct ea_list
*ea_list
= NULL
;
5205 int lock_data_count
= 0;
5206 char *lock_data
= NULL
;
5207 NTSTATUS status
= NT_STATUS_OK
;
5210 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5214 ZERO_STRUCT(write_time_ts
);
5216 if (tran_call
== TRANSACT2_QFILEINFO
) {
5217 if (total_params
< 4) {
5218 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5223 call_trans2qpipeinfo(conn
, req
, tran_call
,
5224 pparams
, total_params
,
5230 fsp
= file_fsp(req
, SVAL(params
,0));
5231 info_level
= SVAL(params
,2);
5233 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level
));
5235 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
5236 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
5240 /* Initial check for valid fsp ptr. */
5241 if (!check_fsp_open(conn
, req
, fsp
)) {
5245 smb_fname
= cp_smb_filename(talloc_tos(), fsp
->fsp_name
);
5246 if (smb_fname
== NULL
) {
5247 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5251 if(fsp
->fake_file_handle
) {
5253 * This is actually for the QUOTA_FAKE_FILE --metze
5256 /* We know this name is ok, it's already passed the checks. */
5258 } else if(fsp
->fh
->fd
== -1) {
5260 * This is actually a QFILEINFO on a directory
5261 * handle (returned from an NT SMB). NT5.0 seems
5262 * to do this call. JRA.
5265 if (INFO_LEVEL_IS_UNIX(info_level
)) {
5266 /* Always do lstat for UNIX calls. */
5267 if (SMB_VFS_LSTAT(conn
, smb_fname
)) {
5268 DEBUG(3,("call_trans2qfilepathinfo: "
5269 "SMB_VFS_LSTAT of %s failed "
5271 smb_fname_str_dbg(smb_fname
),
5274 map_nt_error_from_unix(errno
));
5277 } else if (SMB_VFS_STAT(conn
, smb_fname
)) {
5278 DEBUG(3,("call_trans2qfilepathinfo: "
5279 "SMB_VFS_STAT of %s failed (%s)\n",
5280 smb_fname_str_dbg(smb_fname
),
5283 map_nt_error_from_unix(errno
));
5287 fileid
= vfs_file_id_from_sbuf(conn
, &smb_fname
->st
);
5288 get_file_infos(fileid
, fsp
->name_hash
, &delete_pending
, &write_time_ts
);
5291 * Original code - this is an open file.
5293 if (SMB_VFS_FSTAT(fsp
, &smb_fname
->st
) != 0) {
5294 DEBUG(3, ("fstat of %s failed (%s)\n",
5295 fsp_fnum_dbg(fsp
), strerror(errno
)));
5297 map_nt_error_from_unix(errno
));
5300 fileid
= vfs_file_id_from_sbuf(conn
, &smb_fname
->st
);
5301 get_file_infos(fileid
, fsp
->name_hash
, &delete_pending
, &write_time_ts
);
5307 uint32_t ucf_flags
= 0;
5310 if (total_params
< 7) {
5311 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5315 info_level
= SVAL(params
,0);
5317 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level
));
5319 if (INFO_LEVEL_IS_UNIX(info_level
)) {
5320 if (!lp_unix_extensions()) {
5321 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
5324 if (info_level
== SMB_QUERY_FILE_UNIX_BASIC
||
5325 info_level
== SMB_QUERY_FILE_UNIX_INFO2
||
5326 info_level
== SMB_QUERY_FILE_UNIX_LINK
) {
5327 ucf_flags
|= UCF_UNIX_NAME_LOOKUP
;
5331 srvstr_get_path(req
, params
, req
->flags2
, &fname
, ¶ms
[6],
5333 STR_TERMINATE
, &status
);
5334 if (!NT_STATUS_IS_OK(status
)) {
5335 reply_nterror(req
, status
);
5339 status
= filename_convert(req
,
5341 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
5346 if (!NT_STATUS_IS_OK(status
)) {
5347 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
5348 reply_botherror(req
,
5349 NT_STATUS_PATH_NOT_COVERED
,
5350 ERRSRV
, ERRbadpath
);
5353 reply_nterror(req
, status
);
5357 /* If this is a stream, check if there is a delete_pending. */
5358 if ((conn
->fs_capabilities
& FILE_NAMED_STREAMS
)
5359 && is_ntfs_stream_smb_fname(smb_fname
)) {
5360 struct smb_filename
*smb_fname_base
;
5362 /* Create an smb_filename with stream_name == NULL. */
5363 smb_fname_base
= synthetic_smb_fname(
5364 talloc_tos(), smb_fname
->base_name
,
5366 if (smb_fname_base
== NULL
) {
5367 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5371 if (INFO_LEVEL_IS_UNIX(info_level
)) {
5372 /* Always do lstat for UNIX calls. */
5373 if (SMB_VFS_LSTAT(conn
, smb_fname_base
) != 0) {
5374 DEBUG(3,("call_trans2qfilepathinfo: "
5375 "SMB_VFS_LSTAT of %s failed "
5377 smb_fname_str_dbg(smb_fname_base
),
5379 TALLOC_FREE(smb_fname_base
);
5381 map_nt_error_from_unix(errno
));
5385 if (SMB_VFS_STAT(conn
, smb_fname_base
) != 0) {
5386 DEBUG(3,("call_trans2qfilepathinfo: "
5387 "fileinfo of %s failed "
5389 smb_fname_str_dbg(smb_fname_base
),
5391 TALLOC_FREE(smb_fname_base
);
5393 map_nt_error_from_unix(errno
));
5398 status
= file_name_hash(conn
,
5399 smb_fname_str_dbg(smb_fname_base
),
5401 if (!NT_STATUS_IS_OK(status
)) {
5402 TALLOC_FREE(smb_fname_base
);
5403 reply_nterror(req
, status
);
5407 fileid
= vfs_file_id_from_sbuf(conn
,
5408 &smb_fname_base
->st
);
5409 TALLOC_FREE(smb_fname_base
);
5410 get_file_infos(fileid
, name_hash
, &delete_pending
, NULL
);
5411 if (delete_pending
) {
5412 reply_nterror(req
, NT_STATUS_DELETE_PENDING
);
5417 if (INFO_LEVEL_IS_UNIX(info_level
)) {
5418 /* Always do lstat for UNIX calls. */
5419 if (SMB_VFS_LSTAT(conn
, smb_fname
)) {
5420 DEBUG(3,("call_trans2qfilepathinfo: "
5421 "SMB_VFS_LSTAT of %s failed (%s)\n",
5422 smb_fname_str_dbg(smb_fname
),
5425 map_nt_error_from_unix(errno
));
5430 if (SMB_VFS_STAT(conn
, smb_fname
) != 0) {
5431 DEBUG(3,("call_trans2qfilepathinfo: "
5432 "SMB_VFS_STAT of %s failed (%s)\n",
5433 smb_fname_str_dbg(smb_fname
),
5436 map_nt_error_from_unix(errno
));
5441 status
= file_name_hash(conn
,
5442 smb_fname_str_dbg(smb_fname
),
5444 if (!NT_STATUS_IS_OK(status
)) {
5445 reply_nterror(req
, status
);
5449 fileid
= vfs_file_id_from_sbuf(conn
, &smb_fname
->st
);
5450 get_file_infos(fileid
, name_hash
, &delete_pending
, &write_time_ts
);
5451 if (delete_pending
) {
5452 reply_nterror(req
, NT_STATUS_DELETE_PENDING
);
5457 DEBUG(3,("call_trans2qfilepathinfo %s (%s) level=%d call=%d "
5458 "total_data=%d\n", smb_fname_str_dbg(smb_fname
),
5460 info_level
,tran_call
,total_data
));
5462 /* Pull out any data sent here before we realloc. */
5463 switch (info_level
) {
5464 case SMB_INFO_QUERY_EAS_FROM_LIST
:
5466 /* Pull any EA list from the data portion. */
5469 if (total_data
< 4) {
5471 req
, NT_STATUS_INVALID_PARAMETER
);
5474 ea_size
= IVAL(pdata
,0);
5476 if (total_data
> 0 && ea_size
!= total_data
) {
5477 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5478 total_data=%u (should be %u)\n", (unsigned int)total_data
, (unsigned int)IVAL(pdata
,0) ));
5480 req
, NT_STATUS_INVALID_PARAMETER
);
5484 if (!lp_ea_support(SNUM(conn
))) {
5485 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
5489 /* Pull out the list of names. */
5490 ea_list
= read_ea_name_list(req
, pdata
+ 4, ea_size
- 4);
5493 req
, NT_STATUS_INVALID_PARAMETER
);
5499 case SMB_QUERY_POSIX_LOCK
:
5501 if (fsp
== NULL
|| fsp
->fh
->fd
== -1) {
5502 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
5506 if (total_data
!= POSIX_LOCK_DATA_SIZE
) {
5508 req
, NT_STATUS_INVALID_PARAMETER
);
5512 /* Copy the lock range data. */
5513 lock_data
= (char *)talloc_memdup(
5514 req
, pdata
, total_data
);
5516 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5519 lock_data_count
= total_data
;
5525 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
5526 if (*pparams
== NULL
) {
5527 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5534 * draft-leach-cifs-v1-spec-02.txt
5535 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
5538 * The requested information is placed in the Data portion of the
5539 * transaction response. For the information levels greater than 0x100,
5540 * the transaction response has 1 parameter word which should be
5541 * ignored by the client.
5543 * However Windows only follows this rule for the IS_NAME_VALID call.
5545 switch (info_level
) {
5546 case SMB_INFO_IS_NAME_VALID
:
5551 if ((info_level
& 0xFF00) == 0xFF00) {
5553 * We use levels that start with 0xFF00
5554 * internally to represent SMB2 specific levels
5556 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
5560 status
= smbd_do_qfilepathinfo(conn
, req
, info_level
,
5562 delete_pending
, write_time_ts
,
5564 lock_data_count
, lock_data
,
5565 req
->flags2
, max_data_bytes
,
5566 ppdata
, &data_size
);
5567 if (!NT_STATUS_IS_OK(status
)) {
5568 reply_nterror(req
, status
);
5572 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, param_size
, *ppdata
, data_size
,
5578 /****************************************************************************
5579 Set a hard link (called by UNIX extensions and by NT rename with HARD link
5581 ****************************************************************************/
5583 NTSTATUS
hardlink_internals(TALLOC_CTX
*ctx
,
5584 connection_struct
*conn
,
5585 struct smb_request
*req
,
5586 bool overwrite_if_exists
,
5587 const struct smb_filename
*smb_fname_old
,
5588 struct smb_filename
*smb_fname_new
)
5590 NTSTATUS status
= NT_STATUS_OK
;
5592 /* source must already exist. */
5593 if (!VALID_STAT(smb_fname_old
->st
)) {
5594 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5597 if (VALID_STAT(smb_fname_new
->st
)) {
5598 if (overwrite_if_exists
) {
5599 if (S_ISDIR(smb_fname_new
->st
.st_ex_mode
)) {
5600 return NT_STATUS_FILE_IS_A_DIRECTORY
;
5602 status
= unlink_internals(conn
,
5604 FILE_ATTRIBUTE_NORMAL
,
5607 if (!NT_STATUS_IS_OK(status
)) {
5611 /* Disallow if newname already exists. */
5612 return NT_STATUS_OBJECT_NAME_COLLISION
;
5616 /* No links from a directory. */
5617 if (S_ISDIR(smb_fname_old
->st
.st_ex_mode
)) {
5618 return NT_STATUS_FILE_IS_A_DIRECTORY
;
5621 /* Setting a hardlink to/from a stream isn't currently supported. */
5622 if (is_ntfs_stream_smb_fname(smb_fname_old
) ||
5623 is_ntfs_stream_smb_fname(smb_fname_new
)) {
5624 return NT_STATUS_INVALID_PARAMETER
;
5627 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
5628 smb_fname_old
->base_name
, smb_fname_new
->base_name
));
5630 if (SMB_VFS_LINK(conn
, smb_fname_old
->base_name
,
5631 smb_fname_new
->base_name
) != 0) {
5632 status
= map_nt_error_from_unix(errno
);
5633 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
5634 nt_errstr(status
), smb_fname_old
->base_name
,
5635 smb_fname_new
->base_name
));
5640 /****************************************************************************
5641 Deal with setting the time from any of the setfilepathinfo functions.
5642 NOTE !!!! The check for FILE_WRITE_ATTRIBUTES access must be done *before*
5643 calling this function.
5644 ****************************************************************************/
5646 NTSTATUS
smb_set_file_time(connection_struct
*conn
,
5648 const struct smb_filename
*smb_fname
,
5649 struct smb_file_time
*ft
,
5650 bool setting_write_time
)
5652 struct smb_filename smb_fname_base
;
5654 FILE_NOTIFY_CHANGE_LAST_ACCESS
5655 |FILE_NOTIFY_CHANGE_LAST_WRITE
5656 |FILE_NOTIFY_CHANGE_CREATION
;
5658 if (!VALID_STAT(smb_fname
->st
)) {
5659 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5662 /* get some defaults (no modifications) if any info is zero or -1. */
5663 if (null_timespec(ft
->create_time
)) {
5664 action
&= ~FILE_NOTIFY_CHANGE_CREATION
;
5667 if (null_timespec(ft
->atime
)) {
5668 action
&= ~FILE_NOTIFY_CHANGE_LAST_ACCESS
;
5671 if (null_timespec(ft
->mtime
)) {
5672 action
&= ~FILE_NOTIFY_CHANGE_LAST_WRITE
;
5675 if (!setting_write_time
) {
5676 /* ft->mtime comes from change time, not write time. */
5677 action
&= ~FILE_NOTIFY_CHANGE_LAST_WRITE
;
5680 /* Ensure the resolution is the correct for
5681 * what we can store on this filesystem. */
5683 round_timespec(conn
->ts_res
, &ft
->create_time
);
5684 round_timespec(conn
->ts_res
, &ft
->ctime
);
5685 round_timespec(conn
->ts_res
, &ft
->atime
);
5686 round_timespec(conn
->ts_res
, &ft
->mtime
);
5688 DEBUG(5,("smb_set_filetime: actime: %s\n ",
5689 time_to_asc(convert_timespec_to_time_t(ft
->atime
))));
5690 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
5691 time_to_asc(convert_timespec_to_time_t(ft
->mtime
))));
5692 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
5693 time_to_asc(convert_timespec_to_time_t(ft
->ctime
))));
5694 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
5695 time_to_asc(convert_timespec_to_time_t(ft
->create_time
))));
5697 if (setting_write_time
) {
5699 * This was a Windows setfileinfo on an open file.
5700 * NT does this a lot. We also need to
5701 * set the time here, as it can be read by
5702 * FindFirst/FindNext and with the patch for bug #2045
5703 * in smbd/fileio.c it ensures that this timestamp is
5704 * kept sticky even after a write. We save the request
5705 * away and will set it on file close and after a write. JRA.
5708 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
5709 time_to_asc(convert_timespec_to_time_t(ft
->mtime
))));
5712 if (fsp
->base_fsp
) {
5713 set_sticky_write_time_fsp(fsp
->base_fsp
,
5716 set_sticky_write_time_fsp(fsp
, ft
->mtime
);
5719 set_sticky_write_time_path(
5720 vfs_file_id_from_sbuf(conn
, &smb_fname
->st
),
5725 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5727 /* Always call ntimes on the base, even if a stream was passed in. */
5728 smb_fname_base
= *smb_fname
;
5729 smb_fname_base
.stream_name
= NULL
;
5731 if(file_ntimes(conn
, &smb_fname_base
, ft
)!=0) {
5732 return map_nt_error_from_unix(errno
);
5735 notify_fname(conn
, NOTIFY_ACTION_MODIFIED
, action
,
5736 smb_fname
->base_name
);
5737 return NT_STATUS_OK
;
5740 /****************************************************************************
5741 Deal with setting the dosmode from any of the setfilepathinfo functions.
5742 NB. The check for FILE_WRITE_ATTRIBUTES access on this path must have been
5743 done before calling this function.
5744 ****************************************************************************/
5746 static NTSTATUS
smb_set_file_dosmode(connection_struct
*conn
,
5747 const struct smb_filename
*smb_fname
,
5750 struct smb_filename
*smb_fname_base
;
5753 if (!VALID_STAT(smb_fname
->st
)) {
5754 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5757 /* Always operate on the base_name, even if a stream was passed in. */
5758 smb_fname_base
= synthetic_smb_fname(
5759 talloc_tos(), smb_fname
->base_name
, NULL
, &smb_fname
->st
);
5760 if (smb_fname_base
== NULL
) {
5761 return NT_STATUS_NO_MEMORY
;
5765 if (S_ISDIR(smb_fname_base
->st
.st_ex_mode
)) {
5766 dosmode
|= FILE_ATTRIBUTE_DIRECTORY
;
5768 dosmode
&= ~FILE_ATTRIBUTE_DIRECTORY
;
5772 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode
));
5774 /* check the mode isn't different, before changing it */
5775 if ((dosmode
!= 0) && (dosmode
!= dos_mode(conn
, smb_fname_base
))) {
5776 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
5777 "0x%x\n", smb_fname_str_dbg(smb_fname_base
),
5778 (unsigned int)dosmode
));
5780 if(file_set_dosmode(conn
, smb_fname_base
, dosmode
, NULL
,
5782 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
5784 smb_fname_str_dbg(smb_fname_base
),
5786 status
= map_nt_error_from_unix(errno
);
5790 status
= NT_STATUS_OK
;
5792 TALLOC_FREE(smb_fname_base
);
5796 /****************************************************************************
5797 Deal with setting the size from any of the setfilepathinfo functions.
5798 ****************************************************************************/
5800 static NTSTATUS
smb_set_file_size(connection_struct
*conn
,
5801 struct smb_request
*req
,
5803 const struct smb_filename
*smb_fname
,
5804 const SMB_STRUCT_STAT
*psbuf
,
5806 bool fail_after_createfile
)
5808 NTSTATUS status
= NT_STATUS_OK
;
5809 struct smb_filename
*smb_fname_tmp
= NULL
;
5810 files_struct
*new_fsp
= NULL
;
5812 if (!VALID_STAT(*psbuf
)) {
5813 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5816 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size
));
5818 if (size
== get_file_size_stat(psbuf
)) {
5819 return NT_STATUS_OK
;
5822 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5823 smb_fname_str_dbg(smb_fname
), (double)size
));
5825 if (fsp
&& fsp
->fh
->fd
!= -1) {
5826 /* Handle based call. */
5827 if (!(fsp
->access_mask
& FILE_WRITE_DATA
)) {
5828 return NT_STATUS_ACCESS_DENIED
;
5831 if (vfs_set_filelen(fsp
, size
) == -1) {
5832 return map_nt_error_from_unix(errno
);
5834 trigger_write_time_update_immediate(fsp
);
5835 return NT_STATUS_OK
;
5838 smb_fname_tmp
= cp_smb_filename(talloc_tos(), smb_fname
);
5839 if (smb_fname_tmp
== NULL
) {
5840 return NT_STATUS_NO_MEMORY
;
5843 smb_fname_tmp
->st
= *psbuf
;
5845 status
= SMB_VFS_CREATE_FILE(
5848 0, /* root_dir_fid */
5849 smb_fname_tmp
, /* fname */
5850 FILE_WRITE_DATA
, /* access_mask */
5851 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
5853 FILE_OPEN
, /* create_disposition*/
5854 0, /* create_options */
5855 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
5856 FORCE_OPLOCK_BREAK_TO_NONE
, /* oplock_request */
5857 0, /* allocation_size */
5858 0, /* private_flags */
5861 &new_fsp
, /* result */
5864 TALLOC_FREE(smb_fname_tmp
);
5866 if (!NT_STATUS_IS_OK(status
)) {
5867 /* NB. We check for open_was_deferred in the caller. */
5871 /* See RAW-SFILEINFO-END-OF-FILE */
5872 if (fail_after_createfile
) {
5873 close_file(req
, new_fsp
,NORMAL_CLOSE
);
5874 return NT_STATUS_INVALID_LEVEL
;
5877 if (vfs_set_filelen(new_fsp
, size
) == -1) {
5878 status
= map_nt_error_from_unix(errno
);
5879 close_file(req
, new_fsp
,NORMAL_CLOSE
);
5883 trigger_write_time_update_immediate(new_fsp
);
5884 close_file(req
, new_fsp
,NORMAL_CLOSE
);
5885 return NT_STATUS_OK
;
5888 /****************************************************************************
5889 Deal with SMB_INFO_SET_EA.
5890 ****************************************************************************/
5892 static NTSTATUS
smb_info_set_ea(connection_struct
*conn
,
5896 const struct smb_filename
*smb_fname
)
5898 struct ea_list
*ea_list
= NULL
;
5899 TALLOC_CTX
*ctx
= NULL
;
5900 NTSTATUS status
= NT_STATUS_OK
;
5902 if (total_data
< 10) {
5904 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5905 length. They seem to have no effect. Bug #3212. JRA */
5907 if ((total_data
== 4) && (IVAL(pdata
,0) == 4)) {
5908 /* We're done. We only get EA info in this call. */
5909 return NT_STATUS_OK
;
5912 return NT_STATUS_INVALID_PARAMETER
;
5915 if (IVAL(pdata
,0) > total_data
) {
5916 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5917 IVAL(pdata
,0), (unsigned int)total_data
));
5918 return NT_STATUS_INVALID_PARAMETER
;
5922 ea_list
= read_ea_list(ctx
, pdata
+ 4, total_data
- 4);
5924 return NT_STATUS_INVALID_PARAMETER
;
5927 status
= set_ea(conn
, fsp
, smb_fname
, ea_list
);
5932 /****************************************************************************
5933 Deal with SMB_FILE_FULL_EA_INFORMATION set.
5934 ****************************************************************************/
5936 static NTSTATUS
smb_set_file_full_ea_info(connection_struct
*conn
,
5941 struct ea_list
*ea_list
= NULL
;
5945 return NT_STATUS_INVALID_HANDLE
;
5948 if (!lp_ea_support(SNUM(conn
))) {
5949 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
5950 "EA's not supported.\n",
5951 (unsigned int)total_data
));
5952 return NT_STATUS_EAS_NOT_SUPPORTED
;
5955 if (total_data
< 10) {
5956 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
5958 (unsigned int)total_data
));
5959 return NT_STATUS_INVALID_PARAMETER
;
5962 ea_list
= read_nttrans_ea_list(talloc_tos(),
5967 return NT_STATUS_INVALID_PARAMETER
;
5970 status
= set_ea(conn
, fsp
, fsp
->fsp_name
, ea_list
);
5972 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
5973 smb_fname_str_dbg(fsp
->fsp_name
),
5974 nt_errstr(status
) ));
5980 /****************************************************************************
5981 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5982 ****************************************************************************/
5984 static NTSTATUS
smb_set_file_disposition_info(connection_struct
*conn
,
5988 struct smb_filename
*smb_fname
)
5990 NTSTATUS status
= NT_STATUS_OK
;
5991 bool delete_on_close
;
5994 if (total_data
< 1) {
5995 return NT_STATUS_INVALID_PARAMETER
;
5999 return NT_STATUS_INVALID_HANDLE
;
6002 delete_on_close
= (CVAL(pdata
,0) ? True
: False
);
6003 dosmode
= dos_mode(conn
, smb_fname
);
6005 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
6006 "delete_on_close = %u\n",
6007 smb_fname_str_dbg(smb_fname
),
6008 (unsigned int)dosmode
,
6009 (unsigned int)delete_on_close
));
6011 if (delete_on_close
) {
6012 status
= can_set_delete_on_close(fsp
, dosmode
);
6013 if (!NT_STATUS_IS_OK(status
)) {
6018 /* The set is across all open files on this dev/inode pair. */
6019 if (!set_delete_on_close(fsp
, delete_on_close
,
6020 conn
->session_info
->security_token
,
6021 conn
->session_info
->unix_token
)) {
6022 return NT_STATUS_ACCESS_DENIED
;
6024 return NT_STATUS_OK
;
6027 /****************************************************************************
6028 Deal with SMB_FILE_POSITION_INFORMATION.
6029 ****************************************************************************/
6031 static NTSTATUS
smb_file_position_information(connection_struct
*conn
,
6036 uint64_t position_information
;
6038 if (total_data
< 8) {
6039 return NT_STATUS_INVALID_PARAMETER
;
6043 /* Ignore on pathname based set. */
6044 return NT_STATUS_OK
;
6047 position_information
= (uint64_t)IVAL(pdata
,0);
6048 position_information
|= (((uint64_t)IVAL(pdata
,4)) << 32);
6050 DEBUG(10,("smb_file_position_information: Set file position "
6051 "information for file %s to %.0f\n", fsp_str_dbg(fsp
),
6052 (double)position_information
));
6053 fsp
->fh
->position_information
= position_information
;
6054 return NT_STATUS_OK
;
6057 /****************************************************************************
6058 Deal with SMB_FILE_MODE_INFORMATION.
6059 ****************************************************************************/
6061 static NTSTATUS
smb_file_mode_information(connection_struct
*conn
,
6067 if (total_data
< 4) {
6068 return NT_STATUS_INVALID_PARAMETER
;
6070 mode
= IVAL(pdata
,0);
6071 if (mode
!= 0 && mode
!= 2 && mode
!= 4 && mode
!= 6) {
6072 return NT_STATUS_INVALID_PARAMETER
;
6074 return NT_STATUS_OK
;
6077 /****************************************************************************
6078 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
6079 ****************************************************************************/
6081 static NTSTATUS
smb_set_file_unix_link(connection_struct
*conn
,
6082 struct smb_request
*req
,
6085 const struct smb_filename
*smb_fname
)
6087 char *link_target
= NULL
;
6088 const char *newname
= smb_fname
->base_name
;
6089 TALLOC_CTX
*ctx
= talloc_tos();
6091 /* Set a symbolic link. */
6092 /* Don't allow this if follow links is false. */
6094 if (total_data
== 0) {
6095 return NT_STATUS_INVALID_PARAMETER
;
6098 if (!lp_symlinks(SNUM(conn
))) {
6099 return NT_STATUS_ACCESS_DENIED
;
6102 srvstr_pull_talloc(ctx
, pdata
, req
->flags2
, &link_target
, pdata
,
6103 total_data
, STR_TERMINATE
);
6106 return NT_STATUS_INVALID_PARAMETER
;
6109 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
6110 newname
, link_target
));
6112 if (SMB_VFS_SYMLINK(conn
,link_target
,newname
) != 0) {
6113 return map_nt_error_from_unix(errno
);
6116 return NT_STATUS_OK
;
6119 /****************************************************************************
6120 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
6121 ****************************************************************************/
6123 static NTSTATUS
smb_set_file_unix_hlink(connection_struct
*conn
,
6124 struct smb_request
*req
,
6125 const char *pdata
, int total_data
,
6126 struct smb_filename
*smb_fname_new
)
6128 char *oldname
= NULL
;
6129 struct smb_filename
*smb_fname_old
= NULL
;
6130 TALLOC_CTX
*ctx
= talloc_tos();
6131 NTSTATUS status
= NT_STATUS_OK
;
6133 /* Set a hard link. */
6134 if (total_data
== 0) {
6135 return NT_STATUS_INVALID_PARAMETER
;
6138 srvstr_get_path(ctx
, pdata
, req
->flags2
, &oldname
, pdata
,
6139 total_data
, STR_TERMINATE
, &status
);
6140 if (!NT_STATUS_IS_OK(status
)) {
6144 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
6145 smb_fname_str_dbg(smb_fname_new
), oldname
));
6147 status
= filename_convert(ctx
,
6149 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6154 if (!NT_STATUS_IS_OK(status
)) {
6158 return hardlink_internals(ctx
, conn
, req
, false,
6159 smb_fname_old
, smb_fname_new
);
6162 /****************************************************************************
6163 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
6164 ****************************************************************************/
6166 static NTSTATUS
smb2_file_rename_information(connection_struct
*conn
,
6167 struct smb_request
*req
,
6171 struct smb_filename
*smb_fname_src
)
6175 char *newname
= NULL
;
6176 struct smb_filename
*smb_fname_dst
= NULL
;
6177 NTSTATUS status
= NT_STATUS_OK
;
6178 TALLOC_CTX
*ctx
= talloc_tos();
6181 return NT_STATUS_INVALID_HANDLE
;
6184 if (total_data
< 20) {
6185 return NT_STATUS_INVALID_PARAMETER
;
6188 overwrite
= (CVAL(pdata
,0) ? True
: False
);
6189 len
= IVAL(pdata
,16);
6191 if (len
> (total_data
- 20) || (len
== 0)) {
6192 return NT_STATUS_INVALID_PARAMETER
;
6195 srvstr_get_path(ctx
, pdata
, req
->flags2
, &newname
,
6196 &pdata
[20], len
, STR_TERMINATE
,
6198 if (!NT_STATUS_IS_OK(status
)) {
6202 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
6205 status
= filename_convert(ctx
,
6207 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6212 if (!NT_STATUS_IS_OK(status
)) {
6216 if (fsp
->base_fsp
) {
6217 /* newname must be a stream name. */
6218 if (newname
[0] != ':') {
6219 return NT_STATUS_NOT_SUPPORTED
;
6222 /* Create an smb_fname to call rename_internals_fsp() with. */
6223 smb_fname_dst
= synthetic_smb_fname(
6224 talloc_tos(), fsp
->base_fsp
->fsp_name
->base_name
,
6226 if (smb_fname_dst
== NULL
) {
6227 status
= NT_STATUS_NO_MEMORY
;
6232 * Set the original last component, since
6233 * rename_internals_fsp() requires it.
6235 smb_fname_dst
->original_lcomp
= talloc_strdup(smb_fname_dst
,
6237 if (smb_fname_dst
->original_lcomp
== NULL
) {
6238 status
= NT_STATUS_NO_MEMORY
;
6244 DEBUG(10,("smb2_file_rename_information: "
6245 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
6246 fsp_fnum_dbg(fsp
), fsp_str_dbg(fsp
),
6247 smb_fname_str_dbg(smb_fname_dst
)));
6248 status
= rename_internals_fsp(conn
, fsp
, smb_fname_dst
,
6249 (FILE_ATTRIBUTE_HIDDEN
|FILE_ATTRIBUTE_SYSTEM
),
6253 TALLOC_FREE(smb_fname_dst
);
6257 static NTSTATUS
smb_file_link_information(connection_struct
*conn
,
6258 struct smb_request
*req
,
6262 struct smb_filename
*smb_fname_src
)
6266 char *newname
= NULL
;
6267 struct smb_filename
*smb_fname_dst
= NULL
;
6268 NTSTATUS status
= NT_STATUS_OK
;
6269 TALLOC_CTX
*ctx
= talloc_tos();
6272 return NT_STATUS_INVALID_HANDLE
;
6275 if (total_data
< 20) {
6276 return NT_STATUS_INVALID_PARAMETER
;
6279 overwrite
= (CVAL(pdata
,0) ? true : false);
6280 len
= IVAL(pdata
,16);
6282 if (len
> (total_data
- 20) || (len
== 0)) {
6283 return NT_STATUS_INVALID_PARAMETER
;
6286 srvstr_get_path(ctx
, pdata
, req
->flags2
, &newname
,
6287 &pdata
[20], len
, STR_TERMINATE
,
6289 if (!NT_STATUS_IS_OK(status
)) {
6293 DEBUG(10,("smb_file_link_information: got name |%s|\n",
6296 status
= filename_convert(ctx
,
6298 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6303 if (!NT_STATUS_IS_OK(status
)) {
6307 if (fsp
->base_fsp
) {
6308 /* No stream names. */
6309 return NT_STATUS_NOT_SUPPORTED
;
6312 DEBUG(10,("smb_file_link_information: "
6313 "SMB_FILE_LINK_INFORMATION (%s) %s -> %s\n",
6314 fsp_fnum_dbg(fsp
), fsp_str_dbg(fsp
),
6315 smb_fname_str_dbg(smb_fname_dst
)));
6316 status
= hardlink_internals(ctx
,
6323 TALLOC_FREE(smb_fname_dst
);
6327 /****************************************************************************
6328 Deal with SMB_FILE_RENAME_INFORMATION.
6329 ****************************************************************************/
6331 static NTSTATUS
smb_file_rename_information(connection_struct
*conn
,
6332 struct smb_request
*req
,
6336 struct smb_filename
*smb_fname_src
)
6341 char *newname
= NULL
;
6342 struct smb_filename
*smb_fname_dst
= NULL
;
6343 bool dest_has_wcard
= False
;
6344 NTSTATUS status
= NT_STATUS_OK
;
6346 TALLOC_CTX
*ctx
= talloc_tos();
6348 if (total_data
< 13) {
6349 return NT_STATUS_INVALID_PARAMETER
;
6352 overwrite
= (CVAL(pdata
,0) ? True
: False
);
6353 root_fid
= IVAL(pdata
,4);
6354 len
= IVAL(pdata
,8);
6356 if (len
> (total_data
- 12) || (len
== 0) || (root_fid
!= 0)) {
6357 return NT_STATUS_INVALID_PARAMETER
;
6360 srvstr_get_path_wcard(ctx
, pdata
, req
->flags2
, &newname
, &pdata
[12],
6363 if (!NT_STATUS_IS_OK(status
)) {
6367 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
6370 status
= resolve_dfspath_wcard(ctx
, conn
,
6371 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6374 !conn
->sconn
->using_smb2
,
6377 if (!NT_STATUS_IS_OK(status
)) {
6381 /* Check the new name has no '/' characters. */
6382 if (strchr_m(newname
, '/')) {
6383 return NT_STATUS_NOT_SUPPORTED
;
6386 if (fsp
&& fsp
->base_fsp
) {
6387 /* newname must be a stream name. */
6388 if (newname
[0] != ':') {
6389 return NT_STATUS_NOT_SUPPORTED
;
6392 /* Create an smb_fname to call rename_internals_fsp() with. */
6393 smb_fname_dst
= synthetic_smb_fname(
6394 talloc_tos(), fsp
->base_fsp
->fsp_name
->base_name
,
6396 if (smb_fname_dst
== NULL
) {
6397 status
= NT_STATUS_NO_MEMORY
;
6402 * Set the original last component, since
6403 * rename_internals_fsp() requires it.
6405 smb_fname_dst
->original_lcomp
= talloc_strdup(smb_fname_dst
,
6407 if (smb_fname_dst
->original_lcomp
== NULL
) {
6408 status
= NT_STATUS_NO_MEMORY
;
6414 * Build up an smb_fname_dst based on the filename passed in.
6415 * We basically just strip off the last component, and put on
6416 * the newname instead.
6418 char *base_name
= NULL
;
6420 /* newname must *not* be a stream name. */
6421 if (newname
[0] == ':') {
6422 return NT_STATUS_NOT_SUPPORTED
;
6426 * Strip off the last component (filename) of the path passed
6429 base_name
= talloc_strdup(ctx
, smb_fname_src
->base_name
);
6431 return NT_STATUS_NO_MEMORY
;
6433 p
= strrchr_m(base_name
, '/');
6437 base_name
= talloc_strdup(ctx
, "");
6439 return NT_STATUS_NO_MEMORY
;
6442 /* Append the new name. */
6443 base_name
= talloc_asprintf_append(base_name
,
6447 return NT_STATUS_NO_MEMORY
;
6450 status
= unix_convert(ctx
, conn
, base_name
, &smb_fname_dst
,
6453 UCF_ALWAYS_ALLOW_WCARD_LCOMP
:
6456 /* If an error we expect this to be
6457 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
6459 if (!NT_STATUS_IS_OK(status
)) {
6460 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND
,
6464 /* Create an smb_fname to call rename_internals_fsp() */
6465 smb_fname_dst
= synthetic_smb_fname(
6466 ctx
, base_name
, NULL
, NULL
);
6467 if (smb_fname_dst
== NULL
) {
6468 status
= NT_STATUS_NO_MEMORY
;
6475 DEBUG(10,("smb_file_rename_information: "
6476 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
6477 fsp_fnum_dbg(fsp
), fsp_str_dbg(fsp
),
6478 smb_fname_str_dbg(smb_fname_dst
)));
6479 status
= rename_internals_fsp(conn
, fsp
, smb_fname_dst
, 0,
6482 DEBUG(10,("smb_file_rename_information: "
6483 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
6484 smb_fname_str_dbg(smb_fname_src
),
6485 smb_fname_str_dbg(smb_fname_dst
)));
6486 status
= rename_internals(ctx
, conn
, req
, smb_fname_src
,
6487 smb_fname_dst
, 0, overwrite
, false,
6489 FILE_WRITE_ATTRIBUTES
);
6492 TALLOC_FREE(smb_fname_dst
);
6496 /****************************************************************************
6497 Deal with SMB_SET_POSIX_ACL.
6498 ****************************************************************************/
6500 #if defined(HAVE_POSIX_ACLS)
6501 static NTSTATUS
smb_set_posix_acl(connection_struct
*conn
,
6505 const struct smb_filename
*smb_fname
)
6507 uint16 posix_acl_version
;
6508 uint16 num_file_acls
;
6509 uint16 num_def_acls
;
6510 bool valid_file_acls
= True
;
6511 bool valid_def_acls
= True
;
6513 if (total_data
< SMB_POSIX_ACL_HEADER_SIZE
) {
6514 return NT_STATUS_INVALID_PARAMETER
;
6516 posix_acl_version
= SVAL(pdata
,0);
6517 num_file_acls
= SVAL(pdata
,2);
6518 num_def_acls
= SVAL(pdata
,4);
6520 if (num_file_acls
== SMB_POSIX_IGNORE_ACE_ENTRIES
) {
6521 valid_file_acls
= False
;
6525 if (num_def_acls
== SMB_POSIX_IGNORE_ACE_ENTRIES
) {
6526 valid_def_acls
= False
;
6530 if (posix_acl_version
!= SMB_POSIX_ACL_VERSION
) {
6531 return NT_STATUS_INVALID_PARAMETER
;
6534 if (total_data
< SMB_POSIX_ACL_HEADER_SIZE
+
6535 (num_file_acls
+num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
) {
6536 return NT_STATUS_INVALID_PARAMETER
;
6539 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
6540 smb_fname
? smb_fname_str_dbg(smb_fname
) : fsp_str_dbg(fsp
),
6541 (unsigned int)num_file_acls
,
6542 (unsigned int)num_def_acls
));
6544 if (valid_file_acls
&& !set_unix_posix_acl(conn
, fsp
,
6545 smb_fname
->base_name
, num_file_acls
,
6546 pdata
+ SMB_POSIX_ACL_HEADER_SIZE
)) {
6547 return map_nt_error_from_unix(errno
);
6550 if (valid_def_acls
&& !set_unix_posix_default_acl(conn
,
6551 smb_fname
->base_name
, &smb_fname
->st
, num_def_acls
,
6552 pdata
+ SMB_POSIX_ACL_HEADER_SIZE
+
6553 (num_file_acls
*SMB_POSIX_ACL_ENTRY_SIZE
))) {
6554 return map_nt_error_from_unix(errno
);
6556 return NT_STATUS_OK
;
6560 /****************************************************************************
6561 Deal with SMB_SET_POSIX_LOCK.
6562 ****************************************************************************/
6564 static NTSTATUS
smb_set_posix_lock(connection_struct
*conn
,
6565 struct smb_request
*req
,
6573 bool blocking_lock
= False
;
6574 enum brl_type lock_type
;
6576 NTSTATUS status
= NT_STATUS_OK
;
6578 if (fsp
== NULL
|| fsp
->fh
->fd
== -1) {
6579 return NT_STATUS_INVALID_HANDLE
;
6582 if (total_data
!= POSIX_LOCK_DATA_SIZE
) {
6583 return NT_STATUS_INVALID_PARAMETER
;
6586 switch (SVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
)) {
6587 case POSIX_LOCK_TYPE_READ
:
6588 lock_type
= READ_LOCK
;
6590 case POSIX_LOCK_TYPE_WRITE
:
6591 /* Return the right POSIX-mappable error code for files opened read-only. */
6592 if (!fsp
->can_write
) {
6593 return NT_STATUS_INVALID_HANDLE
;
6595 lock_type
= WRITE_LOCK
;
6597 case POSIX_LOCK_TYPE_UNLOCK
:
6598 lock_type
= UNLOCK_LOCK
;
6601 return NT_STATUS_INVALID_PARAMETER
;
6604 if (SVAL(pdata
,POSIX_LOCK_FLAGS_OFFSET
) == POSIX_LOCK_FLAG_NOWAIT
) {
6605 blocking_lock
= False
;
6606 } else if (SVAL(pdata
,POSIX_LOCK_FLAGS_OFFSET
) == POSIX_LOCK_FLAG_WAIT
) {
6607 blocking_lock
= True
;
6609 return NT_STATUS_INVALID_PARAMETER
;
6612 if (!lp_blocking_locks(SNUM(conn
))) {
6613 blocking_lock
= False
;
6616 smblctx
= (uint64_t)IVAL(pdata
, POSIX_LOCK_PID_OFFSET
);
6617 #if defined(HAVE_LONGLONG)
6618 offset
= (((uint64_t) IVAL(pdata
,(POSIX_LOCK_START_OFFSET
+4))) << 32) |
6619 ((uint64_t) IVAL(pdata
,POSIX_LOCK_START_OFFSET
));
6620 count
= (((uint64_t) IVAL(pdata
,(POSIX_LOCK_LEN_OFFSET
+4))) << 32) |
6621 ((uint64_t) IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
));
6622 #else /* HAVE_LONGLONG */
6623 offset
= (uint64_t)IVAL(pdata
,POSIX_LOCK_START_OFFSET
);
6624 count
= (uint64_t)IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
);
6625 #endif /* HAVE_LONGLONG */
6627 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
6628 "smblctx = %llu, count = %.0f, offset = %.0f\n",
6630 (unsigned int)lock_type
,
6631 (unsigned long long)smblctx
,
6635 if (lock_type
== UNLOCK_LOCK
) {
6636 status
= do_unlock(req
->sconn
->msg_ctx
,
6643 uint64_t block_smblctx
;
6645 struct byte_range_lock
*br_lck
= do_lock(req
->sconn
->msg_ctx
,
6657 if (br_lck
&& blocking_lock
&& ERROR_WAS_LOCK_DENIED(status
)) {
6659 * A blocking lock was requested. Package up
6660 * this smb into a queued request and push it
6661 * onto the blocking lock queue.
6663 if(push_blocking_lock_request(br_lck
,
6666 -1, /* infinite timeout. */
6674 TALLOC_FREE(br_lck
);
6678 TALLOC_FREE(br_lck
);
6684 /****************************************************************************
6685 Deal with SMB_SET_FILE_BASIC_INFO.
6686 ****************************************************************************/
6688 static NTSTATUS
smb_set_file_basic_info(connection_struct
*conn
,
6692 const struct smb_filename
*smb_fname
)
6694 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
6695 struct smb_file_time ft
;
6697 NTSTATUS status
= NT_STATUS_OK
;
6701 if (total_data
< 36) {
6702 return NT_STATUS_INVALID_PARAMETER
;
6705 status
= check_access(conn
, fsp
, smb_fname
, FILE_WRITE_ATTRIBUTES
);
6706 if (!NT_STATUS_IS_OK(status
)) {
6710 /* Set the attributes */
6711 dosmode
= IVAL(pdata
,32);
6712 status
= smb_set_file_dosmode(conn
, smb_fname
, dosmode
);
6713 if (!NT_STATUS_IS_OK(status
)) {
6718 ft
.create_time
= interpret_long_date(pdata
);
6721 ft
.atime
= interpret_long_date(pdata
+8);
6724 ft
.mtime
= interpret_long_date(pdata
+16);
6727 ft
.ctime
= interpret_long_date(pdata
+24);
6729 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
6730 smb_fname_str_dbg(smb_fname
)));
6732 return smb_set_file_time(conn
, fsp
, smb_fname
, &ft
,
6736 /****************************************************************************
6737 Deal with SMB_INFO_STANDARD.
6738 ****************************************************************************/
6740 static NTSTATUS
smb_set_info_standard(connection_struct
*conn
,
6744 const struct smb_filename
*smb_fname
)
6747 struct smb_file_time ft
;
6751 if (total_data
< 12) {
6752 return NT_STATUS_INVALID_PARAMETER
;
6756 ft
.create_time
= convert_time_t_to_timespec(srv_make_unix_date2(pdata
));
6758 ft
.atime
= convert_time_t_to_timespec(srv_make_unix_date2(pdata
+4));
6760 ft
.mtime
= convert_time_t_to_timespec(srv_make_unix_date2(pdata
+8));
6762 DEBUG(10,("smb_set_info_standard: file %s\n",
6763 smb_fname_str_dbg(smb_fname
)));
6765 status
= check_access(conn
, fsp
, smb_fname
, FILE_WRITE_ATTRIBUTES
);
6766 if (!NT_STATUS_IS_OK(status
)) {
6770 return smb_set_file_time(conn
,
6777 /****************************************************************************
6778 Deal with SMB_SET_FILE_ALLOCATION_INFO.
6779 ****************************************************************************/
6781 static NTSTATUS
smb_set_file_allocation_info(connection_struct
*conn
,
6782 struct smb_request
*req
,
6786 struct smb_filename
*smb_fname
)
6788 uint64_t allocation_size
= 0;
6789 NTSTATUS status
= NT_STATUS_OK
;
6790 files_struct
*new_fsp
= NULL
;
6792 if (!VALID_STAT(smb_fname
->st
)) {
6793 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
6796 if (total_data
< 8) {
6797 return NT_STATUS_INVALID_PARAMETER
;
6800 allocation_size
= (uint64_t)IVAL(pdata
,0);
6801 allocation_size
|= (((uint64_t)IVAL(pdata
,4)) << 32);
6802 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
6803 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname
),
6804 (double)allocation_size
));
6806 if (allocation_size
) {
6807 allocation_size
= smb_roundup(conn
, allocation_size
);
6810 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
6811 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname
),
6812 (double)allocation_size
));
6814 if (fsp
&& fsp
->fh
->fd
!= -1) {
6815 /* Open file handle. */
6816 if (!(fsp
->access_mask
& FILE_WRITE_DATA
)) {
6817 return NT_STATUS_ACCESS_DENIED
;
6820 /* Only change if needed. */
6821 if (allocation_size
!= get_file_size_stat(&smb_fname
->st
)) {
6822 if (vfs_allocate_file_space(fsp
, allocation_size
) == -1) {
6823 return map_nt_error_from_unix(errno
);
6826 /* But always update the time. */
6828 * This is equivalent to a write. Ensure it's seen immediately
6829 * if there are no pending writes.
6831 trigger_write_time_update_immediate(fsp
);
6832 return NT_STATUS_OK
;
6835 /* Pathname or stat or directory file. */
6836 status
= SMB_VFS_CREATE_FILE(
6839 0, /* root_dir_fid */
6840 smb_fname
, /* fname */
6841 FILE_WRITE_DATA
, /* access_mask */
6842 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
6844 FILE_OPEN
, /* create_disposition*/
6845 0, /* create_options */
6846 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
6847 FORCE_OPLOCK_BREAK_TO_NONE
, /* oplock_request */
6848 0, /* allocation_size */
6849 0, /* private_flags */
6852 &new_fsp
, /* result */
6855 if (!NT_STATUS_IS_OK(status
)) {
6856 /* NB. We check for open_was_deferred in the caller. */
6860 /* Only change if needed. */
6861 if (allocation_size
!= get_file_size_stat(&smb_fname
->st
)) {
6862 if (vfs_allocate_file_space(new_fsp
, allocation_size
) == -1) {
6863 status
= map_nt_error_from_unix(errno
);
6864 close_file(req
, new_fsp
, NORMAL_CLOSE
);
6869 /* Changing the allocation size should set the last mod time. */
6871 * This is equivalent to a write. Ensure it's seen immediately
6872 * if there are no pending writes.
6874 trigger_write_time_update_immediate(new_fsp
);
6876 close_file(req
, new_fsp
, NORMAL_CLOSE
);
6877 return NT_STATUS_OK
;
6880 /****************************************************************************
6881 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
6882 ****************************************************************************/
6884 static NTSTATUS
smb_set_file_end_of_file_info(connection_struct
*conn
,
6885 struct smb_request
*req
,
6889 const struct smb_filename
*smb_fname
,
6890 bool fail_after_createfile
)
6894 if (total_data
< 8) {
6895 return NT_STATUS_INVALID_PARAMETER
;
6898 size
= IVAL(pdata
,0);
6899 size
|= (((off_t
)IVAL(pdata
,4)) << 32);
6900 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
6901 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname
),
6904 return smb_set_file_size(conn
, req
,
6909 fail_after_createfile
);
6912 /****************************************************************************
6913 Allow a UNIX info mknod.
6914 ****************************************************************************/
6916 static NTSTATUS
smb_unix_mknod(connection_struct
*conn
,
6919 const struct smb_filename
*smb_fname
)
6921 uint32 file_type
= IVAL(pdata
,56);
6922 #if defined(HAVE_MAKEDEV)
6923 uint32 dev_major
= IVAL(pdata
,60);
6924 uint32 dev_minor
= IVAL(pdata
,68);
6926 SMB_DEV_T dev
= (SMB_DEV_T
)0;
6927 uint32 raw_unixmode
= IVAL(pdata
,84);
6931 if (total_data
< 100) {
6932 return NT_STATUS_INVALID_PARAMETER
;
6935 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
6936 PERM_NEW_FILE
, &unixmode
);
6937 if (!NT_STATUS_IS_OK(status
)) {
6941 #if defined(HAVE_MAKEDEV)
6942 dev
= makedev(dev_major
, dev_minor
);
6945 switch (file_type
) {
6946 #if defined(S_IFIFO)
6947 case UNIX_TYPE_FIFO
:
6948 unixmode
|= S_IFIFO
;
6951 #if defined(S_IFSOCK)
6952 case UNIX_TYPE_SOCKET
:
6953 unixmode
|= S_IFSOCK
;
6956 #if defined(S_IFCHR)
6957 case UNIX_TYPE_CHARDEV
:
6958 unixmode
|= S_IFCHR
;
6961 #if defined(S_IFBLK)
6962 case UNIX_TYPE_BLKDEV
:
6963 unixmode
|= S_IFBLK
;
6967 return NT_STATUS_INVALID_PARAMETER
;
6970 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
6971 "%.0f mode 0%o for file %s\n", (double)dev
,
6972 (unsigned int)unixmode
, smb_fname_str_dbg(smb_fname
)));
6974 /* Ok - do the mknod. */
6975 if (SMB_VFS_MKNOD(conn
, smb_fname
->base_name
, unixmode
, dev
) != 0) {
6976 return map_nt_error_from_unix(errno
);
6979 /* If any of the other "set" calls fail we
6980 * don't want to end up with a half-constructed mknod.
6983 if (lp_inherit_perms(SNUM(conn
))) {
6985 if (!parent_dirname(talloc_tos(), smb_fname
->base_name
,
6987 return NT_STATUS_NO_MEMORY
;
6989 inherit_access_posix_acl(conn
, parent
, smb_fname
->base_name
,
6991 TALLOC_FREE(parent
);
6994 return NT_STATUS_OK
;
6997 /****************************************************************************
6998 Deal with SMB_SET_FILE_UNIX_BASIC.
6999 ****************************************************************************/
7001 static NTSTATUS
smb_set_file_unix_basic(connection_struct
*conn
,
7002 struct smb_request
*req
,
7006 const struct smb_filename
*smb_fname
)
7008 struct smb_file_time ft
;
7009 uint32 raw_unixmode
;
7012 uid_t set_owner
= (uid_t
)SMB_UID_NO_CHANGE
;
7013 gid_t set_grp
= (uid_t
)SMB_GID_NO_CHANGE
;
7014 NTSTATUS status
= NT_STATUS_OK
;
7015 bool delete_on_fail
= False
;
7016 enum perm_type ptype
;
7017 files_struct
*all_fsps
= NULL
;
7018 bool modify_mtime
= true;
7020 struct smb_filename
*smb_fname_tmp
= NULL
;
7021 SMB_STRUCT_STAT sbuf
;
7025 if (total_data
< 100) {
7026 return NT_STATUS_INVALID_PARAMETER
;
7029 if(IVAL(pdata
, 0) != SMB_SIZE_NO_CHANGE_LO
&&
7030 IVAL(pdata
, 4) != SMB_SIZE_NO_CHANGE_HI
) {
7031 size
=IVAL(pdata
,0); /* first 8 Bytes are size */
7032 size
|= (((off_t
)IVAL(pdata
,4)) << 32);
7035 ft
.atime
= interpret_long_date(pdata
+24); /* access_time */
7036 ft
.mtime
= interpret_long_date(pdata
+32); /* modification_time */
7037 set_owner
= (uid_t
)IVAL(pdata
,40);
7038 set_grp
= (gid_t
)IVAL(pdata
,48);
7039 raw_unixmode
= IVAL(pdata
,84);
7041 if (VALID_STAT(smb_fname
->st
)) {
7042 if (S_ISDIR(smb_fname
->st
.st_ex_mode
)) {
7043 ptype
= PERM_EXISTING_DIR
;
7045 ptype
= PERM_EXISTING_FILE
;
7048 ptype
= PERM_NEW_FILE
;
7051 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
7053 if (!NT_STATUS_IS_OK(status
)) {
7057 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
7058 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
7059 smb_fname_str_dbg(smb_fname
), (double)size
,
7060 (unsigned int)set_owner
, (unsigned int)set_grp
,
7061 (int)raw_unixmode
));
7063 sbuf
= smb_fname
->st
;
7065 if (!VALID_STAT(sbuf
)) {
7067 * The only valid use of this is to create character and block
7068 * devices, and named pipes. This is deprecated (IMHO) and
7069 * a new info level should be used for mknod. JRA.
7072 status
= smb_unix_mknod(conn
,
7076 if (!NT_STATUS_IS_OK(status
)) {
7080 smb_fname_tmp
= cp_smb_filename(talloc_tos(), smb_fname
);
7081 if (smb_fname_tmp
== NULL
) {
7082 return NT_STATUS_NO_MEMORY
;
7085 if (SMB_VFS_STAT(conn
, smb_fname_tmp
) != 0) {
7086 status
= map_nt_error_from_unix(errno
);
7087 TALLOC_FREE(smb_fname_tmp
);
7088 SMB_VFS_UNLINK(conn
, smb_fname
);
7092 sbuf
= smb_fname_tmp
->st
;
7093 smb_fname
= smb_fname_tmp
;
7095 /* Ensure we don't try and change anything else. */
7096 raw_unixmode
= SMB_MODE_NO_CHANGE
;
7097 size
= get_file_size_stat(&sbuf
);
7098 ft
.atime
= sbuf
.st_ex_atime
;
7099 ft
.mtime
= sbuf
.st_ex_mtime
;
7101 * We continue here as we might want to change the
7104 delete_on_fail
= True
;
7108 /* Horrible backwards compatibility hack as an old server bug
7109 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
7113 size
= get_file_size_stat(&sbuf
);
7118 * Deal with the UNIX specific mode set.
7121 if (raw_unixmode
!= SMB_MODE_NO_CHANGE
) {
7122 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7123 "setting mode 0%o for file %s\n",
7124 (unsigned int)unixmode
,
7125 smb_fname_str_dbg(smb_fname
)));
7126 if (SMB_VFS_CHMOD(conn
, smb_fname
->base_name
, unixmode
) != 0) {
7127 return map_nt_error_from_unix(errno
);
7132 * Deal with the UNIX specific uid set.
7135 if ((set_owner
!= (uid_t
)SMB_UID_NO_CHANGE
) &&
7136 (sbuf
.st_ex_uid
!= set_owner
)) {
7139 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7140 "changing owner %u for path %s\n",
7141 (unsigned int)set_owner
,
7142 smb_fname_str_dbg(smb_fname
)));
7144 if (S_ISLNK(sbuf
.st_ex_mode
)) {
7145 ret
= SMB_VFS_LCHOWN(conn
, smb_fname
->base_name
,
7146 set_owner
, (gid_t
)-1);
7148 ret
= SMB_VFS_CHOWN(conn
, smb_fname
->base_name
,
7149 set_owner
, (gid_t
)-1);
7153 status
= map_nt_error_from_unix(errno
);
7154 if (delete_on_fail
) {
7155 SMB_VFS_UNLINK(conn
, smb_fname
);
7162 * Deal with the UNIX specific gid set.
7165 if ((set_grp
!= (uid_t
)SMB_GID_NO_CHANGE
) &&
7166 (sbuf
.st_ex_gid
!= set_grp
)) {
7167 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7168 "changing group %u for file %s\n",
7169 (unsigned int)set_owner
,
7170 smb_fname_str_dbg(smb_fname
)));
7171 if (SMB_VFS_CHOWN(conn
, smb_fname
->base_name
, (uid_t
)-1,
7173 status
= map_nt_error_from_unix(errno
);
7174 if (delete_on_fail
) {
7175 SMB_VFS_UNLINK(conn
, smb_fname
);
7181 /* Deal with any size changes. */
7183 status
= smb_set_file_size(conn
, req
,
7189 if (!NT_STATUS_IS_OK(status
)) {
7193 /* Deal with any time changes. */
7194 if (null_timespec(ft
.mtime
) && null_timespec(ft
.atime
)) {
7195 /* No change, don't cancel anything. */
7199 id
= vfs_file_id_from_sbuf(conn
, &sbuf
);
7200 for(all_fsps
= file_find_di_first(conn
->sconn
, id
); all_fsps
;
7201 all_fsps
= file_find_di_next(all_fsps
)) {
7203 * We're setting the time explicitly for UNIX.
7204 * Cancel any pending changes over all handles.
7206 all_fsps
->update_write_time_on_close
= false;
7207 TALLOC_FREE(all_fsps
->update_write_time_event
);
7211 * Override the "setting_write_time"
7212 * parameter here as it almost does what
7213 * we need. Just remember if we modified
7214 * mtime and send the notify ourselves.
7216 if (null_timespec(ft
.mtime
)) {
7217 modify_mtime
= false;
7220 status
= smb_set_file_time(conn
,
7226 notify_fname(conn
, NOTIFY_ACTION_MODIFIED
,
7227 FILE_NOTIFY_CHANGE_LAST_WRITE
, smb_fname
->base_name
);
7232 /****************************************************************************
7233 Deal with SMB_SET_FILE_UNIX_INFO2.
7234 ****************************************************************************/
7236 static NTSTATUS
smb_set_file_unix_info2(connection_struct
*conn
,
7237 struct smb_request
*req
,
7241 const struct smb_filename
*smb_fname
)
7247 if (total_data
< 116) {
7248 return NT_STATUS_INVALID_PARAMETER
;
7251 /* Start by setting all the fields that are common between UNIX_BASIC
7254 status
= smb_set_file_unix_basic(conn
, req
, pdata
, total_data
,
7256 if (!NT_STATUS_IS_OK(status
)) {
7260 smb_fflags
= IVAL(pdata
, 108);
7261 smb_fmask
= IVAL(pdata
, 112);
7263 /* NB: We should only attempt to alter the file flags if the client
7264 * sends a non-zero mask.
7266 if (smb_fmask
!= 0) {
7267 int stat_fflags
= 0;
7269 if (!map_info2_flags_to_sbuf(&smb_fname
->st
, smb_fflags
,
7270 smb_fmask
, &stat_fflags
)) {
7271 /* Client asked to alter a flag we don't understand. */
7272 return NT_STATUS_INVALID_PARAMETER
;
7275 if (fsp
&& fsp
->fh
->fd
!= -1) {
7276 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
7277 return NT_STATUS_NOT_SUPPORTED
;
7279 if (SMB_VFS_CHFLAGS(conn
, smb_fname
->base_name
,
7280 stat_fflags
) != 0) {
7281 return map_nt_error_from_unix(errno
);
7286 /* XXX: need to add support for changing the create_time here. You
7287 * can do this for paths on Darwin with setattrlist(2). The right way
7288 * to hook this up is probably by extending the VFS utimes interface.
7291 return NT_STATUS_OK
;
7294 /****************************************************************************
7295 Create a directory with POSIX semantics.
7296 ****************************************************************************/
7298 static NTSTATUS
smb_posix_mkdir(connection_struct
*conn
,
7299 struct smb_request
*req
,
7302 struct smb_filename
*smb_fname
,
7303 int *pdata_return_size
)
7305 NTSTATUS status
= NT_STATUS_OK
;
7306 uint32 raw_unixmode
= 0;
7307 uint32 mod_unixmode
= 0;
7308 mode_t unixmode
= (mode_t
)0;
7309 files_struct
*fsp
= NULL
;
7310 uint16 info_level_return
= 0;
7312 char *pdata
= *ppdata
;
7314 if (total_data
< 18) {
7315 return NT_STATUS_INVALID_PARAMETER
;
7318 raw_unixmode
= IVAL(pdata
,8);
7319 /* Next 4 bytes are not yet defined. */
7321 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
7322 PERM_NEW_DIR
, &unixmode
);
7323 if (!NT_STATUS_IS_OK(status
)) {
7327 mod_unixmode
= (uint32
)unixmode
| FILE_FLAG_POSIX_SEMANTICS
;
7329 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
7330 smb_fname_str_dbg(smb_fname
), (unsigned int)unixmode
));
7332 status
= SMB_VFS_CREATE_FILE(
7335 0, /* root_dir_fid */
7336 smb_fname
, /* fname */
7337 FILE_READ_ATTRIBUTES
, /* access_mask */
7338 FILE_SHARE_NONE
, /* share_access */
7339 FILE_CREATE
, /* create_disposition*/
7340 FILE_DIRECTORY_FILE
, /* create_options */
7341 mod_unixmode
, /* file_attributes */
7342 0, /* oplock_request */
7343 0, /* allocation_size */
7344 0, /* private_flags */
7350 if (NT_STATUS_IS_OK(status
)) {
7351 close_file(req
, fsp
, NORMAL_CLOSE
);
7354 info_level_return
= SVAL(pdata
,16);
7356 if (info_level_return
== SMB_QUERY_FILE_UNIX_BASIC
) {
7357 *pdata_return_size
= 12 + SMB_FILE_UNIX_BASIC_SIZE
;
7358 } else if (info_level_return
== SMB_QUERY_FILE_UNIX_INFO2
) {
7359 *pdata_return_size
= 12 + SMB_FILE_UNIX_INFO2_SIZE
;
7361 *pdata_return_size
= 12;
7364 /* Realloc the data size */
7365 *ppdata
= (char *)SMB_REALLOC(*ppdata
,*pdata_return_size
);
7366 if (*ppdata
== NULL
) {
7367 *pdata_return_size
= 0;
7368 return NT_STATUS_NO_MEMORY
;
7372 SSVAL(pdata
,0,NO_OPLOCK_RETURN
);
7373 SSVAL(pdata
,2,0); /* No fnum. */
7374 SIVAL(pdata
,4,info
); /* Was directory created. */
7376 switch (info_level_return
) {
7377 case SMB_QUERY_FILE_UNIX_BASIC
:
7378 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_BASIC
);
7379 SSVAL(pdata
,10,0); /* Padding. */
7380 store_file_unix_basic(conn
, pdata
+ 12, fsp
,
7383 case SMB_QUERY_FILE_UNIX_INFO2
:
7384 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_INFO2
);
7385 SSVAL(pdata
,10,0); /* Padding. */
7386 store_file_unix_basic_info2(conn
, pdata
+ 12, fsp
,
7390 SSVAL(pdata
,8,SMB_NO_INFO_LEVEL_RETURNED
);
7391 SSVAL(pdata
,10,0); /* Padding. */
7398 /****************************************************************************
7399 Open/Create a file with POSIX semantics.
7400 ****************************************************************************/
7402 #define SMB_O_RDONLY_MAPPING (FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA)
7403 #define SMB_O_WRONLY_MAPPING (FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA)
7405 static NTSTATUS
smb_posix_open(connection_struct
*conn
,
7406 struct smb_request
*req
,
7409 struct smb_filename
*smb_fname
,
7410 int *pdata_return_size
)
7412 bool extended_oplock_granted
= False
;
7413 char *pdata
= *ppdata
;
7415 uint32 wire_open_mode
= 0;
7416 uint32 raw_unixmode
= 0;
7417 uint32 mod_unixmode
= 0;
7418 uint32 create_disp
= 0;
7419 uint32 access_mask
= 0;
7420 uint32 create_options
= FILE_NON_DIRECTORY_FILE
;
7421 NTSTATUS status
= NT_STATUS_OK
;
7422 mode_t unixmode
= (mode_t
)0;
7423 files_struct
*fsp
= NULL
;
7424 int oplock_request
= 0;
7426 uint16 info_level_return
= 0;
7428 if (total_data
< 18) {
7429 return NT_STATUS_INVALID_PARAMETER
;
7432 flags
= IVAL(pdata
,0);
7433 oplock_request
= (flags
& REQUEST_OPLOCK
) ? EXCLUSIVE_OPLOCK
: 0;
7434 if (oplock_request
) {
7435 oplock_request
|= (flags
& REQUEST_BATCH_OPLOCK
) ? BATCH_OPLOCK
: 0;
7438 wire_open_mode
= IVAL(pdata
,4);
7440 if (wire_open_mode
== (SMB_O_CREAT
|SMB_O_DIRECTORY
)) {
7441 return smb_posix_mkdir(conn
, req
,
7448 switch (wire_open_mode
& SMB_ACCMODE
) {
7450 access_mask
= SMB_O_RDONLY_MAPPING
;
7453 access_mask
= SMB_O_WRONLY_MAPPING
;
7456 access_mask
= (SMB_O_RDONLY_MAPPING
|
7457 SMB_O_WRONLY_MAPPING
);
7460 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
7461 (unsigned int)wire_open_mode
));
7462 return NT_STATUS_INVALID_PARAMETER
;
7465 wire_open_mode
&= ~SMB_ACCMODE
;
7467 /* First take care of O_CREAT|O_EXCL interactions. */
7468 switch (wire_open_mode
& (SMB_O_CREAT
| SMB_O_EXCL
)) {
7469 case (SMB_O_CREAT
| SMB_O_EXCL
):
7470 /* File exists fail. File not exist create. */
7471 create_disp
= FILE_CREATE
;
7474 /* File exists open. File not exist create. */
7475 create_disp
= FILE_OPEN_IF
;
7478 /* O_EXCL on its own without O_CREAT is undefined.
7479 We deliberately ignore it as some versions of
7480 Linux CIFSFS can send a bare O_EXCL on the
7481 wire which other filesystems in the kernel
7482 ignore. See bug 9519 for details. */
7487 /* File exists open. File not exist fail. */
7488 create_disp
= FILE_OPEN
;
7491 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
7492 (unsigned int)wire_open_mode
));
7493 return NT_STATUS_INVALID_PARAMETER
;
7496 /* Next factor in the effects of O_TRUNC. */
7497 wire_open_mode
&= ~(SMB_O_CREAT
| SMB_O_EXCL
);
7499 if (wire_open_mode
& SMB_O_TRUNC
) {
7500 switch (create_disp
) {
7502 /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
7503 /* Leave create_disp alone as
7504 (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
7506 /* File exists fail. File not exist create. */
7509 /* SMB_O_CREAT | SMB_O_TRUNC */
7510 /* File exists overwrite. File not exist create. */
7511 create_disp
= FILE_OVERWRITE_IF
;
7515 /* File exists overwrite. File not exist fail. */
7516 create_disp
= FILE_OVERWRITE
;
7519 /* Cannot get here. */
7520 smb_panic("smb_posix_open: logic error");
7521 return NT_STATUS_INVALID_PARAMETER
;
7525 raw_unixmode
= IVAL(pdata
,8);
7526 /* Next 4 bytes are not yet defined. */
7528 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
7529 (VALID_STAT(smb_fname
->st
) ?
7530 PERM_EXISTING_FILE
: PERM_NEW_FILE
),
7533 if (!NT_STATUS_IS_OK(status
)) {
7537 mod_unixmode
= (uint32
)unixmode
| FILE_FLAG_POSIX_SEMANTICS
;
7539 if (wire_open_mode
& SMB_O_SYNC
) {
7540 create_options
|= FILE_WRITE_THROUGH
;
7542 if (wire_open_mode
& SMB_O_APPEND
) {
7543 access_mask
|= FILE_APPEND_DATA
;
7545 if (wire_open_mode
& SMB_O_DIRECT
) {
7546 mod_unixmode
|= FILE_FLAG_NO_BUFFERING
;
7549 if ((wire_open_mode
& SMB_O_DIRECTORY
) ||
7550 VALID_STAT_OF_DIR(smb_fname
->st
)) {
7551 if (access_mask
!= SMB_O_RDONLY_MAPPING
) {
7552 return NT_STATUS_FILE_IS_A_DIRECTORY
;
7554 create_options
&= ~FILE_NON_DIRECTORY_FILE
;
7555 create_options
|= FILE_DIRECTORY_FILE
;
7558 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
7559 smb_fname_str_dbg(smb_fname
),
7560 (unsigned int)wire_open_mode
,
7561 (unsigned int)unixmode
));
7563 status
= SMB_VFS_CREATE_FILE(
7566 0, /* root_dir_fid */
7567 smb_fname
, /* fname */
7568 access_mask
, /* access_mask */
7569 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
7571 create_disp
, /* create_disposition*/
7572 create_options
, /* create_options */
7573 mod_unixmode
, /* file_attributes */
7574 oplock_request
, /* oplock_request */
7575 0, /* allocation_size */
7576 0, /* private_flags */
7582 if (!NT_STATUS_IS_OK(status
)) {
7586 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
7587 extended_oplock_granted
= True
;
7590 if(oplock_request
&& EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
7591 extended_oplock_granted
= True
;
7594 info_level_return
= SVAL(pdata
,16);
7596 /* Allocate the correct return size. */
7598 if (info_level_return
== SMB_QUERY_FILE_UNIX_BASIC
) {
7599 *pdata_return_size
= 12 + SMB_FILE_UNIX_BASIC_SIZE
;
7600 } else if (info_level_return
== SMB_QUERY_FILE_UNIX_INFO2
) {
7601 *pdata_return_size
= 12 + SMB_FILE_UNIX_INFO2_SIZE
;
7603 *pdata_return_size
= 12;
7606 /* Realloc the data size */
7607 *ppdata
= (char *)SMB_REALLOC(*ppdata
,*pdata_return_size
);
7608 if (*ppdata
== NULL
) {
7609 close_file(req
, fsp
, ERROR_CLOSE
);
7610 *pdata_return_size
= 0;
7611 return NT_STATUS_NO_MEMORY
;
7615 if (extended_oplock_granted
) {
7616 if (flags
& REQUEST_BATCH_OPLOCK
) {
7617 SSVAL(pdata
,0, BATCH_OPLOCK_RETURN
);
7619 SSVAL(pdata
,0, EXCLUSIVE_OPLOCK_RETURN
);
7621 } else if (fsp
->oplock_type
== LEVEL_II_OPLOCK
) {
7622 SSVAL(pdata
,0, LEVEL_II_OPLOCK_RETURN
);
7624 SSVAL(pdata
,0,NO_OPLOCK_RETURN
);
7627 SSVAL(pdata
,2,fsp
->fnum
);
7628 SIVAL(pdata
,4,info
); /* Was file created etc. */
7630 switch (info_level_return
) {
7631 case SMB_QUERY_FILE_UNIX_BASIC
:
7632 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_BASIC
);
7633 SSVAL(pdata
,10,0); /* padding. */
7634 store_file_unix_basic(conn
, pdata
+ 12, fsp
,
7637 case SMB_QUERY_FILE_UNIX_INFO2
:
7638 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_INFO2
);
7639 SSVAL(pdata
,10,0); /* padding. */
7640 store_file_unix_basic_info2(conn
, pdata
+ 12, fsp
,
7644 SSVAL(pdata
,8,SMB_NO_INFO_LEVEL_RETURNED
);
7645 SSVAL(pdata
,10,0); /* padding. */
7648 return NT_STATUS_OK
;
7651 /****************************************************************************
7652 Delete a file with POSIX semantics.
7653 ****************************************************************************/
7655 static NTSTATUS
smb_posix_unlink(connection_struct
*conn
,
7656 struct smb_request
*req
,
7659 struct smb_filename
*smb_fname
)
7661 NTSTATUS status
= NT_STATUS_OK
;
7662 files_struct
*fsp
= NULL
;
7666 int create_options
= 0;
7668 struct share_mode_lock
*lck
= NULL
;
7670 if (total_data
< 2) {
7671 return NT_STATUS_INVALID_PARAMETER
;
7674 flags
= SVAL(pdata
,0);
7676 if (!VALID_STAT(smb_fname
->st
)) {
7677 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
7680 if ((flags
== SMB_POSIX_UNLINK_DIRECTORY_TARGET
) &&
7681 !VALID_STAT_OF_DIR(smb_fname
->st
)) {
7682 return NT_STATUS_NOT_A_DIRECTORY
;
7685 DEBUG(10,("smb_posix_unlink: %s %s\n",
7686 (flags
== SMB_POSIX_UNLINK_DIRECTORY_TARGET
) ? "directory" : "file",
7687 smb_fname_str_dbg(smb_fname
)));
7689 if (VALID_STAT_OF_DIR(smb_fname
->st
)) {
7690 create_options
|= FILE_DIRECTORY_FILE
;
7693 status
= SMB_VFS_CREATE_FILE(
7696 0, /* root_dir_fid */
7697 smb_fname
, /* fname */
7698 DELETE_ACCESS
, /* access_mask */
7699 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
7701 FILE_OPEN
, /* create_disposition*/
7702 create_options
, /* create_options */
7703 FILE_FLAG_POSIX_SEMANTICS
|0777, /* file_attributes */
7704 0, /* oplock_request */
7705 0, /* allocation_size */
7706 0, /* private_flags */
7712 if (!NT_STATUS_IS_OK(status
)) {
7717 * Don't lie to client. If we can't really delete due to
7718 * non-POSIX opens return SHARING_VIOLATION.
7721 lck
= get_existing_share_mode_lock(talloc_tos(), fsp
->file_id
);
7723 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
7724 "lock for file %s\n", fsp_str_dbg(fsp
)));
7725 close_file(req
, fsp
, NORMAL_CLOSE
);
7726 return NT_STATUS_INVALID_PARAMETER
;
7730 * See if others still have the file open. If this is the case, then
7731 * don't delete. If all opens are POSIX delete we can set the delete
7732 * on close disposition.
7734 for (i
=0; i
<lck
->data
->num_share_modes
; i
++) {
7735 struct share_mode_entry
*e
= &lck
->data
->share_modes
[i
];
7736 if (is_valid_share_mode_entry(e
)) {
7737 if (e
->flags
& SHARE_MODE_FLAG_POSIX_OPEN
) {
7740 if (share_mode_stale_pid(lck
->data
, i
)) {
7743 /* Fail with sharing violation. */
7745 close_file(req
, fsp
, NORMAL_CLOSE
);
7746 return NT_STATUS_SHARING_VIOLATION
;
7751 * Set the delete on close.
7753 status
= smb_set_file_disposition_info(conn
,
7761 if (!NT_STATUS_IS_OK(status
)) {
7762 close_file(req
, fsp
, NORMAL_CLOSE
);
7765 return close_file(req
, fsp
, NORMAL_CLOSE
);
7768 NTSTATUS
smbd_do_setfilepathinfo(connection_struct
*conn
,
7769 struct smb_request
*req
,
7770 TALLOC_CTX
*mem_ctx
,
7771 uint16_t info_level
,
7773 struct smb_filename
*smb_fname
,
7774 char **ppdata
, int total_data
,
7777 char *pdata
= *ppdata
;
7778 NTSTATUS status
= NT_STATUS_OK
;
7779 int data_return_size
= 0;
7783 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
7784 return NT_STATUS_INVALID_LEVEL
;
7787 if (!CAN_WRITE(conn
)) {
7788 /* Allow POSIX opens. The open path will deny
7789 * any non-readonly opens. */
7790 if (info_level
!= SMB_POSIX_PATH_OPEN
) {
7791 return NT_STATUS_DOS(ERRSRV
, ERRaccess
);
7795 DEBUG(3,("smbd_do_setfilepathinfo: %s (%s) info_level=%d "
7796 "totdata=%d\n", smb_fname_str_dbg(smb_fname
),
7798 info_level
, total_data
));
7800 switch (info_level
) {
7802 case SMB_INFO_STANDARD
:
7804 status
= smb_set_info_standard(conn
,
7812 case SMB_INFO_SET_EA
:
7814 status
= smb_info_set_ea(conn
,
7822 case SMB_SET_FILE_BASIC_INFO
:
7823 case SMB_FILE_BASIC_INFORMATION
:
7825 status
= smb_set_file_basic_info(conn
,
7833 case SMB_FILE_ALLOCATION_INFORMATION
:
7834 case SMB_SET_FILE_ALLOCATION_INFO
:
7836 status
= smb_set_file_allocation_info(conn
, req
,
7844 case SMB_FILE_END_OF_FILE_INFORMATION
:
7845 case SMB_SET_FILE_END_OF_FILE_INFO
:
7848 * XP/Win7 both fail after the createfile with
7849 * SMB_SET_FILE_END_OF_FILE_INFO but not
7850 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
7851 * The level is known here, so pass it down
7855 (info_level
== SMB_SET_FILE_END_OF_FILE_INFO
);
7857 status
= smb_set_file_end_of_file_info(conn
, req
,
7866 case SMB_FILE_DISPOSITION_INFORMATION
:
7867 case SMB_SET_FILE_DISPOSITION_INFO
: /* Set delete on close for open file. */
7870 /* JRA - We used to just ignore this on a path ?
7871 * Shouldn't this be invalid level on a pathname
7874 if (tran_call
!= TRANSACT2_SETFILEINFO
) {
7875 return ERROR_NT(NT_STATUS_INVALID_LEVEL
);
7878 status
= smb_set_file_disposition_info(conn
,
7886 case SMB_FILE_POSITION_INFORMATION
:
7888 status
= smb_file_position_information(conn
,
7895 case SMB_FILE_FULL_EA_INFORMATION
:
7897 status
= smb_set_file_full_ea_info(conn
,
7904 /* From tridge Samba4 :
7905 * MODE_INFORMATION in setfileinfo (I have no
7906 * idea what "mode information" on a file is - it takes a value of 0,
7907 * 2, 4 or 6. What could it be?).
7910 case SMB_FILE_MODE_INFORMATION
:
7912 status
= smb_file_mode_information(conn
,
7919 * CIFS UNIX extensions.
7922 case SMB_SET_FILE_UNIX_BASIC
:
7924 status
= smb_set_file_unix_basic(conn
, req
,
7932 case SMB_SET_FILE_UNIX_INFO2
:
7934 status
= smb_set_file_unix_info2(conn
, req
,
7942 case SMB_SET_FILE_UNIX_LINK
:
7945 /* We must have a pathname for this. */
7946 return NT_STATUS_INVALID_LEVEL
;
7948 status
= smb_set_file_unix_link(conn
, req
, pdata
,
7949 total_data
, smb_fname
);
7953 case SMB_SET_FILE_UNIX_HLINK
:
7956 /* We must have a pathname for this. */
7957 return NT_STATUS_INVALID_LEVEL
;
7959 status
= smb_set_file_unix_hlink(conn
, req
,
7965 case SMB_FILE_RENAME_INFORMATION
:
7967 status
= smb_file_rename_information(conn
, req
,
7973 case SMB2_FILE_RENAME_INFORMATION_INTERNAL
:
7975 /* SMB2 rename information. */
7976 status
= smb2_file_rename_information(conn
, req
,
7982 case SMB_FILE_LINK_INFORMATION
:
7984 status
= smb_file_link_information(conn
, req
,
7990 #if defined(HAVE_POSIX_ACLS)
7991 case SMB_SET_POSIX_ACL
:
7993 status
= smb_set_posix_acl(conn
,
8002 case SMB_SET_POSIX_LOCK
:
8005 return NT_STATUS_INVALID_LEVEL
;
8007 status
= smb_set_posix_lock(conn
, req
,
8008 pdata
, total_data
, fsp
);
8012 case SMB_POSIX_PATH_OPEN
:
8015 /* We must have a pathname for this. */
8016 return NT_STATUS_INVALID_LEVEL
;
8019 status
= smb_posix_open(conn
, req
,
8027 case SMB_POSIX_PATH_UNLINK
:
8030 /* We must have a pathname for this. */
8031 return NT_STATUS_INVALID_LEVEL
;
8034 status
= smb_posix_unlink(conn
, req
,
8042 return NT_STATUS_INVALID_LEVEL
;
8045 if (!NT_STATUS_IS_OK(status
)) {
8049 *ret_data_size
= data_return_size
;
8050 return NT_STATUS_OK
;
8053 /****************************************************************************
8054 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
8055 ****************************************************************************/
8057 static void call_trans2setfilepathinfo(connection_struct
*conn
,
8058 struct smb_request
*req
,
8059 unsigned int tran_call
,
8060 char **pparams
, int total_params
,
8061 char **ppdata
, int total_data
,
8062 unsigned int max_data_bytes
)
8064 char *params
= *pparams
;
8065 char *pdata
= *ppdata
;
8067 struct smb_filename
*smb_fname
= NULL
;
8068 files_struct
*fsp
= NULL
;
8069 NTSTATUS status
= NT_STATUS_OK
;
8070 int data_return_size
= 0;
8073 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8077 if (tran_call
== TRANSACT2_SETFILEINFO
) {
8078 if (total_params
< 4) {
8079 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8083 fsp
= file_fsp(req
, SVAL(params
,0));
8084 /* Basic check for non-null fsp. */
8085 if (!check_fsp_open(conn
, req
, fsp
)) {
8088 info_level
= SVAL(params
,2);
8090 smb_fname
= cp_smb_filename(talloc_tos(), fsp
->fsp_name
);
8091 if (smb_fname
== NULL
) {
8092 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8096 if(fsp
->fh
->fd
== -1) {
8098 * This is actually a SETFILEINFO on a directory
8099 * handle (returned from an NT SMB). NT5.0 seems
8100 * to do this call. JRA.
8102 if (INFO_LEVEL_IS_UNIX(info_level
)) {
8103 /* Always do lstat for UNIX calls. */
8104 if (SMB_VFS_LSTAT(conn
, smb_fname
)) {
8105 DEBUG(3,("call_trans2setfilepathinfo: "
8106 "SMB_VFS_LSTAT of %s failed "
8108 smb_fname_str_dbg(smb_fname
),
8110 reply_nterror(req
, map_nt_error_from_unix(errno
));
8114 if (SMB_VFS_STAT(conn
, smb_fname
) != 0) {
8115 DEBUG(3,("call_trans2setfilepathinfo: "
8116 "fileinfo of %s failed (%s)\n",
8117 smb_fname_str_dbg(smb_fname
),
8119 reply_nterror(req
, map_nt_error_from_unix(errno
));
8123 } else if (fsp
->print_file
) {
8125 * Doing a DELETE_ON_CLOSE should cancel a print job.
8127 if ((info_level
== SMB_SET_FILE_DISPOSITION_INFO
) && CVAL(pdata
,0)) {
8128 fsp
->fh
->private_options
|= NTCREATEX_OPTIONS_PRIVATE_DELETE_ON_CLOSE
;
8130 DEBUG(3,("call_trans2setfilepathinfo: "
8131 "Cancelling print job (%s)\n",
8135 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 2,
8141 NT_STATUS_OBJECT_PATH_NOT_FOUND
);
8146 * Original code - this is an open file.
8148 if (SMB_VFS_FSTAT(fsp
, &smb_fname
->st
) != 0) {
8149 DEBUG(3,("call_trans2setfilepathinfo: fstat "
8150 "of %s failed (%s)\n", fsp_fnum_dbg(fsp
),
8152 reply_nterror(req
, map_nt_error_from_unix(errno
));
8158 uint32_t ucf_flags
= 0;
8161 if (total_params
< 7) {
8162 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8166 info_level
= SVAL(params
,0);
8167 srvstr_get_path(req
, params
, req
->flags2
, &fname
, ¶ms
[6],
8168 total_params
- 6, STR_TERMINATE
,
8170 if (!NT_STATUS_IS_OK(status
)) {
8171 reply_nterror(req
, status
);
8175 if (info_level
== SMB_SET_FILE_UNIX_BASIC
||
8176 info_level
== SMB_SET_FILE_UNIX_INFO2
||
8177 info_level
== SMB_FILE_RENAME_INFORMATION
||
8178 info_level
== SMB_POSIX_PATH_UNLINK
) {
8179 ucf_flags
|= UCF_UNIX_NAME_LOOKUP
;
8182 status
= filename_convert(req
, conn
,
8183 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
8188 if (!NT_STATUS_IS_OK(status
)) {
8189 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
8190 reply_botherror(req
,
8191 NT_STATUS_PATH_NOT_COVERED
,
8192 ERRSRV
, ERRbadpath
);
8195 reply_nterror(req
, status
);
8199 if (INFO_LEVEL_IS_UNIX(info_level
)) {
8201 * For CIFS UNIX extensions the target name may not exist.
8204 /* Always do lstat for UNIX calls. */
8205 SMB_VFS_LSTAT(conn
, smb_fname
);
8207 } else if (!VALID_STAT(smb_fname
->st
) &&
8208 SMB_VFS_STAT(conn
, smb_fname
)) {
8209 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
8211 smb_fname_str_dbg(smb_fname
),
8213 reply_nterror(req
, map_nt_error_from_unix(errno
));
8218 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (%s) info_level=%d "
8219 "totdata=%d\n", tran_call
, smb_fname_str_dbg(smb_fname
),
8221 info_level
,total_data
));
8223 /* Realloc the parameter size */
8224 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
8225 if (*pparams
== NULL
) {
8226 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8233 status
= smbd_do_setfilepathinfo(conn
, req
, req
,
8239 if (!NT_STATUS_IS_OK(status
)) {
8240 if (open_was_deferred(req
->sconn
, req
->mid
)) {
8241 /* We have re-scheduled this call. */
8244 if (blocking_lock_was_deferred_smb1(req
->sconn
, req
->mid
)) {
8245 /* We have re-scheduled this call. */
8248 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
8249 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
8250 ERRSRV
, ERRbadpath
);
8253 if (info_level
== SMB_POSIX_PATH_OPEN
) {
8254 reply_openerror(req
, status
);
8259 * Invalid EA name needs to return 2 param bytes,
8260 * not a zero-length error packet.
8262 if (NT_STATUS_EQUAL(status
, STATUS_INVALID_EA_NAME
)) {
8263 send_trans2_replies(conn
, req
, status
, params
, 2, NULL
, 0,
8266 reply_nterror(req
, status
);
8271 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 2, *ppdata
, data_return_size
,
8277 /****************************************************************************
8278 Reply to a TRANS2_MKDIR (make directory with extended attributes).
8279 ****************************************************************************/
8281 static void call_trans2mkdir(connection_struct
*conn
, struct smb_request
*req
,
8282 char **pparams
, int total_params
,
8283 char **ppdata
, int total_data
,
8284 unsigned int max_data_bytes
)
8286 struct smb_filename
*smb_dname
= NULL
;
8287 char *params
= *pparams
;
8288 char *pdata
= *ppdata
;
8289 char *directory
= NULL
;
8290 NTSTATUS status
= NT_STATUS_OK
;
8291 struct ea_list
*ea_list
= NULL
;
8292 TALLOC_CTX
*ctx
= talloc_tos();
8294 if (!CAN_WRITE(conn
)) {
8295 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
8299 if (total_params
< 5) {
8300 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8304 srvstr_get_path(ctx
, params
, req
->flags2
, &directory
, ¶ms
[4],
8305 total_params
- 4, STR_TERMINATE
,
8307 if (!NT_STATUS_IS_OK(status
)) {
8308 reply_nterror(req
, status
);
8312 DEBUG(3,("call_trans2mkdir : name = %s\n", directory
));
8314 status
= filename_convert(ctx
,
8316 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
8322 if (!NT_STATUS_IS_OK(status
)) {
8323 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
8324 reply_botherror(req
,
8325 NT_STATUS_PATH_NOT_COVERED
,
8326 ERRSRV
, ERRbadpath
);
8329 reply_nterror(req
, status
);
8334 * OS/2 workplace shell seems to send SET_EA requests of "null"
8335 * length (4 bytes containing IVAL 4).
8336 * They seem to have no effect. Bug #3212. JRA.
8339 if (total_data
&& (total_data
!= 4)) {
8340 /* Any data in this call is an EA list. */
8341 if (total_data
< 10) {
8342 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8346 if (IVAL(pdata
,0) > total_data
) {
8347 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
8348 IVAL(pdata
,0), (unsigned int)total_data
));
8349 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8353 ea_list
= read_ea_list(talloc_tos(), pdata
+ 4,
8356 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8360 if (!lp_ea_support(SNUM(conn
))) {
8361 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
8365 /* If total_data == 4 Windows doesn't care what values
8366 * are placed in that field, it just ignores them.
8367 * The System i QNTC IBM SMB client puts bad values here,
8368 * so ignore them. */
8370 status
= create_directory(conn
, req
, smb_dname
);
8372 if (!NT_STATUS_IS_OK(status
)) {
8373 reply_nterror(req
, status
);
8377 /* Try and set any given EA. */
8379 status
= set_ea(conn
, NULL
, smb_dname
, ea_list
);
8380 if (!NT_STATUS_IS_OK(status
)) {
8381 reply_nterror(req
, status
);
8386 /* Realloc the parameter and data sizes */
8387 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
8388 if(*pparams
== NULL
) {
8389 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8396 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 2, *ppdata
, 0, max_data_bytes
);
8399 TALLOC_FREE(smb_dname
);
8403 /****************************************************************************
8404 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
8405 We don't actually do this - we just send a null response.
8406 ****************************************************************************/
8408 static void call_trans2findnotifyfirst(connection_struct
*conn
,
8409 struct smb_request
*req
,
8410 char **pparams
, int total_params
,
8411 char **ppdata
, int total_data
,
8412 unsigned int max_data_bytes
)
8414 char *params
= *pparams
;
8417 if (total_params
< 6) {
8418 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8422 info_level
= SVAL(params
,4);
8423 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level
));
8425 switch (info_level
) {
8430 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
8434 /* Realloc the parameter and data sizes */
8435 *pparams
= (char *)SMB_REALLOC(*pparams
,6);
8436 if (*pparams
== NULL
) {
8437 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8442 SSVAL(params
,0,fnf_handle
);
8443 SSVAL(params
,2,0); /* No changes */
8444 SSVAL(params
,4,0); /* No EA errors */
8451 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 6, *ppdata
, 0, max_data_bytes
);
8456 /****************************************************************************
8457 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
8458 changes). Currently this does nothing.
8459 ****************************************************************************/
8461 static void call_trans2findnotifynext(connection_struct
*conn
,
8462 struct smb_request
*req
,
8463 char **pparams
, int total_params
,
8464 char **ppdata
, int total_data
,
8465 unsigned int max_data_bytes
)
8467 char *params
= *pparams
;
8469 DEBUG(3,("call_trans2findnotifynext\n"));
8471 /* Realloc the parameter and data sizes */
8472 *pparams
= (char *)SMB_REALLOC(*pparams
,4);
8473 if (*pparams
== NULL
) {
8474 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8479 SSVAL(params
,0,0); /* No changes */
8480 SSVAL(params
,2,0); /* No EA errors */
8482 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 4, *ppdata
, 0, max_data_bytes
);
8487 /****************************************************************************
8488 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
8489 ****************************************************************************/
8491 static void call_trans2getdfsreferral(connection_struct
*conn
,
8492 struct smb_request
*req
,
8493 char **pparams
, int total_params
,
8494 char **ppdata
, int total_data
,
8495 unsigned int max_data_bytes
)
8497 char *params
= *pparams
;
8498 char *pathname
= NULL
;
8500 int max_referral_level
;
8501 NTSTATUS status
= NT_STATUS_OK
;
8502 TALLOC_CTX
*ctx
= talloc_tos();
8504 DEBUG(10,("call_trans2getdfsreferral\n"));
8506 if (total_params
< 3) {
8507 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8511 max_referral_level
= SVAL(params
,0);
8513 if(!lp_host_msdfs()) {
8514 reply_nterror(req
, NT_STATUS_NOT_IMPLEMENTED
);
8518 srvstr_pull_talloc(ctx
, params
, req
->flags2
, &pathname
, ¶ms
[2],
8519 total_params
- 2, STR_TERMINATE
);
8521 reply_nterror(req
, NT_STATUS_NOT_FOUND
);
8524 if((reply_size
= setup_dfs_referral(conn
, pathname
, max_referral_level
,
8525 ppdata
,&status
)) < 0) {
8526 reply_nterror(req
, status
);
8530 SSVAL((discard_const_p(uint8_t, req
->inbuf
)), smb_flg2
,
8531 SVAL(req
->inbuf
,smb_flg2
) | FLAGS2_DFS_PATHNAMES
);
8532 send_trans2_replies(conn
, req
, NT_STATUS_OK
, 0,0,*ppdata
,reply_size
, max_data_bytes
);
8537 #define LMCAT_SPL 0x53
8538 #define LMFUNC_GETJOBID 0x60
8540 /****************************************************************************
8541 Reply to a TRANS2_IOCTL - used for OS/2 printing.
8542 ****************************************************************************/
8544 static void call_trans2ioctl(connection_struct
*conn
,
8545 struct smb_request
*req
,
8546 char **pparams
, int total_params
,
8547 char **ppdata
, int total_data
,
8548 unsigned int max_data_bytes
)
8550 char *pdata
= *ppdata
;
8551 files_struct
*fsp
= file_fsp(req
, SVAL(req
->vwv
+15, 0));
8553 /* check for an invalid fid before proceeding */
8556 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
8560 if ((SVAL(req
->vwv
+16, 0) == LMCAT_SPL
)
8561 && (SVAL(req
->vwv
+17, 0) == LMFUNC_GETJOBID
)) {
8562 *ppdata
= (char *)SMB_REALLOC(*ppdata
, 32);
8563 if (*ppdata
== NULL
) {
8564 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8569 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
8570 CAN ACCEPT THIS IN UNICODE. JRA. */
8573 SSVAL(pdata
, 0, print_spool_rap_jobid(fsp
->print_file
));
8575 srvstr_push(pdata
, req
->flags2
, pdata
+ 2,
8576 lp_netbios_name(), 15,
8577 STR_ASCII
|STR_TERMINATE
); /* Our NetBIOS name */
8578 srvstr_push(pdata
, req
->flags2
, pdata
+18,
8579 lp_servicename(talloc_tos(), SNUM(conn
)), 13,
8580 STR_ASCII
|STR_TERMINATE
); /* Service name */
8581 send_trans2_replies(conn
, req
, NT_STATUS_OK
, *pparams
, 0, *ppdata
, 32,
8586 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
8587 reply_nterror(req
, NT_STATUS_NOT_IMPLEMENTED
);
8590 /****************************************************************************
8591 Reply to a SMBfindclose (stop trans2 directory search).
8592 ****************************************************************************/
8594 void reply_findclose(struct smb_request
*req
)
8597 struct smbd_server_connection
*sconn
= req
->sconn
;
8599 START_PROFILE(SMBfindclose
);
8602 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8603 END_PROFILE(SMBfindclose
);
8607 dptr_num
= SVALS(req
->vwv
+0, 0);
8609 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num
));
8611 dptr_close(sconn
, &dptr_num
);
8613 reply_outbuf(req
, 0, 0);
8615 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num
));
8617 END_PROFILE(SMBfindclose
);
8621 /****************************************************************************
8622 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
8623 ****************************************************************************/
8625 void reply_findnclose(struct smb_request
*req
)
8629 START_PROFILE(SMBfindnclose
);
8632 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8633 END_PROFILE(SMBfindnclose
);
8637 dptr_num
= SVAL(req
->vwv
+0, 0);
8639 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num
));
8641 /* We never give out valid handles for a
8642 findnotifyfirst - so any dptr_num is ok here.
8645 reply_outbuf(req
, 0, 0);
8647 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num
));
8649 END_PROFILE(SMBfindnclose
);
8653 static void handle_trans2(connection_struct
*conn
, struct smb_request
*req
,
8654 struct trans_state
*state
)
8656 if (get_Protocol() >= PROTOCOL_NT1
) {
8657 req
->flags2
|= 0x40; /* IS_LONG_NAME */
8658 SSVAL((discard_const_p(uint8_t, req
->inbuf
)),smb_flg2
,req
->flags2
);
8661 if (ENCRYPTION_REQUIRED(conn
) && !req
->encrypted
) {
8662 if (state
->call
!= TRANSACT2_QFSINFO
&&
8663 state
->call
!= TRANSACT2_SETFSINFO
) {
8664 DEBUG(0,("handle_trans2: encryption required "
8666 (unsigned int)state
->call
));
8667 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
8672 SMB_PERFCOUNT_SET_SUBOP(&req
->pcd
, state
->call
);
8674 /* Now we must call the relevant TRANS2 function */
8675 switch(state
->call
) {
8676 case TRANSACT2_OPEN
:
8678 START_PROFILE(Trans2_open
);
8679 call_trans2open(conn
, req
,
8680 &state
->param
, state
->total_param
,
8681 &state
->data
, state
->total_data
,
8682 state
->max_data_return
);
8683 END_PROFILE(Trans2_open
);
8687 case TRANSACT2_FINDFIRST
:
8689 START_PROFILE(Trans2_findfirst
);
8690 call_trans2findfirst(conn
, req
,
8691 &state
->param
, state
->total_param
,
8692 &state
->data
, state
->total_data
,
8693 state
->max_data_return
);
8694 END_PROFILE(Trans2_findfirst
);
8698 case TRANSACT2_FINDNEXT
:
8700 START_PROFILE(Trans2_findnext
);
8701 call_trans2findnext(conn
, req
,
8702 &state
->param
, state
->total_param
,
8703 &state
->data
, state
->total_data
,
8704 state
->max_data_return
);
8705 END_PROFILE(Trans2_findnext
);
8709 case TRANSACT2_QFSINFO
:
8711 START_PROFILE(Trans2_qfsinfo
);
8712 call_trans2qfsinfo(conn
, req
,
8713 &state
->param
, state
->total_param
,
8714 &state
->data
, state
->total_data
,
8715 state
->max_data_return
);
8716 END_PROFILE(Trans2_qfsinfo
);
8720 case TRANSACT2_SETFSINFO
:
8722 START_PROFILE(Trans2_setfsinfo
);
8723 call_trans2setfsinfo(conn
, req
,
8724 &state
->param
, state
->total_param
,
8725 &state
->data
, state
->total_data
,
8726 state
->max_data_return
);
8727 END_PROFILE(Trans2_setfsinfo
);
8731 case TRANSACT2_QPATHINFO
:
8732 case TRANSACT2_QFILEINFO
:
8734 START_PROFILE(Trans2_qpathinfo
);
8735 call_trans2qfilepathinfo(conn
, req
, state
->call
,
8736 &state
->param
, state
->total_param
,
8737 &state
->data
, state
->total_data
,
8738 state
->max_data_return
);
8739 END_PROFILE(Trans2_qpathinfo
);
8743 case TRANSACT2_SETPATHINFO
:
8744 case TRANSACT2_SETFILEINFO
:
8746 START_PROFILE(Trans2_setpathinfo
);
8747 call_trans2setfilepathinfo(conn
, req
, state
->call
,
8748 &state
->param
, state
->total_param
,
8749 &state
->data
, state
->total_data
,
8750 state
->max_data_return
);
8751 END_PROFILE(Trans2_setpathinfo
);
8755 case TRANSACT2_FINDNOTIFYFIRST
:
8757 START_PROFILE(Trans2_findnotifyfirst
);
8758 call_trans2findnotifyfirst(conn
, req
,
8759 &state
->param
, state
->total_param
,
8760 &state
->data
, state
->total_data
,
8761 state
->max_data_return
);
8762 END_PROFILE(Trans2_findnotifyfirst
);
8766 case TRANSACT2_FINDNOTIFYNEXT
:
8768 START_PROFILE(Trans2_findnotifynext
);
8769 call_trans2findnotifynext(conn
, req
,
8770 &state
->param
, state
->total_param
,
8771 &state
->data
, state
->total_data
,
8772 state
->max_data_return
);
8773 END_PROFILE(Trans2_findnotifynext
);
8777 case TRANSACT2_MKDIR
:
8779 START_PROFILE(Trans2_mkdir
);
8780 call_trans2mkdir(conn
, req
,
8781 &state
->param
, state
->total_param
,
8782 &state
->data
, state
->total_data
,
8783 state
->max_data_return
);
8784 END_PROFILE(Trans2_mkdir
);
8788 case TRANSACT2_GET_DFS_REFERRAL
:
8790 START_PROFILE(Trans2_get_dfs_referral
);
8791 call_trans2getdfsreferral(conn
, req
,
8792 &state
->param
, state
->total_param
,
8793 &state
->data
, state
->total_data
,
8794 state
->max_data_return
);
8795 END_PROFILE(Trans2_get_dfs_referral
);
8799 case TRANSACT2_IOCTL
:
8801 START_PROFILE(Trans2_ioctl
);
8802 call_trans2ioctl(conn
, req
,
8803 &state
->param
, state
->total_param
,
8804 &state
->data
, state
->total_data
,
8805 state
->max_data_return
);
8806 END_PROFILE(Trans2_ioctl
);
8811 /* Error in request */
8812 DEBUG(2,("Unknown request %d in trans2 call\n", state
->call
));
8813 reply_nterror(req
, NT_STATUS_NOT_IMPLEMENTED
);
8817 /****************************************************************************
8818 Reply to a SMBtrans2.
8819 ****************************************************************************/
8821 void reply_trans2(struct smb_request
*req
)
8823 connection_struct
*conn
= req
->conn
;
8828 unsigned int tran_call
;
8829 struct trans_state
*state
;
8832 START_PROFILE(SMBtrans2
);
8834 if (req
->wct
< 14) {
8835 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8836 END_PROFILE(SMBtrans2
);
8840 dsoff
= SVAL(req
->vwv
+12, 0);
8841 dscnt
= SVAL(req
->vwv
+11, 0);
8842 psoff
= SVAL(req
->vwv
+10, 0);
8843 pscnt
= SVAL(req
->vwv
+9, 0);
8844 tran_call
= SVAL(req
->vwv
+14, 0);
8846 result
= allow_new_trans(conn
->pending_trans
, req
->mid
);
8847 if (!NT_STATUS_IS_OK(result
)) {
8848 DEBUG(2, ("Got invalid trans2 request: %s\n",
8849 nt_errstr(result
)));
8850 reply_nterror(req
, result
);
8851 END_PROFILE(SMBtrans2
);
8856 switch (tran_call
) {
8857 /* List the allowed trans2 calls on IPC$ */
8858 case TRANSACT2_OPEN
:
8859 case TRANSACT2_GET_DFS_REFERRAL
:
8860 case TRANSACT2_QFILEINFO
:
8861 case TRANSACT2_QFSINFO
:
8862 case TRANSACT2_SETFSINFO
:
8865 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
8866 END_PROFILE(SMBtrans2
);
8871 if ((state
= talloc(conn
, struct trans_state
)) == NULL
) {
8872 DEBUG(0, ("talloc failed\n"));
8873 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8874 END_PROFILE(SMBtrans2
);
8878 state
->cmd
= SMBtrans2
;
8880 state
->mid
= req
->mid
;
8881 state
->vuid
= req
->vuid
;
8882 state
->setup_count
= SVAL(req
->vwv
+13, 0);
8883 state
->setup
= NULL
;
8884 state
->total_param
= SVAL(req
->vwv
+0, 0);
8885 state
->param
= NULL
;
8886 state
->total_data
= SVAL(req
->vwv
+1, 0);
8888 state
->max_param_return
= SVAL(req
->vwv
+2, 0);
8889 state
->max_data_return
= SVAL(req
->vwv
+3, 0);
8890 state
->max_setup_return
= SVAL(req
->vwv
+4, 0);
8891 state
->close_on_completion
= BITSETW(req
->vwv
+5, 0);
8892 state
->one_way
= BITSETW(req
->vwv
+5, 1);
8894 state
->call
= tran_call
;
8896 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
8897 is so as a sanity check */
8898 if (state
->setup_count
!= 1) {
8900 * Need to have rc=0 for ioctl to get job id for OS/2.
8901 * Network printing will fail if function is not successful.
8902 * Similar function in reply.c will be used if protocol
8903 * is LANMAN1.0 instead of LM1.2X002.
8904 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
8905 * outbuf doesn't have to be set(only job id is used).
8907 if ( (state
->setup_count
== 4)
8908 && (tran_call
== TRANSACT2_IOCTL
)
8909 && (SVAL(req
->vwv
+16, 0) == LMCAT_SPL
)
8910 && (SVAL(req
->vwv
+17, 0) == LMFUNC_GETJOBID
)) {
8911 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
8913 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state
->setup_count
));
8914 DEBUG(2,("Transaction is %d\n",tran_call
));
8916 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8917 END_PROFILE(SMBtrans2
);
8922 if ((dscnt
> state
->total_data
) || (pscnt
> state
->total_param
))
8925 if (state
->total_data
) {
8927 if (trans_oob(state
->total_data
, 0, dscnt
)
8928 || trans_oob(smb_len(req
->inbuf
), dsoff
, dscnt
)) {
8932 /* Can't use talloc here, the core routines do realloc on the
8933 * params and data. */
8934 state
->data
= (char *)SMB_MALLOC(state
->total_data
);
8935 if (state
->data
== NULL
) {
8936 DEBUG(0,("reply_trans2: data malloc fail for %u "
8937 "bytes !\n", (unsigned int)state
->total_data
));
8939 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8940 END_PROFILE(SMBtrans2
);
8944 memcpy(state
->data
,smb_base(req
->inbuf
)+dsoff
,dscnt
);
8947 if (state
->total_param
) {
8949 if (trans_oob(state
->total_param
, 0, pscnt
)
8950 || trans_oob(smb_len(req
->inbuf
), psoff
, pscnt
)) {
8954 /* Can't use talloc here, the core routines do realloc on the
8955 * params and data. */
8956 state
->param
= (char *)SMB_MALLOC(state
->total_param
);
8957 if (state
->param
== NULL
) {
8958 DEBUG(0,("reply_trans: param malloc fail for %u "
8959 "bytes !\n", (unsigned int)state
->total_param
));
8960 SAFE_FREE(state
->data
);
8962 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8963 END_PROFILE(SMBtrans2
);
8967 memcpy(state
->param
,smb_base(req
->inbuf
)+psoff
,pscnt
);
8970 state
->received_data
= dscnt
;
8971 state
->received_param
= pscnt
;
8973 if ((state
->received_param
== state
->total_param
) &&
8974 (state
->received_data
== state
->total_data
)) {
8976 handle_trans2(conn
, req
, state
);
8978 SAFE_FREE(state
->data
);
8979 SAFE_FREE(state
->param
);
8981 END_PROFILE(SMBtrans2
);
8985 DLIST_ADD(conn
->pending_trans
, state
);
8987 /* We need to send an interim response then receive the rest
8988 of the parameter/data bytes */
8989 reply_outbuf(req
, 0, 0);
8990 show_msg((char *)req
->outbuf
);
8991 END_PROFILE(SMBtrans2
);
8996 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
8997 SAFE_FREE(state
->data
);
8998 SAFE_FREE(state
->param
);
9000 END_PROFILE(SMBtrans2
);
9001 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
9005 /****************************************************************************
9006 Reply to a SMBtranss2
9007 ****************************************************************************/
9009 void reply_transs2(struct smb_request
*req
)
9011 connection_struct
*conn
= req
->conn
;
9012 unsigned int pcnt
,poff
,dcnt
,doff
,pdisp
,ddisp
;
9013 struct trans_state
*state
;
9015 START_PROFILE(SMBtranss2
);
9017 show_msg((const char *)req
->inbuf
);
9019 /* Windows clients expect all replies to
9020 a transact secondary (SMBtranss2 0x33)
9021 to have a command code of transact
9022 (SMBtrans2 0x32). See bug #8989
9023 and also [MS-CIFS] section 2.2.4.47.2
9026 req
->cmd
= SMBtrans2
;
9029 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
9030 END_PROFILE(SMBtranss2
);
9034 for (state
= conn
->pending_trans
; state
!= NULL
;
9035 state
= state
->next
) {
9036 if (state
->mid
== req
->mid
) {
9041 if ((state
== NULL
) || (state
->cmd
!= SMBtrans2
)) {
9042 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
9043 END_PROFILE(SMBtranss2
);
9047 /* Revise state->total_param and state->total_data in case they have
9048 changed downwards */
9050 if (SVAL(req
->vwv
+0, 0) < state
->total_param
)
9051 state
->total_param
= SVAL(req
->vwv
+0, 0);
9052 if (SVAL(req
->vwv
+1, 0) < state
->total_data
)
9053 state
->total_data
= SVAL(req
->vwv
+1, 0);
9055 pcnt
= SVAL(req
->vwv
+2, 0);
9056 poff
= SVAL(req
->vwv
+3, 0);
9057 pdisp
= SVAL(req
->vwv
+4, 0);
9059 dcnt
= SVAL(req
->vwv
+5, 0);
9060 doff
= SVAL(req
->vwv
+6, 0);
9061 ddisp
= SVAL(req
->vwv
+7, 0);
9063 state
->received_param
+= pcnt
;
9064 state
->received_data
+= dcnt
;
9066 if ((state
->received_data
> state
->total_data
) ||
9067 (state
->received_param
> state
->total_param
))
9071 if (trans_oob(state
->total_param
, pdisp
, pcnt
)
9072 || trans_oob(smb_len(req
->inbuf
), poff
, pcnt
)) {
9075 memcpy(state
->param
+pdisp
,smb_base(req
->inbuf
)+poff
,pcnt
);
9079 if (trans_oob(state
->total_data
, ddisp
, dcnt
)
9080 || trans_oob(smb_len(req
->inbuf
), doff
, dcnt
)) {
9083 memcpy(state
->data
+ddisp
, smb_base(req
->inbuf
)+doff
,dcnt
);
9086 if ((state
->received_param
< state
->total_param
) ||
9087 (state
->received_data
< state
->total_data
)) {
9088 END_PROFILE(SMBtranss2
);
9092 handle_trans2(conn
, req
, state
);
9094 DLIST_REMOVE(conn
->pending_trans
, state
);
9095 SAFE_FREE(state
->data
);
9096 SAFE_FREE(state
->param
);
9099 END_PROFILE(SMBtranss2
);
9104 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
9105 DLIST_REMOVE(conn
->pending_trans
, state
);
9106 SAFE_FREE(state
->data
);
9107 SAFE_FREE(state
->param
);
9109 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
9110 END_PROFILE(SMBtranss2
);