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 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, ("%s: ea_namelist size = %u\n",
262 __func__
, (unsigned int)sizeret
));
274 * Ensure the result is 0-terminated
277 if (ea_namelist
[sizeret
-1] != '\0') {
279 return NT_STATUS_INTERNAL_ERROR
;
287 for (p
= ea_namelist
; p
- ea_namelist
< sizeret
; p
+= strlen(p
)+1) {
291 tmp
= talloc_realloc(mem_ctx
, names
, char *, num_names
);
293 DEBUG(0, ("talloc failed\n"));
295 return NT_STATUS_NO_MEMORY
;
301 for (p
= ea_namelist
; p
- ea_namelist
< sizeret
; p
+= strlen(p
)+1) {
302 names
[num_names
++] = p
;
310 *pnum_names
= num_names
;
314 /****************************************************************************
315 Return a linked list of the total EA's. Plus the total size
316 ****************************************************************************/
318 static NTSTATUS
get_ea_list_from_file_path(TALLOC_CTX
*mem_ctx
, connection_struct
*conn
, files_struct
*fsp
,
319 const char *fname
, size_t *pea_total_len
, struct ea_list
**ea_list
)
321 /* Get a list of all xattrs. Max namesize is 64k. */
324 struct ea_list
*ea_list_head
= NULL
;
330 status
= get_ea_names_from_file(talloc_tos(), conn
, fsp
, fname
,
333 if (!NT_STATUS_IS_OK(status
)) {
337 if (num_names
== 0) {
342 for (i
=0; i
<num_names
; i
++) {
343 struct ea_list
*listp
;
346 if (strnequal(names
[i
], "system.", 7)
347 || samba_private_attr_name(names
[i
]))
351 * Filter out any underlying POSIX EA names
352 * that a Windows client can't handle.
354 if (!lp_posix_pathnames() &&
355 is_invalid_windows_ea_name(names
[i
])) {
359 listp
= talloc(mem_ctx
, struct ea_list
);
361 return NT_STATUS_NO_MEMORY
;
364 status
= get_ea_value(listp
, conn
, fsp
,
368 if (!NT_STATUS_IS_OK(status
)) {
373 if (listp
->ea
.value
.length
== 0) {
375 * We can never return a zero length EA.
376 * Windows reports the EA's as corrupted.
382 push_ascii_fstring(dos_ea_name
, listp
->ea
.name
);
385 4 + strlen(dos_ea_name
) + 1 + listp
->ea
.value
.length
;
387 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
388 "= %u\n", (unsigned int)*pea_total_len
, dos_ea_name
,
389 (unsigned int)listp
->ea
.value
.length
));
391 DLIST_ADD_END(ea_list_head
, listp
, struct ea_list
*);
395 /* Add on 4 for total length. */
396 if (*pea_total_len
) {
400 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
401 (unsigned int)*pea_total_len
));
403 *ea_list
= ea_list_head
;
407 static NTSTATUS
get_ea_list_from_file(TALLOC_CTX
*mem_ctx
, connection_struct
*conn
, files_struct
*fsp
,
408 const struct smb_filename
*smb_fname
, size_t *pea_total_len
, struct ea_list
**ea_list
)
413 if (!lp_ea_support(SNUM(conn
))) {
417 if (is_ntfs_stream_smb_fname(smb_fname
)) {
418 return NT_STATUS_INVALID_PARAMETER
;
421 return get_ea_list_from_file_path(mem_ctx
, conn
, fsp
, smb_fname
->base_name
, pea_total_len
, ea_list
);
424 /****************************************************************************
425 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
427 ****************************************************************************/
429 static unsigned int fill_ea_buffer(TALLOC_CTX
*mem_ctx
, char *pdata
, unsigned int total_data_size
,
430 connection_struct
*conn
, struct ea_list
*ea_list
)
432 unsigned int ret_data_size
= 4;
435 SMB_ASSERT(total_data_size
>= 4);
437 if (!lp_ea_support(SNUM(conn
))) {
442 for (p
= pdata
+ 4; ea_list
; ea_list
= ea_list
->next
) {
445 push_ascii_fstring(dos_ea_name
, ea_list
->ea
.name
);
446 dos_namelen
= strlen(dos_ea_name
);
447 if (dos_namelen
> 255 || dos_namelen
== 0) {
450 if (ea_list
->ea
.value
.length
> 65535) {
453 if (4 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
> total_data_size
) {
457 /* We know we have room. */
458 SCVAL(p
,0,ea_list
->ea
.flags
);
459 SCVAL(p
,1,dos_namelen
);
460 SSVAL(p
,2,ea_list
->ea
.value
.length
);
461 strlcpy(p
+4, dos_ea_name
, dos_namelen
+1);
462 memcpy( p
+ 4 + dos_namelen
+ 1, ea_list
->ea
.value
.data
, ea_list
->ea
.value
.length
);
464 total_data_size
-= 4 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
;
465 p
+= 4 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
;
468 ret_data_size
= PTR_DIFF(p
, pdata
);
469 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size
));
470 SIVAL(pdata
,0,ret_data_size
);
471 return ret_data_size
;
474 static NTSTATUS
fill_ea_chained_buffer(TALLOC_CTX
*mem_ctx
,
476 unsigned int total_data_size
,
477 unsigned int *ret_data_size
,
478 connection_struct
*conn
,
479 struct ea_list
*ea_list
)
481 uint8_t *p
= (uint8_t *)pdata
;
482 uint8_t *last_start
= NULL
;
483 bool do_store_data
= (pdata
!= NULL
);
487 if (!lp_ea_support(SNUM(conn
))) {
488 return NT_STATUS_NO_EAS_ON_FILE
;
491 for (; ea_list
; ea_list
= ea_list
->next
) {
497 if (last_start
!= NULL
&& do_store_data
) {
498 SIVAL(last_start
, 0, PTR_DIFF(p
, last_start
));
502 push_ascii_fstring(dos_ea_name
, ea_list
->ea
.name
);
503 dos_namelen
= strlen(dos_ea_name
);
504 if (dos_namelen
> 255 || dos_namelen
== 0) {
505 return NT_STATUS_INTERNAL_ERROR
;
507 if (ea_list
->ea
.value
.length
> 65535) {
508 return NT_STATUS_INTERNAL_ERROR
;
511 this_size
= 0x08 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
;
514 pad
= (4 - (this_size
% 4)) % 4;
519 if (this_size
> total_data_size
) {
520 return NT_STATUS_INFO_LENGTH_MISMATCH
;
523 /* We know we have room. */
524 SIVAL(p
, 0x00, 0); /* next offset */
525 SCVAL(p
, 0x04, ea_list
->ea
.flags
);
526 SCVAL(p
, 0x05, dos_namelen
);
527 SSVAL(p
, 0x06, ea_list
->ea
.value
.length
);
528 strlcpy((char *)(p
+0x08), dos_ea_name
, dos_namelen
+1);
529 memcpy(p
+ 0x08 + dos_namelen
+ 1, ea_list
->ea
.value
.data
, ea_list
->ea
.value
.length
);
531 memset(p
+ 0x08 + dos_namelen
+ 1 + ea_list
->ea
.value
.length
,
535 total_data_size
-= this_size
;
541 *ret_data_size
= PTR_DIFF(p
, pdata
);
542 DEBUG(10,("fill_ea_chained_buffer: data_size = %u\n", *ret_data_size
));
546 static unsigned int estimate_ea_size(connection_struct
*conn
, files_struct
*fsp
, const struct smb_filename
*smb_fname
)
548 size_t total_ea_len
= 0;
550 struct ea_list
*ea_list
= NULL
;
552 if (!lp_ea_support(SNUM(conn
))) {
555 mem_ctx
= talloc_stackframe();
557 /* If this is a stream fsp, then we need to instead find the
558 * estimated ea len from the main file, not the stream
559 * (streams cannot have EAs), but the estimate isn't just 0 in
561 if (is_ntfs_stream_smb_fname(smb_fname
)) {
564 (void)get_ea_list_from_file_path(mem_ctx
, conn
, fsp
, smb_fname
->base_name
, &total_ea_len
, &ea_list
);
565 if(conn
->sconn
->using_smb2
) {
567 unsigned int ret_data_size
;
569 * We're going to be using fill_ea_chained_buffer() to
570 * marshall EA's - this size is significantly larger
571 * than the SMB1 buffer. Re-calculate the size without
574 status
= fill_ea_chained_buffer(mem_ctx
,
580 if (!NT_STATUS_IS_OK(status
)) {
583 total_ea_len
= ret_data_size
;
585 TALLOC_FREE(mem_ctx
);
589 /****************************************************************************
590 Ensure the EA name is case insensitive by matching any existing EA name.
591 ****************************************************************************/
593 static void canonicalize_ea_name(connection_struct
*conn
, files_struct
*fsp
, const char *fname
, fstring unix_ea_name
)
596 TALLOC_CTX
*mem_ctx
= talloc_tos();
597 struct ea_list
*ea_list
;
598 NTSTATUS status
= get_ea_list_from_file_path(mem_ctx
, conn
, fsp
, fname
, &total_ea_len
, &ea_list
);
599 if (!NT_STATUS_IS_OK(status
)) {
603 for (; ea_list
; ea_list
= ea_list
->next
) {
604 if (strequal(&unix_ea_name
[5], ea_list
->ea
.name
)) {
605 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
606 &unix_ea_name
[5], ea_list
->ea
.name
));
607 strlcpy(&unix_ea_name
[5], ea_list
->ea
.name
, sizeof(fstring
)-5);
613 /****************************************************************************
614 Set or delete an extended attribute.
615 ****************************************************************************/
617 NTSTATUS
set_ea(connection_struct
*conn
, files_struct
*fsp
,
618 const struct smb_filename
*smb_fname
, struct ea_list
*ea_list
)
623 if (!lp_ea_support(SNUM(conn
))) {
624 return NT_STATUS_EAS_NOT_SUPPORTED
;
627 status
= check_access(conn
, fsp
, smb_fname
, FILE_WRITE_EA
);
628 if (!NT_STATUS_IS_OK(status
)) {
632 /* Setting EAs on streams isn't supported. */
633 if (is_ntfs_stream_smb_fname(smb_fname
)) {
634 return NT_STATUS_INVALID_PARAMETER
;
638 * Filter out invalid Windows EA names - before
639 * we set *any* of them.
642 if (ea_list_has_invalid_name(ea_list
)) {
643 return STATUS_INVALID_EA_NAME
;
646 fname
= smb_fname
->base_name
;
648 for (;ea_list
; ea_list
= ea_list
->next
) {
650 fstring unix_ea_name
;
652 fstrcpy(unix_ea_name
, "user."); /* All EA's must start with user. */
653 fstrcat(unix_ea_name
, ea_list
->ea
.name
);
655 canonicalize_ea_name(conn
, fsp
, fname
, unix_ea_name
);
657 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name
, (unsigned int)ea_list
->ea
.value
.length
));
659 if (samba_private_attr_name(unix_ea_name
)) {
660 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name
));
661 return NT_STATUS_ACCESS_DENIED
;
664 if (ea_list
->ea
.value
.length
== 0) {
665 /* Remove the attribute. */
666 if (fsp
&& (fsp
->fh
->fd
!= -1)) {
667 DEBUG(10,("set_ea: deleting ea name %s on "
668 "file %s by file descriptor.\n",
669 unix_ea_name
, fsp_str_dbg(fsp
)));
670 ret
= SMB_VFS_FREMOVEXATTR(fsp
, unix_ea_name
);
672 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
673 unix_ea_name
, fname
));
674 ret
= SMB_VFS_REMOVEXATTR(conn
, fname
, unix_ea_name
);
677 /* Removing a non existent attribute always succeeds. */
678 if (ret
== -1 && errno
== ENOATTR
) {
679 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
685 if (fsp
&& (fsp
->fh
->fd
!= -1)) {
686 DEBUG(10,("set_ea: setting ea name %s on file "
687 "%s by file descriptor.\n",
688 unix_ea_name
, fsp_str_dbg(fsp
)));
689 ret
= SMB_VFS_FSETXATTR(fsp
, unix_ea_name
,
690 ea_list
->ea
.value
.data
, ea_list
->ea
.value
.length
, 0);
692 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
693 unix_ea_name
, fname
));
694 ret
= SMB_VFS_SETXATTR(conn
, fname
, unix_ea_name
,
695 ea_list
->ea
.value
.data
, ea_list
->ea
.value
.length
, 0);
701 if (errno
== ENOTSUP
) {
702 return NT_STATUS_EAS_NOT_SUPPORTED
;
705 return map_nt_error_from_unix(errno
);
711 /****************************************************************************
712 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
713 ****************************************************************************/
715 static struct ea_list
*read_ea_name_list(TALLOC_CTX
*ctx
, const char *pdata
, size_t data_size
)
717 struct ea_list
*ea_list_head
= NULL
;
718 size_t converted_size
, offset
= 0;
720 while (offset
+ 2 < data_size
) {
721 struct ea_list
*eal
= talloc_zero(ctx
, struct ea_list
);
722 unsigned int namelen
= CVAL(pdata
,offset
);
724 offset
++; /* Go past the namelen byte. */
726 /* integer wrap paranioa. */
727 if ((offset
+ namelen
< offset
) || (offset
+ namelen
< namelen
) ||
728 (offset
> data_size
) || (namelen
> data_size
) ||
729 (offset
+ namelen
>= data_size
)) {
732 /* Ensure the name is null terminated. */
733 if (pdata
[offset
+ namelen
] != '\0') {
736 if (!pull_ascii_talloc(ctx
, &eal
->ea
.name
, &pdata
[offset
],
738 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
739 "failed: %s", strerror(errno
)));
745 offset
+= (namelen
+ 1); /* Go past the name + terminating zero. */
746 DLIST_ADD_END(ea_list_head
, eal
, struct ea_list
*);
747 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal
->ea
.name
));
753 /****************************************************************************
754 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
755 ****************************************************************************/
757 static struct ea_list
*read_ea_list(TALLOC_CTX
*ctx
, const char *pdata
, size_t data_size
)
759 struct ea_list
*ea_list_head
= NULL
;
761 size_t bytes_used
= 0;
763 while (offset
< data_size
) {
764 struct ea_list
*eal
= read_ea_list_entry(ctx
, pdata
+ offset
, data_size
- offset
, &bytes_used
);
770 DLIST_ADD_END(ea_list_head
, eal
, struct ea_list
*);
771 offset
+= bytes_used
;
777 /****************************************************************************
778 Count the total EA size needed.
779 ****************************************************************************/
781 static size_t ea_list_size(struct ea_list
*ealist
)
784 struct ea_list
*listp
;
787 for (listp
= ealist
; listp
; listp
= listp
->next
) {
788 push_ascii_fstring(dos_ea_name
, listp
->ea
.name
);
789 ret
+= 4 + strlen(dos_ea_name
) + 1 + listp
->ea
.value
.length
;
791 /* Add on 4 for total length. */
799 /****************************************************************************
800 Return a union of EA's from a file list and a list of names.
801 The TALLOC context for the two lists *MUST* be identical as we steal
802 memory from one list to add to another. JRA.
803 ****************************************************************************/
805 static struct ea_list
*ea_list_union(struct ea_list
*name_list
, struct ea_list
*file_list
, size_t *total_ea_len
)
807 struct ea_list
*nlistp
, *flistp
;
809 for (nlistp
= name_list
; nlistp
; nlistp
= nlistp
->next
) {
810 for (flistp
= file_list
; flistp
; flistp
= flistp
->next
) {
811 if (strequal(nlistp
->ea
.name
, flistp
->ea
.name
)) {
817 /* Copy the data from this entry. */
818 nlistp
->ea
.flags
= flistp
->ea
.flags
;
819 nlistp
->ea
.value
= flistp
->ea
.value
;
822 nlistp
->ea
.flags
= 0;
823 ZERO_STRUCT(nlistp
->ea
.value
);
827 *total_ea_len
= ea_list_size(name_list
);
831 /****************************************************************************
832 Send the required number of replies back.
833 We assume all fields other than the data fields are
834 set correctly for the type of call.
835 HACK ! Always assumes smb_setup field is zero.
836 ****************************************************************************/
838 void send_trans2_replies(connection_struct
*conn
,
839 struct smb_request
*req
,
847 /* As we are using a protocol > LANMAN1 then the max_send
848 variable must have been set in the sessetupX call.
849 This takes precedence over the max_xmit field in the
850 global struct. These different max_xmit variables should
851 be merged as this is now too confusing */
853 int data_to_send
= datasize
;
854 int params_to_send
= paramsize
;
856 const char *pp
= params
;
857 const char *pd
= pdata
;
858 int params_sent_thistime
, data_sent_thistime
, total_sent_thistime
;
859 int alignment_offset
= 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
860 int data_alignment_offset
= 0;
861 bool overflow
= False
;
862 struct smbd_server_connection
*sconn
= req
->sconn
;
863 int max_send
= sconn
->smb1
.sessions
.max_send
;
865 /* Modify the data_to_send and datasize and set the error if
866 we're trying to send more than max_data_bytes. We still send
867 the part of the packet(s) that fit. Strange, but needed
870 if (max_data_bytes
> 0 && datasize
> max_data_bytes
) {
871 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
872 max_data_bytes
, datasize
));
873 datasize
= data_to_send
= max_data_bytes
;
877 /* If there genuinely are no parameters or data to send just send the empty packet */
879 if(params_to_send
== 0 && data_to_send
== 0) {
880 reply_outbuf(req
, 10, 0);
881 if (NT_STATUS_V(status
)) {
884 ntstatus_to_dos(status
, &eclass
, &ecode
);
885 error_packet_set((char *)req
->outbuf
,
886 eclass
, ecode
, status
,
889 show_msg((char *)req
->outbuf
);
890 if (!srv_send_smb(sconn
,
893 IS_CONN_ENCRYPTED(conn
),
895 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
897 TALLOC_FREE(req
->outbuf
);
901 /* When sending params and data ensure that both are nicely aligned */
902 /* Only do this alignment when there is also data to send - else
903 can cause NT redirector problems. */
905 if (((params_to_send
% 4) != 0) && (data_to_send
!= 0))
906 data_alignment_offset
= 4 - (params_to_send
% 4);
908 /* Space is bufsize minus Netbios over TCP header minus SMB header */
909 /* The alignment_offset is to align the param bytes on an even byte
910 boundary. NT 4.0 Beta needs this to work correctly. */
912 useable_space
= max_send
- (smb_size
915 + data_alignment_offset
);
917 if (useable_space
< 0) {
918 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
919 "= %d!!!", useable_space
));
920 exit_server_cleanly("send_trans2_replies: Not enough space");
923 while (params_to_send
|| data_to_send
) {
924 /* Calculate whether we will totally or partially fill this packet */
926 total_sent_thistime
= params_to_send
+ data_to_send
;
928 /* We can never send more than useable_space */
930 * Note that 'useable_space' does not include the alignment offsets,
931 * but we must include the alignment offsets in the calculation of
932 * the length of the data we send over the wire, as the alignment offsets
933 * are sent here. Fix from Marc_Jacobsen@hp.com.
936 total_sent_thistime
= MIN(total_sent_thistime
, useable_space
);
938 reply_outbuf(req
, 10, total_sent_thistime
+ alignment_offset
939 + data_alignment_offset
);
941 /* Set total params and data to be sent */
942 SSVAL(req
->outbuf
,smb_tprcnt
,paramsize
);
943 SSVAL(req
->outbuf
,smb_tdrcnt
,datasize
);
945 /* Calculate how many parameters and data we can fit into
946 * this packet. Parameters get precedence
949 params_sent_thistime
= MIN(params_to_send
,useable_space
);
950 data_sent_thistime
= useable_space
- params_sent_thistime
;
951 data_sent_thistime
= MIN(data_sent_thistime
,data_to_send
);
953 SSVAL(req
->outbuf
,smb_prcnt
, params_sent_thistime
);
955 /* smb_proff is the offset from the start of the SMB header to the
956 parameter bytes, however the first 4 bytes of outbuf are
957 the Netbios over TCP header. Thus use smb_base() to subtract
958 them from the calculation */
960 SSVAL(req
->outbuf
,smb_proff
,
961 ((smb_buf(req
->outbuf
)+alignment_offset
)
962 - smb_base(req
->outbuf
)));
964 if(params_sent_thistime
== 0)
965 SSVAL(req
->outbuf
,smb_prdisp
,0);
967 /* Absolute displacement of param bytes sent in this packet */
968 SSVAL(req
->outbuf
,smb_prdisp
,pp
- params
);
970 SSVAL(req
->outbuf
,smb_drcnt
, data_sent_thistime
);
971 if(data_sent_thistime
== 0) {
972 SSVAL(req
->outbuf
,smb_droff
,0);
973 SSVAL(req
->outbuf
,smb_drdisp
, 0);
975 /* The offset of the data bytes is the offset of the
976 parameter bytes plus the number of parameters being sent this time */
977 SSVAL(req
->outbuf
, smb_droff
,
978 ((smb_buf(req
->outbuf
)+alignment_offset
)
979 - smb_base(req
->outbuf
))
980 + params_sent_thistime
+ data_alignment_offset
);
981 SSVAL(req
->outbuf
,smb_drdisp
, pd
- pdata
);
984 /* Initialize the padding for alignment */
986 if (alignment_offset
!= 0) {
987 memset(smb_buf(req
->outbuf
), 0, alignment_offset
);
990 /* Copy the param bytes into the packet */
992 if(params_sent_thistime
) {
993 memcpy((smb_buf(req
->outbuf
)+alignment_offset
), pp
,
994 params_sent_thistime
);
997 /* Copy in the data bytes */
998 if(data_sent_thistime
) {
999 if (data_alignment_offset
!= 0) {
1000 memset((smb_buf(req
->outbuf
)+alignment_offset
+
1001 params_sent_thistime
), 0,
1002 data_alignment_offset
);
1004 memcpy(smb_buf(req
->outbuf
)+alignment_offset
1005 +params_sent_thistime
+data_alignment_offset
,
1006 pd
,data_sent_thistime
);
1009 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
1010 params_sent_thistime
, data_sent_thistime
, useable_space
));
1011 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
1012 params_to_send
, data_to_send
, paramsize
, datasize
));
1015 error_packet_set((char *)req
->outbuf
,
1016 ERRDOS
,ERRbufferoverflow
,
1017 STATUS_BUFFER_OVERFLOW
,
1019 } else if (NT_STATUS_V(status
)) {
1022 ntstatus_to_dos(status
, &eclass
, &ecode
);
1023 error_packet_set((char *)req
->outbuf
,
1024 eclass
, ecode
, status
,
1028 /* Send the packet */
1029 show_msg((char *)req
->outbuf
);
1030 if (!srv_send_smb(sconn
,
1031 (char *)req
->outbuf
,
1032 true, req
->seqnum
+1,
1033 IS_CONN_ENCRYPTED(conn
),
1035 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
1037 TALLOC_FREE(req
->outbuf
);
1039 pp
+= params_sent_thistime
;
1040 pd
+= data_sent_thistime
;
1042 params_to_send
-= params_sent_thistime
;
1043 data_to_send
-= data_sent_thistime
;
1046 if(params_to_send
< 0 || data_to_send
< 0) {
1047 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
1048 params_to_send
, data_to_send
));
1056 /****************************************************************************
1057 Reply to a TRANSACT2_OPEN.
1058 ****************************************************************************/
1060 static void call_trans2open(connection_struct
*conn
,
1061 struct smb_request
*req
,
1062 char **pparams
, int total_params
,
1063 char **ppdata
, int total_data
,
1064 unsigned int max_data_bytes
)
1066 struct smb_filename
*smb_fname
= NULL
;
1067 char *params
= *pparams
;
1068 char *pdata
= *ppdata
;
1071 bool oplock_request
;
1073 bool return_additional_info
;
1082 int fattr
=0,mtime
=0;
1083 SMB_INO_T inode
= 0;
1086 struct ea_list
*ea_list
= NULL
;
1091 uint32 create_disposition
;
1092 uint32 create_options
= 0;
1093 uint32_t private_flags
= 0;
1094 TALLOC_CTX
*ctx
= talloc_tos();
1097 * Ensure we have enough parameters to perform the operation.
1100 if (total_params
< 29) {
1101 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1105 flags
= SVAL(params
, 0);
1106 deny_mode
= SVAL(params
, 2);
1107 open_attr
= SVAL(params
,6);
1108 oplock_request
= (flags
& REQUEST_OPLOCK
) ? EXCLUSIVE_OPLOCK
: 0;
1109 if (oplock_request
) {
1110 oplock_request
|= (flags
& REQUEST_BATCH_OPLOCK
) ? BATCH_OPLOCK
: 0;
1114 return_additional_info
= BITSETW(params
,0);
1115 open_sattr
= SVAL(params
, 4);
1116 open_time
= make_unix_date3(params
+8);
1118 open_ofun
= SVAL(params
,12);
1119 open_size
= IVAL(params
,14);
1120 pname
= ¶ms
[28];
1123 reply_nterror(req
, NT_STATUS_NETWORK_ACCESS_DENIED
);
1127 srvstr_get_path(ctx
, params
, req
->flags2
, &fname
, pname
,
1128 total_params
- 28, STR_TERMINATE
,
1130 if (!NT_STATUS_IS_OK(status
)) {
1131 reply_nterror(req
, status
);
1135 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
1136 fname
, (unsigned int)deny_mode
, (unsigned int)open_attr
,
1137 (unsigned int)open_ofun
, open_size
));
1139 status
= filename_convert(ctx
,
1141 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
1146 if (!NT_STATUS_IS_OK(status
)) {
1147 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
1148 reply_botherror(req
,
1149 NT_STATUS_PATH_NOT_COVERED
,
1150 ERRSRV
, ERRbadpath
);
1153 reply_nterror(req
, status
);
1157 if (open_ofun
== 0) {
1158 reply_nterror(req
, NT_STATUS_OBJECT_NAME_COLLISION
);
1162 if (!map_open_params_to_ntcreate(smb_fname
->base_name
, deny_mode
,
1164 &access_mask
, &share_mode
,
1165 &create_disposition
,
1168 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
1172 /* Any data in this call is an EA list. */
1173 if (total_data
&& (total_data
!= 4)) {
1174 if (total_data
< 10) {
1175 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1179 if (IVAL(pdata
,0) > total_data
) {
1180 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
1181 IVAL(pdata
,0), (unsigned int)total_data
));
1182 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1186 ea_list
= read_ea_list(talloc_tos(), pdata
+ 4,
1189 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1193 if (!lp_ea_support(SNUM(conn
))) {
1194 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
1198 if (ea_list_has_invalid_name(ea_list
)) {
1200 *pparams
= (char *)SMB_REALLOC(*pparams
, param_len
);
1201 if(*pparams
== NULL
) {
1202 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1206 memset(params
, '\0', param_len
);
1207 send_trans2_replies(conn
, req
, STATUS_INVALID_EA_NAME
,
1208 params
, param_len
, NULL
, 0, max_data_bytes
);
1213 status
= SMB_VFS_CREATE_FILE(
1216 0, /* root_dir_fid */
1217 smb_fname
, /* fname */
1218 access_mask
, /* access_mask */
1219 share_mode
, /* share_access */
1220 create_disposition
, /* create_disposition*/
1221 create_options
, /* create_options */
1222 open_attr
, /* file_attributes */
1223 oplock_request
, /* oplock_request */
1224 open_size
, /* allocation_size */
1227 ea_list
, /* ea_list */
1229 &smb_action
); /* psbuf */
1231 if (!NT_STATUS_IS_OK(status
)) {
1232 if (open_was_deferred(req
->sconn
, req
->mid
)) {
1233 /* We have re-scheduled this call. */
1236 reply_openerror(req
, status
);
1240 size
= get_file_size_stat(&smb_fname
->st
);
1241 fattr
= dos_mode(conn
, smb_fname
);
1242 mtime
= convert_timespec_to_time_t(smb_fname
->st
.st_ex_mtime
);
1243 inode
= smb_fname
->st
.st_ex_ino
;
1244 if (fattr
& FILE_ATTRIBUTE_DIRECTORY
) {
1245 close_file(req
, fsp
, ERROR_CLOSE
);
1246 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
1250 /* Realloc the size of parameters and data we will return */
1251 *pparams
= (char *)SMB_REALLOC(*pparams
, 30);
1252 if(*pparams
== NULL
) {
1253 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1258 SSVAL(params
,0,fsp
->fnum
);
1259 SSVAL(params
,2,fattr
);
1260 srv_put_dos_date2(params
,4, mtime
);
1261 SIVAL(params
,8, (uint32
)size
);
1262 SSVAL(params
,12,deny_mode
);
1263 SSVAL(params
,14,0); /* open_type - file or directory. */
1264 SSVAL(params
,16,0); /* open_state - only valid for IPC device. */
1266 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
1267 smb_action
|= EXTENDED_OPLOCK_GRANTED
;
1270 SSVAL(params
,18,smb_action
);
1273 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1275 SIVAL(params
,20,inode
);
1276 SSVAL(params
,24,0); /* Padding. */
1278 uint32 ea_size
= estimate_ea_size(conn
, fsp
,
1280 SIVAL(params
, 26, ea_size
);
1282 SIVAL(params
, 26, 0);
1285 /* Send the required number of replies */
1286 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 30, *ppdata
, 0, max_data_bytes
);
1288 TALLOC_FREE(smb_fname
);
1291 /*********************************************************
1292 Routine to check if a given string matches exactly.
1293 as a special case a mask of "." does NOT match. That
1294 is required for correct wildcard semantics
1295 Case can be significant or not.
1296 **********************************************************/
1298 static bool exact_match(bool has_wild
,
1299 bool case_sensitive
,
1303 if (mask
[0] == '.' && mask
[1] == 0) {
1311 if (case_sensitive
) {
1312 return strcmp(str
,mask
)==0;
1314 return strcasecmp_m(str
,mask
) == 0;
1318 /****************************************************************************
1319 Return the filetype for UNIX extensions.
1320 ****************************************************************************/
1322 static uint32
unix_filetype(mode_t mode
)
1325 return UNIX_TYPE_FILE
;
1326 else if(S_ISDIR(mode
))
1327 return UNIX_TYPE_DIR
;
1329 else if(S_ISLNK(mode
))
1330 return UNIX_TYPE_SYMLINK
;
1333 else if(S_ISCHR(mode
))
1334 return UNIX_TYPE_CHARDEV
;
1337 else if(S_ISBLK(mode
))
1338 return UNIX_TYPE_BLKDEV
;
1341 else if(S_ISFIFO(mode
))
1342 return UNIX_TYPE_FIFO
;
1345 else if(S_ISSOCK(mode
))
1346 return UNIX_TYPE_SOCKET
;
1349 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode
));
1350 return UNIX_TYPE_UNKNOWN
;
1353 /****************************************************************************
1354 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1355 ****************************************************************************/
1357 enum perm_type
{ PERM_NEW_FILE
, PERM_NEW_DIR
, PERM_EXISTING_FILE
, PERM_EXISTING_DIR
};
1359 static NTSTATUS
unix_perms_from_wire( connection_struct
*conn
,
1360 const SMB_STRUCT_STAT
*psbuf
,
1362 enum perm_type ptype
,
1367 if (perms
== SMB_MODE_NO_CHANGE
) {
1368 if (!VALID_STAT(*psbuf
)) {
1369 return NT_STATUS_INVALID_PARAMETER
;
1371 *ret_perms
= psbuf
->st_ex_mode
;
1372 return NT_STATUS_OK
;
1376 ret
|= ((perms
& UNIX_X_OTH
) ? S_IXOTH
: 0);
1377 ret
|= ((perms
& UNIX_W_OTH
) ? S_IWOTH
: 0);
1378 ret
|= ((perms
& UNIX_R_OTH
) ? S_IROTH
: 0);
1379 ret
|= ((perms
& UNIX_X_GRP
) ? S_IXGRP
: 0);
1380 ret
|= ((perms
& UNIX_W_GRP
) ? S_IWGRP
: 0);
1381 ret
|= ((perms
& UNIX_R_GRP
) ? S_IRGRP
: 0);
1382 ret
|= ((perms
& UNIX_X_USR
) ? S_IXUSR
: 0);
1383 ret
|= ((perms
& UNIX_W_USR
) ? S_IWUSR
: 0);
1384 ret
|= ((perms
& UNIX_R_USR
) ? S_IRUSR
: 0);
1386 ret
|= ((perms
& UNIX_STICKY
) ? S_ISVTX
: 0);
1389 ret
|= ((perms
& UNIX_SET_GID
) ? S_ISGID
: 0);
1392 ret
|= ((perms
& UNIX_SET_UID
) ? S_ISUID
: 0);
1395 if (ptype
== PERM_NEW_FILE
) {
1397 * "create mask"/"force create mode" are
1398 * only applied to new files, not existing ones.
1400 ret
&= lp_create_mask(SNUM(conn
));
1401 /* Add in force bits */
1402 ret
|= lp_force_create_mode(SNUM(conn
));
1403 } else if (ptype
== PERM_NEW_DIR
) {
1405 * "directory mask"/"force directory mode" are
1406 * only applied to new directories, not existing ones.
1408 ret
&= lp_directory_mask(SNUM(conn
));
1409 /* Add in force bits */
1410 ret
|= lp_force_directory_mode(SNUM(conn
));
1414 return NT_STATUS_OK
;
1417 /****************************************************************************
1418 Needed to show the msdfs symlinks as directories. Modifies psbuf
1419 to be a directory if it's a msdfs link.
1420 ****************************************************************************/
1422 static bool check_msdfs_link(connection_struct
*conn
,
1423 const char *pathname
,
1424 SMB_STRUCT_STAT
*psbuf
)
1426 int saved_errno
= errno
;
1427 if(lp_host_msdfs() &&
1428 lp_msdfs_root(SNUM(conn
)) &&
1429 is_msdfs_link(conn
, pathname
, psbuf
)) {
1431 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1434 psbuf
->st_ex_mode
= (psbuf
->st_ex_mode
& 0xFFF) | S_IFDIR
;
1435 errno
= saved_errno
;
1438 errno
= saved_errno
;
1443 /****************************************************************************
1444 Get a level dependent lanman2 dir entry.
1445 ****************************************************************************/
1447 struct smbd_dirptr_lanman2_state
{
1448 connection_struct
*conn
;
1449 uint32_t info_level
;
1450 bool check_mangled_names
;
1452 bool got_exact_match
;
1455 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX
*ctx
,
1461 struct smbd_dirptr_lanman2_state
*state
=
1462 (struct smbd_dirptr_lanman2_state
*)private_data
;
1464 char mangled_name
[13]; /* mangled 8.3 name. */
1468 /* Mangle fname if it's an illegal name. */
1469 if (mangle_must_mangle(dname
, state
->conn
->params
)) {
1470 ok
= name_to_8_3(dname
, mangled_name
,
1471 true, state
->conn
->params
);
1475 fname
= mangled_name
;
1480 got_match
= exact_match(state
->has_wild
,
1481 state
->conn
->case_sensitive
,
1483 state
->got_exact_match
= got_match
;
1485 got_match
= mask_match(fname
, mask
,
1486 state
->conn
->case_sensitive
);
1489 if(!got_match
&& state
->check_mangled_names
&&
1490 !mangle_is_8_3(fname
, false, state
->conn
->params
)) {
1492 * It turns out that NT matches wildcards against
1493 * both long *and* short names. This may explain some
1494 * of the wildcard wierdness from old DOS clients
1495 * that some people have been seeing.... JRA.
1497 /* Force the mangling into 8.3. */
1498 ok
= name_to_8_3(fname
, mangled_name
,
1499 false, state
->conn
->params
);
1504 got_match
= exact_match(state
->has_wild
,
1505 state
->conn
->case_sensitive
,
1506 mangled_name
, mask
);
1507 state
->got_exact_match
= got_match
;
1509 got_match
= mask_match(mangled_name
, mask
,
1510 state
->conn
->case_sensitive
);
1518 *_fname
= talloc_strdup(ctx
, fname
);
1519 if (*_fname
== NULL
) {
1526 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX
*ctx
,
1528 struct smb_filename
*smb_fname
,
1531 struct smbd_dirptr_lanman2_state
*state
=
1532 (struct smbd_dirptr_lanman2_state
*)private_data
;
1533 bool ms_dfs_link
= false;
1536 if (INFO_LEVEL_IS_UNIX(state
->info_level
)) {
1537 if (SMB_VFS_LSTAT(state
->conn
, smb_fname
) != 0) {
1538 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1539 "Couldn't lstat [%s] (%s)\n",
1540 smb_fname_str_dbg(smb_fname
),
1544 } else if (!VALID_STAT(smb_fname
->st
) &&
1545 SMB_VFS_STAT(state
->conn
, smb_fname
) != 0) {
1546 /* Needed to show the msdfs symlinks as
1549 ms_dfs_link
= check_msdfs_link(state
->conn
,
1550 smb_fname
->base_name
,
1553 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1554 "Couldn't stat [%s] (%s)\n",
1555 smb_fname_str_dbg(smb_fname
),
1562 mode
= dos_mode_msdfs(state
->conn
, smb_fname
);
1564 mode
= dos_mode(state
->conn
, smb_fname
);
1571 static bool smbd_marshall_dir_entry(TALLOC_CTX
*ctx
,
1572 connection_struct
*conn
,
1574 uint32_t info_level
,
1575 struct ea_list
*name_list
,
1576 bool check_mangled_names
,
1577 bool requires_resume_key
,
1580 const struct smb_filename
*smb_fname
,
1581 int space_remaining
,
1588 uint64_t *last_entry_off
)
1590 char *p
, *q
, *pdata
= *ppdata
;
1592 uint64_t file_size
= 0;
1593 uint64_t allocation_size
= 0;
1594 uint64_t file_index
= 0;
1596 struct timespec mdate_ts
, adate_ts
, cdate_ts
, create_date_ts
;
1597 time_t mdate
= (time_t)0, adate
= (time_t)0, create_date
= (time_t)0;
1599 char *last_entry_ptr
;
1604 *out_of_space
= false;
1606 ZERO_STRUCT(mdate_ts
);
1607 ZERO_STRUCT(adate_ts
);
1608 ZERO_STRUCT(create_date_ts
);
1609 ZERO_STRUCT(cdate_ts
);
1611 if (!(mode
& FILE_ATTRIBUTE_DIRECTORY
)) {
1612 file_size
= get_file_size_stat(&smb_fname
->st
);
1614 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
, NULL
, &smb_fname
->st
);
1616 file_index
= get_FileIndex(conn
, &smb_fname
->st
);
1618 mdate_ts
= smb_fname
->st
.st_ex_mtime
;
1619 adate_ts
= smb_fname
->st
.st_ex_atime
;
1620 create_date_ts
= get_create_timespec(conn
, NULL
, smb_fname
);
1621 cdate_ts
= get_change_timespec(conn
, NULL
, smb_fname
);
1623 if (lp_dos_filetime_resolution(SNUM(conn
))) {
1624 dos_filetime_timespec(&create_date_ts
);
1625 dos_filetime_timespec(&mdate_ts
);
1626 dos_filetime_timespec(&adate_ts
);
1627 dos_filetime_timespec(&cdate_ts
);
1630 create_date
= convert_timespec_to_time_t(create_date_ts
);
1631 mdate
= convert_timespec_to_time_t(mdate_ts
);
1632 adate
= convert_timespec_to_time_t(adate_ts
);
1634 /* align the record */
1635 SMB_ASSERT(align
>= 1);
1637 off
= (int)PTR_DIFF(pdata
, base_data
);
1638 pad
= (off
+ (align
-1)) & ~(align
-1);
1641 if (pad
&& pad
> space_remaining
) {
1642 *out_of_space
= true;
1643 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1644 "for padding (wanted %u, had %d)\n",
1647 return false; /* Not finished - just out of space */
1651 /* initialize padding to 0 */
1653 memset(pdata
, 0, pad
);
1655 space_remaining
-= pad
;
1657 DEBUG(10,("smbd_marshall_dir_entry: space_remaining = %d\n",
1667 switch (info_level
) {
1668 case SMB_FIND_INFO_STANDARD
:
1669 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1670 if(requires_resume_key
) {
1674 srv_put_dos_date2(p
,0,create_date
);
1675 srv_put_dos_date2(p
,4,adate
);
1676 srv_put_dos_date2(p
,8,mdate
);
1677 SIVAL(p
,12,(uint32
)file_size
);
1678 SIVAL(p
,16,(uint32
)allocation_size
);
1682 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1683 p
+= ucs2_align(base_data
, p
, 0);
1685 len
= srvstr_push(base_data
, flags2
, p
,
1686 fname
, PTR_DIFF(end_data
, p
),
1688 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1690 SCVAL(nameptr
, -1, len
- 2);
1692 SCVAL(nameptr
, -1, 0);
1696 SCVAL(nameptr
, -1, len
- 1);
1698 SCVAL(nameptr
, -1, 0);
1704 case SMB_FIND_EA_SIZE
:
1705 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
1706 if (requires_resume_key
) {
1710 srv_put_dos_date2(p
,0,create_date
);
1711 srv_put_dos_date2(p
,4,adate
);
1712 srv_put_dos_date2(p
,8,mdate
);
1713 SIVAL(p
,12,(uint32
)file_size
);
1714 SIVAL(p
,16,(uint32
)allocation_size
);
1717 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
1719 SIVAL(p
,22,ea_size
); /* Extended attributes */
1723 len
= srvstr_push(base_data
, flags2
,
1724 p
, fname
, PTR_DIFF(end_data
, p
),
1725 STR_TERMINATE
| STR_NOALIGN
);
1726 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1739 SCVAL(nameptr
,0,len
);
1741 SCVAL(p
,0,0); p
+= 1; /* Extra zero byte ? - why.. */
1744 case SMB_FIND_EA_LIST
:
1746 struct ea_list
*file_list
= NULL
;
1750 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
1754 if (requires_resume_key
) {
1758 srv_put_dos_date2(p
,0,create_date
);
1759 srv_put_dos_date2(p
,4,adate
);
1760 srv_put_dos_date2(p
,8,mdate
);
1761 SIVAL(p
,12,(uint32
)file_size
);
1762 SIVAL(p
,16,(uint32
)allocation_size
);
1764 p
+= 22; /* p now points to the EA area. */
1766 status
= get_ea_list_from_file(ctx
, conn
, NULL
,
1768 &ea_len
, &file_list
);
1769 if (!NT_STATUS_IS_OK(status
)) {
1772 name_list
= ea_list_union(name_list
, file_list
, &ea_len
);
1774 /* We need to determine if this entry will fit in the space available. */
1775 /* Max string size is 255 bytes. */
1776 if (PTR_DIFF(p
+ 255 + ea_len
,pdata
) > space_remaining
) {
1777 *out_of_space
= true;
1778 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1779 "(wanted %u, had %d)\n",
1780 (unsigned int)PTR_DIFF(p
+ 255 + ea_len
,pdata
),
1782 return False
; /* Not finished - just out of space */
1785 /* Push the ea_data followed by the name. */
1786 p
+= fill_ea_buffer(ctx
, p
, space_remaining
, conn
, name_list
);
1788 len
= srvstr_push(base_data
, flags2
,
1789 p
+ 1, fname
, PTR_DIFF(end_data
, p
+1),
1790 STR_TERMINATE
| STR_NOALIGN
);
1791 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1804 SCVAL(nameptr
,0,len
);
1806 SCVAL(p
,0,0); p
+= 1; /* Extra zero byte ? - why.. */
1810 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
1811 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1812 was_8_3
= mangle_is_8_3(fname
, True
, conn
->params
);
1814 SIVAL(p
,0,reskey
); p
+= 4;
1815 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
1816 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
1817 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
1818 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
1819 SOFF_T(p
,0,file_size
); p
+= 8;
1820 SOFF_T(p
,0,allocation_size
); p
+= 8;
1821 SIVAL(p
,0,mode
); p
+= 4;
1822 q
= p
; p
+= 4; /* q is placeholder for name length. */
1823 if (mode
& FILE_ATTRIBUTE_REPARSE_POINT
) {
1824 SIVAL(p
, 0, IO_REPARSE_TAG_DFS
);
1826 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
1828 SIVAL(p
,0,ea_size
); /* Extended attributes */
1831 /* Clear the short name buffer. This is
1832 * IMPORTANT as not doing so will trigger
1833 * a Win2k client bug. JRA.
1835 if (!was_8_3
&& check_mangled_names
) {
1836 char mangled_name
[13]; /* mangled 8.3 name. */
1837 if (!name_to_8_3(fname
,mangled_name
,True
,
1839 /* Error - mangle failed ! */
1840 memset(mangled_name
,'\0',12);
1842 mangled_name
[12] = 0;
1843 len
= srvstr_push(base_data
, flags2
,
1844 p
+2, mangled_name
, 24,
1845 STR_UPPER
|STR_UNICODE
);
1847 memset(p
+ 2 + len
,'\0',24 - len
);
1854 len
= srvstr_push(base_data
, flags2
, p
,
1855 fname
, PTR_DIFF(end_data
, p
),
1856 STR_TERMINATE_ASCII
);
1860 len
= PTR_DIFF(p
, pdata
);
1861 pad
= (len
+ (align
-1)) & ~(align
-1);
1863 * offset to the next entry, the caller
1864 * will overwrite it for the last entry
1865 * that's why we always include the padding
1869 * set padding to zero
1872 memset(p
, 0, pad
- len
);
1879 case SMB_FIND_FILE_DIRECTORY_INFO
:
1880 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1882 SIVAL(p
,0,reskey
); p
+= 4;
1883 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
1884 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
1885 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
1886 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
1887 SOFF_T(p
,0,file_size
); p
+= 8;
1888 SOFF_T(p
,0,allocation_size
); p
+= 8;
1889 SIVAL(p
,0,mode
); p
+= 4;
1890 len
= srvstr_push(base_data
, flags2
,
1891 p
+ 4, fname
, PTR_DIFF(end_data
, p
+4),
1892 STR_TERMINATE_ASCII
);
1896 len
= PTR_DIFF(p
, pdata
);
1897 pad
= (len
+ (align
-1)) & ~(align
-1);
1899 * offset to the next entry, the caller
1900 * will overwrite it for the last entry
1901 * that's why we always include the padding
1905 * set padding to zero
1908 memset(p
, 0, pad
- len
);
1915 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
1916 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1918 SIVAL(p
,0,reskey
); p
+= 4;
1919 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
1920 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
1921 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
1922 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
1923 SOFF_T(p
,0,file_size
); p
+= 8;
1924 SOFF_T(p
,0,allocation_size
); p
+= 8;
1925 SIVAL(p
,0,mode
); p
+= 4;
1926 q
= p
; p
+= 4; /* q is placeholder for name length. */
1928 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
1930 SIVAL(p
,0,ea_size
); /* Extended attributes */
1933 len
= srvstr_push(base_data
, flags2
, p
,
1934 fname
, PTR_DIFF(end_data
, p
),
1935 STR_TERMINATE_ASCII
);
1939 len
= PTR_DIFF(p
, pdata
);
1940 pad
= (len
+ (align
-1)) & ~(align
-1);
1942 * offset to the next entry, the caller
1943 * will overwrite it for the last entry
1944 * that's why we always include the padding
1948 * set padding to zero
1951 memset(p
, 0, pad
- len
);
1958 case SMB_FIND_FILE_NAMES_INFO
:
1959 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1961 SIVAL(p
,0,reskey
); p
+= 4;
1963 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1964 acl on a dir (tridge) */
1965 len
= srvstr_push(base_data
, flags2
, p
,
1966 fname
, PTR_DIFF(end_data
, p
),
1967 STR_TERMINATE_ASCII
);
1971 len
= PTR_DIFF(p
, pdata
);
1972 pad
= (len
+ (align
-1)) & ~(align
-1);
1974 * offset to the next entry, the caller
1975 * will overwrite it for the last entry
1976 * that's why we always include the padding
1980 * set padding to zero
1983 memset(p
, 0, pad
- len
);
1990 case SMB_FIND_ID_FULL_DIRECTORY_INFO
:
1991 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1993 SIVAL(p
,0,reskey
); p
+= 4;
1994 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
1995 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
1996 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
1997 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
1998 SOFF_T(p
,0,file_size
); p
+= 8;
1999 SOFF_T(p
,0,allocation_size
); p
+= 8;
2000 SIVAL(p
,0,mode
); p
+= 4;
2001 q
= p
; p
+= 4; /* q is placeholder for name length. */
2002 if (mode
& FILE_ATTRIBUTE_REPARSE_POINT
) {
2003 SIVAL(p
, 0, IO_REPARSE_TAG_DFS
);
2005 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
2007 SIVAL(p
,0,ea_size
); /* Extended attributes */
2010 SIVAL(p
,0,0); p
+= 4; /* Unknown - reserved ? */
2011 SBVAL(p
,0,file_index
); p
+= 8;
2012 len
= srvstr_push(base_data
, flags2
, p
,
2013 fname
, PTR_DIFF(end_data
, p
),
2014 STR_TERMINATE_ASCII
);
2018 len
= PTR_DIFF(p
, pdata
);
2019 pad
= (len
+ (align
-1)) & ~(align
-1);
2021 * offset to the next entry, the caller
2022 * will overwrite it for the last entry
2023 * that's why we always include the padding
2027 * set padding to zero
2030 memset(p
, 0, pad
- len
);
2037 case SMB_FIND_ID_BOTH_DIRECTORY_INFO
:
2038 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
2039 was_8_3
= mangle_is_8_3(fname
, True
, conn
->params
);
2041 SIVAL(p
,0,reskey
); p
+= 4;
2042 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
2043 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
2044 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
2045 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
2046 SOFF_T(p
,0,file_size
); p
+= 8;
2047 SOFF_T(p
,0,allocation_size
); p
+= 8;
2048 SIVAL(p
,0,mode
); p
+= 4;
2049 q
= p
; p
+= 4; /* q is placeholder for name length */
2050 if (mode
& FILE_ATTRIBUTE_REPARSE_POINT
) {
2051 SIVAL(p
, 0, IO_REPARSE_TAG_DFS
);
2053 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
2055 SIVAL(p
,0,ea_size
); /* Extended attributes */
2058 /* Clear the short name buffer. This is
2059 * IMPORTANT as not doing so will trigger
2060 * a Win2k client bug. JRA.
2062 if (!was_8_3
&& check_mangled_names
) {
2063 char mangled_name
[13]; /* mangled 8.3 name. */
2064 if (!name_to_8_3(fname
,mangled_name
,True
,
2066 /* Error - mangle failed ! */
2067 memset(mangled_name
,'\0',12);
2069 mangled_name
[12] = 0;
2070 len
= srvstr_push(base_data
, flags2
,
2071 p
+2, mangled_name
, 24,
2072 STR_UPPER
|STR_UNICODE
);
2075 memset(p
+ 2 + len
,'\0',24 - len
);
2082 SSVAL(p
,0,0); p
+= 2; /* Reserved ? */
2083 SBVAL(p
,0,file_index
); p
+= 8;
2084 len
= srvstr_push(base_data
, flags2
, p
,
2085 fname
, PTR_DIFF(end_data
, p
),
2086 STR_TERMINATE_ASCII
);
2090 len
= PTR_DIFF(p
, pdata
);
2091 pad
= (len
+ (align
-1)) & ~(align
-1);
2093 * offset to the next entry, the caller
2094 * will overwrite it for the last entry
2095 * that's why we always include the padding
2099 * set padding to zero
2102 memset(p
, 0, pad
- len
);
2109 /* CIFS UNIX Extension. */
2111 case SMB_FIND_FILE_UNIX
:
2112 case SMB_FIND_FILE_UNIX_INFO2
:
2114 SIVAL(p
,0,reskey
); p
+= 4; /* Used for continuing search. */
2116 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
2118 if (info_level
== SMB_FIND_FILE_UNIX
) {
2119 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
2120 p
= store_file_unix_basic(conn
, p
,
2121 NULL
, &smb_fname
->st
);
2122 len
= srvstr_push(base_data
, flags2
, p
,
2123 fname
, PTR_DIFF(end_data
, p
),
2126 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
2127 p
= store_file_unix_basic_info2(conn
, p
,
2128 NULL
, &smb_fname
->st
);
2131 len
= srvstr_push(base_data
, flags2
, p
, fname
,
2132 PTR_DIFF(end_data
, p
), 0);
2133 SIVAL(nameptr
, 0, len
);
2138 len
= PTR_DIFF(p
, pdata
);
2139 pad
= (len
+ (align
-1)) & ~(align
-1);
2141 * offset to the next entry, the caller
2142 * will overwrite it for the last entry
2143 * that's why we always include the padding
2147 * set padding to zero
2150 memset(p
, 0, pad
- len
);
2155 /* End of SMB_QUERY_FILE_UNIX_BASIC */
2163 if (PTR_DIFF(p
,pdata
) > space_remaining
) {
2164 *out_of_space
= true;
2165 DEBUG(9,("smbd_marshall_dir_entry: out of space "
2166 "(wanted %u, had %d)\n",
2167 (unsigned int)PTR_DIFF(p
,pdata
),
2169 return false; /* Not finished - just out of space */
2172 /* Setup the last entry pointer, as an offset from base_data */
2173 *last_entry_off
= PTR_DIFF(last_entry_ptr
,base_data
);
2174 /* Advance the data pointer to the next slot */
2180 bool smbd_dirptr_lanman2_entry(TALLOC_CTX
*ctx
,
2181 connection_struct
*conn
,
2182 struct dptr_struct
*dirptr
,
2184 const char *path_mask
,
2187 int requires_resume_key
,
2195 int space_remaining
,
2197 bool *got_exact_match
,
2198 int *_last_entry_off
,
2199 struct ea_list
*name_list
)
2202 const char *mask
= NULL
;
2203 long prev_dirpos
= 0;
2206 struct smb_filename
*smb_fname
= NULL
;
2207 struct smbd_dirptr_lanman2_state state
;
2209 uint64_t last_entry_off
= 0;
2213 state
.info_level
= info_level
;
2214 state
.check_mangled_names
= lp_mangled_names(conn
->params
);
2215 state
.has_wild
= dptr_has_wild(dirptr
);
2216 state
.got_exact_match
= false;
2218 *out_of_space
= false;
2219 *got_exact_match
= false;
2221 p
= strrchr_m(path_mask
,'/');
2232 ok
= smbd_dirptr_get_entry(ctx
,
2238 smbd_dirptr_lanman2_match_fn
,
2239 smbd_dirptr_lanman2_mode_fn
,
2249 *got_exact_match
= state
.got_exact_match
;
2251 ok
= smbd_marshall_dir_entry(ctx
,
2256 state
.check_mangled_names
,
2257 requires_resume_key
,
2270 TALLOC_FREE(smb_fname
);
2271 if (*out_of_space
) {
2272 dptr_SeekDir(dirptr
, prev_dirpos
);
2279 *_last_entry_off
= last_entry_off
;
2283 static bool get_lanman2_dir_entry(TALLOC_CTX
*ctx
,
2284 connection_struct
*conn
,
2285 struct dptr_struct
*dirptr
,
2287 const char *path_mask
,
2290 bool requires_resume_key
,
2296 int space_remaining
,
2298 bool *got_exact_match
,
2299 int *last_entry_off
,
2300 struct ea_list
*name_list
)
2303 const bool do_pad
= true;
2305 if (info_level
>= 1 && info_level
<= 3) {
2306 /* No alignment on earlier info levels. */
2310 return smbd_dirptr_lanman2_entry(ctx
, conn
, dirptr
, flags2
,
2311 path_mask
, dirtype
, info_level
,
2312 requires_resume_key
, dont_descend
, ask_sharemode
,
2314 ppdata
, base_data
, end_data
,
2316 out_of_space
, got_exact_match
,
2317 last_entry_off
, name_list
);
2320 /****************************************************************************
2321 Reply to a TRANS2_FINDFIRST.
2322 ****************************************************************************/
2324 static void call_trans2findfirst(connection_struct
*conn
,
2325 struct smb_request
*req
,
2326 char **pparams
, int total_params
,
2327 char **ppdata
, int total_data
,
2328 unsigned int max_data_bytes
)
2330 /* We must be careful here that we don't return more than the
2331 allowed number of data bytes. If this means returning fewer than
2332 maxentries then so be it. We assume that the redirector has
2333 enough room for the fixed number of parameter bytes it has
2335 struct smb_filename
*smb_dname
= NULL
;
2336 char *params
= *pparams
;
2337 char *pdata
= *ppdata
;
2341 uint16 findfirst_flags
;
2342 bool close_after_first
;
2344 bool requires_resume_key
;
2346 char *directory
= NULL
;
2349 int last_entry_off
=0;
2353 bool finished
= False
;
2354 bool dont_descend
= False
;
2355 bool out_of_space
= False
;
2356 int space_remaining
;
2357 bool mask_contains_wcard
= False
;
2358 struct ea_list
*ea_list
= NULL
;
2359 NTSTATUS ntstatus
= NT_STATUS_OK
;
2360 bool ask_sharemode
= lp_parm_bool(SNUM(conn
), "smbd", "search ask sharemode", true);
2361 TALLOC_CTX
*ctx
= talloc_tos();
2362 struct dptr_struct
*dirptr
= NULL
;
2363 struct smbd_server_connection
*sconn
= req
->sconn
;
2364 uint32_t ucf_flags
= (UCF_SAVE_LCOMP
| UCF_ALWAYS_ALLOW_WCARD_LCOMP
);
2365 bool backup_priv
= false;
2367 if (total_params
< 13) {
2368 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2372 dirtype
= SVAL(params
,0);
2373 maxentries
= SVAL(params
,2);
2374 findfirst_flags
= SVAL(params
,4);
2375 close_after_first
= (findfirst_flags
& FLAG_TRANS2_FIND_CLOSE
);
2376 close_if_end
= (findfirst_flags
& FLAG_TRANS2_FIND_CLOSE_IF_END
);
2377 requires_resume_key
= (findfirst_flags
& FLAG_TRANS2_FIND_REQUIRE_RESUME
);
2378 backup_priv
= ((findfirst_flags
& FLAG_TRANS2_FIND_BACKUP_INTENT
) &&
2379 security_token_has_privilege(get_current_nttok(conn
),
2382 info_level
= SVAL(params
,6);
2384 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2385 close_if_end = %d requires_resume_key = %d backup_priv = %d level = 0x%x, max_data_bytes = %d\n",
2386 (unsigned int)dirtype
, maxentries
, close_after_first
, close_if_end
, requires_resume_key
,
2388 info_level
, max_data_bytes
));
2391 /* W2K3 seems to treat zero as 1. */
2395 switch (info_level
) {
2396 case SMB_FIND_INFO_STANDARD
:
2397 case SMB_FIND_EA_SIZE
:
2398 case SMB_FIND_EA_LIST
:
2399 case SMB_FIND_FILE_DIRECTORY_INFO
:
2400 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
2401 case SMB_FIND_FILE_NAMES_INFO
:
2402 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
2403 case SMB_FIND_ID_FULL_DIRECTORY_INFO
:
2404 case SMB_FIND_ID_BOTH_DIRECTORY_INFO
:
2406 case SMB_FIND_FILE_UNIX
:
2407 case SMB_FIND_FILE_UNIX_INFO2
:
2408 /* Always use filesystem for UNIX mtime query. */
2409 ask_sharemode
= false;
2410 if (!lp_unix_extensions()) {
2411 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2414 ucf_flags
|= UCF_UNIX_NAME_LOOKUP
;
2417 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2421 srvstr_get_path_wcard(ctx
, params
, req
->flags2
, &directory
,
2422 params
+12, total_params
- 12,
2423 STR_TERMINATE
, &ntstatus
, &mask_contains_wcard
);
2424 if (!NT_STATUS_IS_OK(ntstatus
)) {
2425 reply_nterror(req
, ntstatus
);
2431 ntstatus
= filename_convert_with_privilege(ctx
,
2436 &mask_contains_wcard
,
2439 ntstatus
= filename_convert(ctx
, conn
,
2440 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
2443 &mask_contains_wcard
,
2447 if (!NT_STATUS_IS_OK(ntstatus
)) {
2448 if (NT_STATUS_EQUAL(ntstatus
,NT_STATUS_PATH_NOT_COVERED
)) {
2449 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
2450 ERRSRV
, ERRbadpath
);
2453 reply_nterror(req
, ntstatus
);
2457 mask
= smb_dname
->original_lcomp
;
2459 directory
= smb_dname
->base_name
;
2461 p
= strrchr_m(directory
,'/');
2463 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2464 if((directory
[0] == '.') && (directory
[1] == '\0')) {
2465 mask
= talloc_strdup(ctx
,"*");
2467 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2470 mask_contains_wcard
= True
;
2476 if (p
== NULL
|| p
== directory
) {
2477 /* Ensure we don't have a directory name of "". */
2478 directory
= talloc_strdup(talloc_tos(), ".");
2480 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2485 DEBUG(5,("dir=%s, mask = %s\n",directory
, mask
));
2487 if (info_level
== SMB_FIND_EA_LIST
) {
2490 if (total_data
< 4) {
2491 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2495 ea_size
= IVAL(pdata
,0);
2496 if (ea_size
!= total_data
) {
2497 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2498 total_data=%u (should be %u)\n", (unsigned int)total_data
, (unsigned int)IVAL(pdata
,0) ));
2499 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2503 if (!lp_ea_support(SNUM(conn
))) {
2504 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
2508 /* Pull out the list of names. */
2509 ea_list
= read_ea_name_list(ctx
, pdata
+ 4, ea_size
- 4);
2511 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2516 if (max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
< max_data_bytes
) {
2517 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2521 *ppdata
= (char *)SMB_REALLOC(
2522 *ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
2523 if(*ppdata
== NULL
) {
2524 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2528 data_end
= pdata
+ max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
- 1;
2530 /* Realloc the params space */
2531 *pparams
= (char *)SMB_REALLOC(*pparams
, 10);
2532 if (*pparams
== NULL
) {
2533 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2538 /* Save the wildcard match and attribs we are using on this directory -
2539 needed as lanman2 assumes these are being saved between calls */
2541 ntstatus
= dptr_create(conn
,
2549 mask_contains_wcard
,
2553 if (!NT_STATUS_IS_OK(ntstatus
)) {
2554 reply_nterror(req
, ntstatus
);
2559 /* Remember this in case we have
2560 to do a findnext. */
2561 dptr_set_priv(dirptr
);
2564 dptr_num
= dptr_dnum(dirptr
);
2565 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num
, mask
, dirtype
));
2567 /* Initialize per TRANS2_FIND_FIRST operation data */
2568 dptr_init_search_op(dirptr
);
2570 /* We don't need to check for VOL here as this is returned by
2571 a different TRANS2 call. */
2573 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2574 directory
,lp_dont_descend(ctx
, SNUM(conn
))));
2575 if (in_list(directory
,lp_dont_descend(ctx
, SNUM(conn
)),conn
->case_sensitive
))
2576 dont_descend
= True
;
2579 space_remaining
= max_data_bytes
;
2580 out_of_space
= False
;
2582 for (i
=0;(i
<maxentries
) && !finished
&& !out_of_space
;i
++) {
2583 bool got_exact_match
= False
;
2585 /* this is a heuristic to avoid seeking the dirptr except when
2586 absolutely necessary. It allows for a filename of about 40 chars */
2587 if (space_remaining
< DIRLEN_GUESS
&& numentries
> 0) {
2588 out_of_space
= True
;
2591 finished
= !get_lanman2_dir_entry(ctx
,
2595 mask
,dirtype
,info_level
,
2596 requires_resume_key
,dont_descend
,
2599 space_remaining
, &out_of_space
,
2601 &last_entry_off
, ea_list
);
2604 if (finished
&& out_of_space
)
2607 if (!finished
&& !out_of_space
)
2611 * As an optimisation if we know we aren't looking
2612 * for a wildcard name (ie. the name matches the wildcard exactly)
2613 * then we can finish on any (first) match.
2614 * This speeds up large directory searches. JRA.
2620 /* Ensure space_remaining never goes -ve. */
2621 if (PTR_DIFF(p
,pdata
) > max_data_bytes
) {
2622 space_remaining
= 0;
2623 out_of_space
= true;
2625 space_remaining
= max_data_bytes
- PTR_DIFF(p
,pdata
);
2629 /* Check if we can close the dirptr */
2630 if(close_after_first
|| (finished
&& close_if_end
)) {
2631 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num
));
2632 dptr_close(sconn
, &dptr_num
);
2636 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2637 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2638 * the protocol level is less than NT1. Tested with smbclient. JRA.
2639 * This should fix the OS/2 client bug #2335.
2642 if(numentries
== 0) {
2643 dptr_close(sconn
, &dptr_num
);
2644 if (get_Protocol() < PROTOCOL_NT1
) {
2645 reply_force_doserror(req
, ERRDOS
, ERRnofiles
);
2648 reply_botherror(req
, NT_STATUS_NO_SUCH_FILE
,
2649 ERRDOS
, ERRbadfile
);
2654 /* At this point pdata points to numentries directory entries. */
2656 /* Set up the return parameter block */
2657 SSVAL(params
,0,dptr_num
);
2658 SSVAL(params
,2,numentries
);
2659 SSVAL(params
,4,finished
);
2660 SSVAL(params
,6,0); /* Never an EA error */
2661 SSVAL(params
,8,last_entry_off
);
2663 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 10, pdata
, PTR_DIFF(p
,pdata
),
2666 if ((! *directory
) && dptr_path(sconn
, dptr_num
)) {
2667 directory
= talloc_strdup(talloc_tos(),dptr_path(sconn
, dptr_num
));
2669 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2673 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2674 smb_fn_name(req
->cmd
),
2675 mask
, directory
, dirtype
, numentries
) );
2678 * Force a name mangle here to ensure that the
2679 * mask as an 8.3 name is top of the mangled cache.
2680 * The reasons for this are subtle. Don't remove
2681 * this code unless you know what you are doing
2682 * (see PR#13758). JRA.
2685 if(!mangle_is_8_3_wildcards( mask
, False
, conn
->params
)) {
2686 char mangled_name
[13];
2687 name_to_8_3(mask
, mangled_name
, True
, conn
->params
);
2695 TALLOC_FREE(smb_dname
);
2699 /****************************************************************************
2700 Reply to a TRANS2_FINDNEXT.
2701 ****************************************************************************/
2703 static void call_trans2findnext(connection_struct
*conn
,
2704 struct smb_request
*req
,
2705 char **pparams
, int total_params
,
2706 char **ppdata
, int total_data
,
2707 unsigned int max_data_bytes
)
2709 /* We must be careful here that we don't return more than the
2710 allowed number of data bytes. If this means returning fewer than
2711 maxentries then so be it. We assume that the redirector has
2712 enough room for the fixed number of parameter bytes it has
2714 char *params
= *pparams
;
2715 char *pdata
= *ppdata
;
2721 uint16 findnext_flags
;
2722 bool close_after_request
;
2724 bool requires_resume_key
;
2726 bool mask_contains_wcard
= False
;
2727 char *resume_name
= NULL
;
2728 const char *mask
= NULL
;
2729 const char *directory
= NULL
;
2733 int i
, last_entry_off
=0;
2734 bool finished
= False
;
2735 bool dont_descend
= False
;
2736 bool out_of_space
= False
;
2737 int space_remaining
;
2738 struct ea_list
*ea_list
= NULL
;
2739 NTSTATUS ntstatus
= NT_STATUS_OK
;
2740 bool ask_sharemode
= lp_parm_bool(SNUM(conn
), "smbd", "search ask sharemode", true);
2741 TALLOC_CTX
*ctx
= talloc_tos();
2742 struct dptr_struct
*dirptr
;
2743 struct smbd_server_connection
*sconn
= req
->sconn
;
2744 bool backup_priv
= false;
2746 if (total_params
< 13) {
2747 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2751 dptr_num
= SVAL(params
,0);
2752 maxentries
= SVAL(params
,2);
2753 info_level
= SVAL(params
,4);
2754 resume_key
= IVAL(params
,6);
2755 findnext_flags
= SVAL(params
,10);
2756 close_after_request
= (findnext_flags
& FLAG_TRANS2_FIND_CLOSE
);
2757 close_if_end
= (findnext_flags
& FLAG_TRANS2_FIND_CLOSE_IF_END
);
2758 requires_resume_key
= (findnext_flags
& FLAG_TRANS2_FIND_REQUIRE_RESUME
);
2759 continue_bit
= (findnext_flags
& FLAG_TRANS2_FIND_CONTINUE
);
2761 if (!continue_bit
) {
2762 /* We only need resume_name if continue_bit is zero. */
2763 srvstr_get_path_wcard(ctx
, params
, req
->flags2
, &resume_name
,
2765 total_params
- 12, STR_TERMINATE
, &ntstatus
,
2766 &mask_contains_wcard
);
2767 if (!NT_STATUS_IS_OK(ntstatus
)) {
2768 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2769 complain (it thinks we're asking for the directory above the shared
2770 path or an invalid name). Catch this as the resume name is only compared, never used in
2771 a file access. JRA. */
2772 srvstr_pull_talloc(ctx
, params
, req
->flags2
,
2773 &resume_name
, params
+12,
2777 if (!resume_name
|| !(ISDOT(resume_name
) || ISDOTDOT(resume_name
))) {
2778 reply_nterror(req
, ntstatus
);
2784 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2785 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2786 resume_key = %d resume name = %s continue=%d level = %d\n",
2787 dptr_num
, max_data_bytes
, maxentries
, close_after_request
, close_if_end
,
2788 requires_resume_key
, resume_key
,
2789 resume_name
? resume_name
: "(NULL)", continue_bit
, info_level
));
2792 /* W2K3 seems to treat zero as 1. */
2796 switch (info_level
) {
2797 case SMB_FIND_INFO_STANDARD
:
2798 case SMB_FIND_EA_SIZE
:
2799 case SMB_FIND_EA_LIST
:
2800 case SMB_FIND_FILE_DIRECTORY_INFO
:
2801 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
2802 case SMB_FIND_FILE_NAMES_INFO
:
2803 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
2804 case SMB_FIND_ID_FULL_DIRECTORY_INFO
:
2805 case SMB_FIND_ID_BOTH_DIRECTORY_INFO
:
2807 case SMB_FIND_FILE_UNIX
:
2808 case SMB_FIND_FILE_UNIX_INFO2
:
2809 /* Always use filesystem for UNIX mtime query. */
2810 ask_sharemode
= false;
2811 if (!lp_unix_extensions()) {
2812 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2817 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2821 if (info_level
== SMB_FIND_EA_LIST
) {
2824 if (total_data
< 4) {
2825 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2829 ea_size
= IVAL(pdata
,0);
2830 if (ea_size
!= total_data
) {
2831 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2832 total_data=%u (should be %u)\n", (unsigned int)total_data
, (unsigned int)IVAL(pdata
,0) ));
2833 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2837 if (!lp_ea_support(SNUM(conn
))) {
2838 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
2842 /* Pull out the list of names. */
2843 ea_list
= read_ea_name_list(ctx
, pdata
+ 4, ea_size
- 4);
2845 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2850 if (max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
< max_data_bytes
) {
2851 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2855 *ppdata
= (char *)SMB_REALLOC(
2856 *ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
2857 if(*ppdata
== NULL
) {
2858 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2863 data_end
= pdata
+ max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
- 1;
2865 /* Realloc the params space */
2866 *pparams
= (char *)SMB_REALLOC(*pparams
, 6*SIZEOFWORD
);
2867 if(*pparams
== NULL
) {
2868 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2874 /* Check that the dptr is valid */
2875 if(!(dirptr
= dptr_fetch_lanman2(sconn
, dptr_num
))) {
2876 reply_nterror(req
, STATUS_NO_MORE_FILES
);
2880 directory
= dptr_path(sconn
, dptr_num
);
2882 /* Get the wildcard mask from the dptr */
2883 if((mask
= dptr_wcard(sconn
, dptr_num
))== NULL
) {
2884 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num
));
2885 reply_nterror(req
, STATUS_NO_MORE_FILES
);
2889 /* Get the attr mask from the dptr */
2890 dirtype
= dptr_attr(sconn
, dptr_num
);
2892 backup_priv
= dptr_get_priv(dirptr
);
2894 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld) "
2895 "backup_priv = %d\n",
2896 dptr_num
, mask
, dirtype
,
2898 dptr_TellDir(dirptr
),
2901 /* Initialize per TRANS2_FIND_NEXT operation data */
2902 dptr_init_search_op(dirptr
);
2904 /* We don't need to check for VOL here as this is returned by
2905 a different TRANS2 call. */
2907 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2908 directory
,lp_dont_descend(ctx
, SNUM(conn
))));
2909 if (in_list(directory
,lp_dont_descend(ctx
, SNUM(conn
)),conn
->case_sensitive
))
2910 dont_descend
= True
;
2913 space_remaining
= max_data_bytes
;
2914 out_of_space
= False
;
2921 * Seek to the correct position. We no longer use the resume key but
2922 * depend on the last file name instead.
2925 if(!continue_bit
&& resume_name
&& *resume_name
) {
2928 long current_pos
= 0;
2930 * Remember, name_to_8_3 is called by
2931 * get_lanman2_dir_entry(), so the resume name
2932 * could be mangled. Ensure we check the unmangled name.
2935 if (mangle_is_mangled(resume_name
, conn
->params
)) {
2936 char *new_resume_name
= NULL
;
2937 mangle_lookup_name_from_8_3(ctx
,
2941 if (new_resume_name
) {
2942 resume_name
= new_resume_name
;
2947 * Fix for NT redirector problem triggered by resume key indexes
2948 * changing between directory scans. We now return a resume key of 0
2949 * and instead look for the filename to continue from (also given
2950 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2951 * findfirst/findnext (as is usual) then the directory pointer
2952 * should already be at the correct place.
2955 finished
= !dptr_SearchDir(dirptr
, resume_name
, ¤t_pos
, &st
);
2956 } /* end if resume_name && !continue_bit */
2958 for (i
=0;(i
<(int)maxentries
) && !finished
&& !out_of_space
;i
++) {
2959 bool got_exact_match
= False
;
2961 /* this is a heuristic to avoid seeking the dirptr except when
2962 absolutely necessary. It allows for a filename of about 40 chars */
2963 if (space_remaining
< DIRLEN_GUESS
&& numentries
> 0) {
2964 out_of_space
= True
;
2967 finished
= !get_lanman2_dir_entry(ctx
,
2971 mask
,dirtype
,info_level
,
2972 requires_resume_key
,dont_descend
,
2975 space_remaining
, &out_of_space
,
2977 &last_entry_off
, ea_list
);
2980 if (finished
&& out_of_space
)
2983 if (!finished
&& !out_of_space
)
2987 * As an optimisation if we know we aren't looking
2988 * for a wildcard name (ie. the name matches the wildcard exactly)
2989 * then we can finish on any (first) match.
2990 * This speeds up large directory searches. JRA.
2996 space_remaining
= max_data_bytes
- PTR_DIFF(p
,pdata
);
2999 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
3000 smb_fn_name(req
->cmd
),
3001 mask
, directory
, dirtype
, numentries
) );
3003 /* Check if we can close the dirptr */
3004 if(close_after_request
|| (finished
&& close_if_end
)) {
3005 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num
));
3006 dptr_close(sconn
, &dptr_num
); /* This frees up the saved mask */
3013 /* Set up the return parameter block */
3014 SSVAL(params
,0,numentries
);
3015 SSVAL(params
,2,finished
);
3016 SSVAL(params
,4,0); /* Never an EA error */
3017 SSVAL(params
,6,last_entry_off
);
3019 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 8, pdata
, PTR_DIFF(p
,pdata
),
3025 unsigned char *create_volume_objectid(connection_struct
*conn
, unsigned char objid
[16])
3027 E_md4hash(lp_servicename(talloc_tos(), SNUM(conn
)),objid
);
3031 static void samba_extended_info_version(struct smb_extended_info
*extended_info
)
3033 SMB_ASSERT(extended_info
!= NULL
);
3035 extended_info
->samba_magic
= SAMBA_EXTENDED_INFO_MAGIC
;
3036 extended_info
->samba_version
= ((SAMBA_VERSION_MAJOR
& 0xff) << 24)
3037 | ((SAMBA_VERSION_MINOR
& 0xff) << 16)
3038 | ((SAMBA_VERSION_RELEASE
& 0xff) << 8);
3039 #ifdef SAMBA_VERSION_REVISION
3040 extended_info
->samba_version
|= (tolower(*SAMBA_VERSION_REVISION
) - 'a' + 1) & 0xff;
3042 extended_info
->samba_subversion
= 0;
3043 #ifdef SAMBA_VERSION_RC_RELEASE
3044 extended_info
->samba_subversion
|= (SAMBA_VERSION_RC_RELEASE
& 0xff) << 24;
3046 #ifdef SAMBA_VERSION_PRE_RELEASE
3047 extended_info
->samba_subversion
|= (SAMBA_VERSION_PRE_RELEASE
& 0xff) << 16;
3050 #ifdef SAMBA_VERSION_VENDOR_PATCH
3051 extended_info
->samba_subversion
|= (SAMBA_VERSION_VENDOR_PATCH
& 0xffff);
3053 extended_info
->samba_gitcommitdate
= 0;
3054 #ifdef SAMBA_VERSION_COMMIT_TIME
3055 unix_to_nt_time(&extended_info
->samba_gitcommitdate
, SAMBA_VERSION_COMMIT_TIME
);
3058 memset(extended_info
->samba_version_string
, 0,
3059 sizeof(extended_info
->samba_version_string
));
3061 snprintf (extended_info
->samba_version_string
,
3062 sizeof(extended_info
->samba_version_string
),
3063 "%s", samba_version_string());
3066 NTSTATUS
smbd_do_qfsinfo(connection_struct
*conn
,
3067 TALLOC_CTX
*mem_ctx
,
3068 uint16_t info_level
,
3070 unsigned int max_data_bytes
,
3071 size_t *fixed_portion
,
3072 struct smb_filename
*fname
,
3076 char *pdata
, *end_data
;
3077 int data_len
= 0, len
;
3078 const char *vname
= volume_label(talloc_tos(), SNUM(conn
));
3079 int snum
= SNUM(conn
);
3080 const char *fstype
= lp_fstype(SNUM(conn
));
3081 const char *filename
= NULL
;
3082 uint32 additional_flags
= 0;
3083 struct smb_filename smb_fname
;
3085 NTSTATUS status
= NT_STATUS_OK
;
3087 if (fname
== NULL
|| fname
->base_name
== NULL
) {
3090 filename
= fname
->base_name
;
3094 if (info_level
!= SMB_QUERY_CIFS_UNIX_INFO
) {
3095 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
3096 "info level (0x%x) on IPC$.\n",
3097 (unsigned int)info_level
));
3098 return NT_STATUS_ACCESS_DENIED
;
3102 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level
));
3104 ZERO_STRUCT(smb_fname
);
3105 smb_fname
.base_name
= discard_const_p(char, filename
);
3107 if(SMB_VFS_STAT(conn
, &smb_fname
) != 0) {
3108 DEBUG(2,("stat of . failed (%s)\n", strerror(errno
)));
3109 return map_nt_error_from_unix(errno
);
3114 if (max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
< max_data_bytes
) {
3115 return NT_STATUS_INVALID_PARAMETER
;
3118 *ppdata
= (char *)SMB_REALLOC(
3119 *ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
3120 if (*ppdata
== NULL
) {
3121 return NT_STATUS_NO_MEMORY
;
3125 memset((char *)pdata
,'\0',max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
3126 end_data
= pdata
+ max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
- 1;
3130 switch (info_level
) {
3131 case SMB_INFO_ALLOCATION
:
3133 uint64_t dfree
,dsize
,bsize
,block_size
,sectors_per_unit
,bytes_per_sector
;
3135 if (get_dfree_info(conn
,filename
,False
,&bsize
,&dfree
,&dsize
) == (uint64_t)-1) {
3136 return map_nt_error_from_unix(errno
);
3139 block_size
= lp_block_size(snum
);
3140 if (bsize
< block_size
) {
3141 uint64_t factor
= block_size
/bsize
;
3146 if (bsize
> block_size
) {
3147 uint64_t factor
= bsize
/block_size
;
3152 bytes_per_sector
= 512;
3153 sectors_per_unit
= bsize
/bytes_per_sector
;
3155 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
3156 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st
.st_ex_dev
, (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
3157 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
3159 SIVAL(pdata
,l1_idFileSystem
,st
.st_ex_dev
);
3160 SIVAL(pdata
,l1_cSectorUnit
,sectors_per_unit
);
3161 SIVAL(pdata
,l1_cUnit
,dsize
);
3162 SIVAL(pdata
,l1_cUnitAvail
,dfree
);
3163 SSVAL(pdata
,l1_cbSector
,bytes_per_sector
);
3167 case SMB_INFO_VOLUME
:
3168 /* Return volume name */
3170 * Add volume serial number - hash of a combination of
3171 * the called hostname and the service name.
3173 SIVAL(pdata
,0,str_checksum(lp_servicename(talloc_tos(), snum
)) ^ (str_checksum(get_local_machine_name())<<16) );
3175 * Win2k3 and previous mess this up by sending a name length
3176 * one byte short. I believe only older clients (OS/2 Win9x) use
3177 * this call so try fixing this by adding a terminating null to
3178 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
3182 pdata
+l2_vol_szVolLabel
, vname
,
3183 PTR_DIFF(end_data
, pdata
+l2_vol_szVolLabel
),
3184 STR_NOALIGN
|STR_TERMINATE
);
3185 SCVAL(pdata
,l2_vol_cch
,len
);
3186 data_len
= l2_vol_szVolLabel
+ len
;
3187 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %d, name = %s\n",
3188 (unsigned)convert_timespec_to_time_t(st
.st_ex_ctime
),
3192 case SMB_QUERY_FS_ATTRIBUTE_INFO
:
3193 case SMB_FS_ATTRIBUTE_INFORMATION
:
3195 additional_flags
= 0;
3196 #if defined(HAVE_SYS_QUOTAS)
3197 additional_flags
|= FILE_VOLUME_QUOTAS
;
3200 if(lp_nt_acl_support(SNUM(conn
))) {
3201 additional_flags
|= FILE_PERSISTENT_ACLS
;
3204 /* Capabilities are filled in at connection time through STATVFS call */
3205 additional_flags
|= conn
->fs_capabilities
;
3206 additional_flags
|= lp_parm_int(conn
->params
->service
,
3207 "share", "fake_fscaps",
3210 SIVAL(pdata
,0,FILE_CASE_PRESERVED_NAMES
|FILE_CASE_SENSITIVE_SEARCH
|
3211 FILE_SUPPORTS_OBJECT_IDS
|FILE_UNICODE_ON_DISK
|
3212 additional_flags
); /* FS ATTRIBUTES */
3214 SIVAL(pdata
,4,255); /* Max filename component length */
3215 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
3216 and will think we can't do long filenames */
3217 len
= srvstr_push(pdata
, flags2
, pdata
+12, fstype
,
3218 PTR_DIFF(end_data
, pdata
+12),
3221 data_len
= 12 + len
;
3222 if (max_data_bytes
>= 16 && data_len
> max_data_bytes
) {
3223 /* the client only requested a portion of the
3225 data_len
= max_data_bytes
;
3226 status
= STATUS_BUFFER_OVERFLOW
;
3228 *fixed_portion
= 16;
3231 case SMB_QUERY_FS_LABEL_INFO
:
3232 case SMB_FS_LABEL_INFORMATION
:
3233 len
= srvstr_push(pdata
, flags2
, pdata
+4, vname
,
3234 PTR_DIFF(end_data
, pdata
+4), 0);
3239 case SMB_QUERY_FS_VOLUME_INFO
:
3240 case SMB_FS_VOLUME_INFORMATION
:
3243 * Add volume serial number - hash of a combination of
3244 * the called hostname and the service name.
3246 SIVAL(pdata
,8,str_checksum(lp_servicename(talloc_tos(), snum
)) ^
3247 (str_checksum(get_local_machine_name())<<16));
3249 /* Max label len is 32 characters. */
3250 len
= srvstr_push(pdata
, flags2
, pdata
+18, vname
,
3251 PTR_DIFF(end_data
, pdata
+18),
3253 SIVAL(pdata
,12,len
);
3256 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3257 (int)strlen(vname
),vname
,
3258 lp_servicename(talloc_tos(), snum
)));
3259 if (max_data_bytes
>= 24 && data_len
> max_data_bytes
) {
3260 /* the client only requested a portion of the
3262 data_len
= max_data_bytes
;
3263 status
= STATUS_BUFFER_OVERFLOW
;
3265 *fixed_portion
= 24;
3268 case SMB_QUERY_FS_SIZE_INFO
:
3269 case SMB_FS_SIZE_INFORMATION
:
3271 uint64_t dfree
,dsize
,bsize
,block_size
,sectors_per_unit
,bytes_per_sector
;
3273 if (get_dfree_info(conn
,filename
,False
,&bsize
,&dfree
,&dsize
) == (uint64_t)-1) {
3274 return map_nt_error_from_unix(errno
);
3276 block_size
= lp_block_size(snum
);
3277 if (bsize
< block_size
) {
3278 uint64_t factor
= block_size
/bsize
;
3283 if (bsize
> block_size
) {
3284 uint64_t factor
= bsize
/block_size
;
3289 bytes_per_sector
= 512;
3290 sectors_per_unit
= bsize
/bytes_per_sector
;
3291 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3292 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
3293 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
3294 SBIG_UINT(pdata
,0,dsize
);
3295 SBIG_UINT(pdata
,8,dfree
);
3296 SIVAL(pdata
,16,sectors_per_unit
);
3297 SIVAL(pdata
,20,bytes_per_sector
);
3298 *fixed_portion
= 24;
3302 case SMB_FS_FULL_SIZE_INFORMATION
:
3304 uint64_t dfree
,dsize
,bsize
,block_size
,sectors_per_unit
,bytes_per_sector
;
3306 if (get_dfree_info(conn
,filename
,False
,&bsize
,&dfree
,&dsize
) == (uint64_t)-1) {
3307 return map_nt_error_from_unix(errno
);
3309 block_size
= lp_block_size(snum
);
3310 if (bsize
< block_size
) {
3311 uint64_t factor
= block_size
/bsize
;
3316 if (bsize
> block_size
) {
3317 uint64_t factor
= bsize
/block_size
;
3322 bytes_per_sector
= 512;
3323 sectors_per_unit
= bsize
/bytes_per_sector
;
3324 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3325 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
3326 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
3327 SBIG_UINT(pdata
,0,dsize
); /* Total Allocation units. */
3328 SBIG_UINT(pdata
,8,dfree
); /* Caller available allocation units. */
3329 SBIG_UINT(pdata
,16,dfree
); /* Actual available allocation units. */
3330 SIVAL(pdata
,24,sectors_per_unit
); /* Sectors per allocation unit. */
3331 SIVAL(pdata
,28,bytes_per_sector
); /* Bytes per sector. */
3332 *fixed_portion
= 32;
3336 case SMB_QUERY_FS_DEVICE_INFO
:
3337 case SMB_FS_DEVICE_INFORMATION
:
3339 uint32_t characteristics
= FILE_DEVICE_IS_MOUNTED
;
3341 if (!CAN_WRITE(conn
)) {
3342 characteristics
|= FILE_READ_ONLY_DEVICE
;
3345 SIVAL(pdata
,0,FILE_DEVICE_DISK
); /* dev type */
3346 SIVAL(pdata
,4,characteristics
);
3351 #ifdef HAVE_SYS_QUOTAS
3352 case SMB_FS_QUOTA_INFORMATION
:
3354 * what we have to send --metze:
3356 * Unknown1: 24 NULL bytes
3357 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3358 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3359 * Quota Flags: 2 byte :
3360 * Unknown3: 6 NULL bytes
3364 * details for Quota Flags:
3366 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3367 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3368 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3369 * 0x0001 Enable Quotas: enable quota for this fs
3373 /* we need to fake up a fsp here,
3374 * because its not send in this call
3377 SMB_NTQUOTA_STRUCT quotas
;
3380 ZERO_STRUCT(quotas
);
3383 fsp
.fnum
= FNUM_FIELD_INVALID
;
3386 if (get_current_uid(conn
) != 0) {
3387 DEBUG(0,("get_user_quota: access_denied "
3388 "service [%s] user [%s]\n",
3389 lp_servicename(talloc_tos(), SNUM(conn
)),
3390 conn
->session_info
->unix_info
->unix_name
));
3391 return NT_STATUS_ACCESS_DENIED
;
3394 if (vfs_get_ntquota(&fsp
, SMB_USER_FS_QUOTA_TYPE
, NULL
, "as
)!=0) {
3395 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn
))));
3396 return map_nt_error_from_unix(errno
);
3401 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3402 lp_servicename(talloc_tos(), SNUM(conn
))));
3404 /* Unknown1 24 NULL bytes*/
3405 SBIG_UINT(pdata
,0,(uint64_t)0);
3406 SBIG_UINT(pdata
,8,(uint64_t)0);
3407 SBIG_UINT(pdata
,16,(uint64_t)0);
3409 /* Default Soft Quota 8 bytes */
3410 SBIG_UINT(pdata
,24,quotas
.softlim
);
3412 /* Default Hard Quota 8 bytes */
3413 SBIG_UINT(pdata
,32,quotas
.hardlim
);
3415 /* Quota flag 2 bytes */
3416 SSVAL(pdata
,40,quotas
.qflags
);
3418 /* Unknown3 6 NULL bytes */
3424 #endif /* HAVE_SYS_QUOTAS */
3425 case SMB_FS_OBJECTID_INFORMATION
:
3427 unsigned char objid
[16];
3428 struct smb_extended_info extended_info
;
3429 memcpy(pdata
,create_volume_objectid(conn
, objid
),16);
3430 samba_extended_info_version (&extended_info
);
3431 SIVAL(pdata
,16,extended_info
.samba_magic
);
3432 SIVAL(pdata
,20,extended_info
.samba_version
);
3433 SIVAL(pdata
,24,extended_info
.samba_subversion
);
3434 SBIG_UINT(pdata
,28,extended_info
.samba_gitcommitdate
);
3435 memcpy(pdata
+36,extended_info
.samba_version_string
,28);
3441 * Query the version and capabilities of the CIFS UNIX extensions
3445 case SMB_QUERY_CIFS_UNIX_INFO
:
3447 bool large_write
= lp_min_receive_file_size() &&
3448 !srv_is_signing_active(conn
->sconn
);
3449 bool large_read
= !srv_is_signing_active(conn
->sconn
);
3450 int encrypt_caps
= 0;
3452 if (!lp_unix_extensions()) {
3453 return NT_STATUS_INVALID_LEVEL
;
3456 switch (conn
->encrypt_level
) {
3457 case SMB_SIGNING_OFF
:
3460 case SMB_SIGNING_IF_REQUIRED
:
3461 case SMB_SIGNING_DEFAULT
:
3462 encrypt_caps
= CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP
;
3464 case SMB_SIGNING_REQUIRED
:
3465 encrypt_caps
= CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP
|
3466 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP
;
3467 large_write
= false;
3473 SSVAL(pdata
,0,CIFS_UNIX_MAJOR_VERSION
);
3474 SSVAL(pdata
,2,CIFS_UNIX_MINOR_VERSION
);
3476 /* We have POSIX ACLs, pathname, encryption,
3477 * large read/write, and locking capability. */
3479 SBIG_UINT(pdata
,4,((uint64_t)(
3480 CIFS_UNIX_POSIX_ACLS_CAP
|
3481 CIFS_UNIX_POSIX_PATHNAMES_CAP
|
3482 CIFS_UNIX_FCNTL_LOCKS_CAP
|
3483 CIFS_UNIX_EXTATTR_CAP
|
3484 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP
|
3486 (large_read
? CIFS_UNIX_LARGE_READ_CAP
: 0) |
3488 CIFS_UNIX_LARGE_WRITE_CAP
: 0))));
3492 case SMB_QUERY_POSIX_FS_INFO
:
3495 vfs_statvfs_struct svfs
;
3497 if (!lp_unix_extensions()) {
3498 return NT_STATUS_INVALID_LEVEL
;
3501 rc
= SMB_VFS_STATVFS(conn
, filename
, &svfs
);
3505 SIVAL(pdata
,0,svfs
.OptimalTransferSize
);
3506 SIVAL(pdata
,4,svfs
.BlockSize
);
3507 SBIG_UINT(pdata
,8,svfs
.TotalBlocks
);
3508 SBIG_UINT(pdata
,16,svfs
.BlocksAvail
);
3509 SBIG_UINT(pdata
,24,svfs
.UserBlocksAvail
);
3510 SBIG_UINT(pdata
,32,svfs
.TotalFileNodes
);
3511 SBIG_UINT(pdata
,40,svfs
.FreeFileNodes
);
3512 SBIG_UINT(pdata
,48,svfs
.FsIdentifier
);
3513 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3515 } else if (rc
== EOPNOTSUPP
) {
3516 return NT_STATUS_INVALID_LEVEL
;
3517 #endif /* EOPNOTSUPP */
3519 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn
))));
3520 return NT_STATUS_DOS(ERRSRV
, ERRerror
);
3525 case SMB_QUERY_POSIX_WHOAMI
:
3531 if (!lp_unix_extensions()) {
3532 return NT_STATUS_INVALID_LEVEL
;
3535 if (max_data_bytes
< 40) {
3536 return NT_STATUS_BUFFER_TOO_SMALL
;
3539 if (security_session_user_level(conn
->session_info
, NULL
) < SECURITY_USER
) {
3540 flags
|= SMB_WHOAMI_GUEST
;
3543 /* NOTE: 8 bytes for UID/GID, irrespective of native
3544 * platform size. This matches
3545 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3547 data_len
= 4 /* flags */
3554 + 4 /* pad/reserved */
3555 + (conn
->session_info
->unix_token
->ngroups
* 8)
3557 + (conn
->session_info
->security_token
->num_sids
*
3561 SIVAL(pdata
, 0, flags
);
3562 SIVAL(pdata
, 4, SMB_WHOAMI_MASK
);
3564 (uint64_t)conn
->session_info
->unix_token
->uid
);
3565 SBIG_UINT(pdata
, 16,
3566 (uint64_t)conn
->session_info
->unix_token
->gid
);
3569 if (data_len
>= max_data_bytes
) {
3570 /* Potential overflow, skip the GIDs and SIDs. */
3572 SIVAL(pdata
, 24, 0); /* num_groups */
3573 SIVAL(pdata
, 28, 0); /* num_sids */
3574 SIVAL(pdata
, 32, 0); /* num_sid_bytes */
3575 SIVAL(pdata
, 36, 0); /* reserved */
3581 SIVAL(pdata
, 24, conn
->session_info
->unix_token
->ngroups
);
3582 SIVAL(pdata
, 28, conn
->session_info
->security_token
->num_sids
);
3584 /* We walk the SID list twice, but this call is fairly
3585 * infrequent, and I don't expect that it's performance
3586 * sensitive -- jpeach
3588 for (i
= 0, sid_bytes
= 0;
3589 i
< conn
->session_info
->security_token
->num_sids
; ++i
) {
3590 sid_bytes
+= ndr_size_dom_sid(
3591 &conn
->session_info
->security_token
->sids
[i
],
3595 /* SID list byte count */
3596 SIVAL(pdata
, 32, sid_bytes
);
3598 /* 4 bytes pad/reserved - must be zero */
3599 SIVAL(pdata
, 36, 0);
3603 for (i
= 0; i
< conn
->session_info
->unix_token
->ngroups
; ++i
) {
3604 SBIG_UINT(pdata
, data_len
,
3605 (uint64_t)conn
->session_info
->unix_token
->groups
[i
]);
3611 i
< conn
->session_info
->security_token
->num_sids
; ++i
) {
3612 int sid_len
= ndr_size_dom_sid(
3613 &conn
->session_info
->security_token
->sids
[i
],
3616 sid_linearize(pdata
+ data_len
, sid_len
,
3617 &conn
->session_info
->security_token
->sids
[i
]);
3618 data_len
+= sid_len
;
3624 case SMB_MAC_QUERY_FS_INFO
:
3626 * Thursby MAC extension... ONLY on NTFS filesystems
3627 * once we do streams then we don't need this
3629 if (strequal(lp_fstype(SNUM(conn
)),"NTFS")) {
3631 SIVAL(pdata
,84,0x100); /* Don't support mac... */
3636 return NT_STATUS_INVALID_LEVEL
;
3639 *ret_data_len
= data_len
;
3643 /****************************************************************************
3644 Reply to a TRANS2_QFSINFO (query filesystem info).
3645 ****************************************************************************/
3647 static void call_trans2qfsinfo(connection_struct
*conn
,
3648 struct smb_request
*req
,
3649 char **pparams
, int total_params
,
3650 char **ppdata
, int total_data
,
3651 unsigned int max_data_bytes
)
3653 char *params
= *pparams
;
3654 uint16_t info_level
;
3656 size_t fixed_portion
;
3659 if (total_params
< 2) {
3660 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3664 info_level
= SVAL(params
,0);
3666 if (ENCRYPTION_REQUIRED(conn
) && !req
->encrypted
) {
3667 if (info_level
!= SMB_QUERY_CIFS_UNIX_INFO
) {
3668 DEBUG(0,("call_trans2qfsinfo: encryption required "
3669 "and info level 0x%x sent.\n",
3670 (unsigned int)info_level
));
3671 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3676 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level
));
3678 status
= smbd_do_qfsinfo(conn
, req
,
3685 if (!NT_STATUS_IS_OK(status
)) {
3686 reply_nterror(req
, status
);
3690 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 0, *ppdata
, data_len
,
3693 DEBUG( 4, ( "%s info_level = %d\n",
3694 smb_fn_name(req
->cmd
), info_level
) );
3699 /****************************************************************************
3700 Reply to a TRANS2_SETFSINFO (set filesystem info).
3701 ****************************************************************************/
3703 static void call_trans2setfsinfo(connection_struct
*conn
,
3704 struct smb_request
*req
,
3705 char **pparams
, int total_params
,
3706 char **ppdata
, int total_data
,
3707 unsigned int max_data_bytes
)
3709 struct smbd_server_connection
*sconn
= req
->sconn
;
3710 char *pdata
= *ppdata
;
3711 char *params
= *pparams
;
3714 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",
3715 lp_servicename(talloc_tos(), SNUM(conn
))));
3718 if (total_params
< 4) {
3719 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3721 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3725 info_level
= SVAL(params
,2);
3728 if (info_level
!= SMB_REQUEST_TRANSPORT_ENCRYPTION
&&
3729 info_level
!= SMB_SET_CIFS_UNIX_INFO
) {
3730 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3731 "info level (0x%x) on IPC$.\n",
3732 (unsigned int)info_level
));
3733 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3738 if (ENCRYPTION_REQUIRED(conn
) && !req
->encrypted
) {
3739 if (info_level
!= SMB_REQUEST_TRANSPORT_ENCRYPTION
) {
3740 DEBUG(0,("call_trans2setfsinfo: encryption required "
3741 "and info level 0x%x sent.\n",
3742 (unsigned int)info_level
));
3743 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3748 switch(info_level
) {
3749 case SMB_SET_CIFS_UNIX_INFO
:
3750 if (!lp_unix_extensions()) {
3751 DEBUG(2,("call_trans2setfsinfo: "
3752 "SMB_SET_CIFS_UNIX_INFO is invalid with "
3753 "unix extensions off\n"));
3755 NT_STATUS_INVALID_LEVEL
);
3759 /* There should be 12 bytes of capabilities set. */
3760 if (total_data
< 12) {
3763 NT_STATUS_INVALID_PARAMETER
);
3766 sconn
->smb1
.unix_info
.client_major
= SVAL(pdata
,0);
3767 sconn
->smb1
.unix_info
.client_minor
= SVAL(pdata
,2);
3768 sconn
->smb1
.unix_info
.client_cap_low
= IVAL(pdata
,4);
3769 sconn
->smb1
.unix_info
.client_cap_high
= IVAL(pdata
,8);
3770 /* Just print these values for now. */
3771 DEBUG(10, ("call_trans2setfsinfo: set unix_info info. "
3772 "major = %u, minor = %u cap_low = 0x%x, "
3774 (unsigned int)sconn
->
3775 smb1
.unix_info
.client_major
,
3776 (unsigned int)sconn
->
3777 smb1
.unix_info
.client_minor
,
3778 (unsigned int)sconn
->
3779 smb1
.unix_info
.client_cap_low
,
3780 (unsigned int)sconn
->
3781 smb1
.unix_info
.client_cap_high
));
3783 /* Here is where we must switch to posix pathname processing... */
3784 if (sconn
->smb1
.unix_info
.client_cap_low
& CIFS_UNIX_POSIX_PATHNAMES_CAP
) {
3785 lp_set_posix_pathnames();
3786 mangle_change_to_posix();
3789 if ((sconn
->smb1
.unix_info
.client_cap_low
& CIFS_UNIX_FCNTL_LOCKS_CAP
) &&
3790 !(sconn
->smb1
.unix_info
.client_cap_low
& CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP
)) {
3791 /* Client that knows how to do posix locks,
3792 * but not posix open/mkdir operations. Set a
3793 * default type for read/write checks. */
3795 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK
);
3800 case SMB_REQUEST_TRANSPORT_ENCRYPTION
:
3803 size_t param_len
= 0;
3804 size_t data_len
= total_data
;
3806 if (!lp_unix_extensions()) {
3809 NT_STATUS_INVALID_LEVEL
);
3813 if (lp_smb_encrypt(SNUM(conn
)) == SMB_SIGNING_OFF
) {
3816 NT_STATUS_NOT_SUPPORTED
);
3820 if (req
->sconn
->smb1
.echo_handler
.trusted_fde
) {
3821 DEBUG( 2,("call_trans2setfsinfo: "
3822 "request transport encryption disabled"
3823 "with 'fork echo handler = yes'\n"));
3826 NT_STATUS_NOT_SUPPORTED
);
3830 DEBUG( 4,("call_trans2setfsinfo: "
3831 "request transport encryption.\n"));
3833 status
= srv_request_encryption_setup(conn
,
3834 (unsigned char **)ppdata
,
3836 (unsigned char **)pparams
,
3839 if (!NT_STATUS_EQUAL(status
, NT_STATUS_MORE_PROCESSING_REQUIRED
) &&
3840 !NT_STATUS_IS_OK(status
)) {
3841 reply_nterror(req
, status
);
3845 send_trans2_replies(conn
, req
,
3853 if (NT_STATUS_IS_OK(status
)) {
3854 /* Server-side transport
3855 * encryption is now *on*. */
3856 status
= srv_encryption_start(conn
);
3857 if (!NT_STATUS_IS_OK(status
)) {
3858 char *reason
= talloc_asprintf(talloc_tos(),
3859 "Failure in setting "
3860 "up encrypted transport: %s",
3862 exit_server_cleanly(reason
);
3868 case SMB_FS_QUOTA_INFORMATION
:
3870 files_struct
*fsp
= NULL
;
3871 SMB_NTQUOTA_STRUCT quotas
;
3873 ZERO_STRUCT(quotas
);
3876 if ((get_current_uid(conn
) != 0) || !CAN_WRITE(conn
)) {
3877 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3878 lp_servicename(talloc_tos(), SNUM(conn
)),
3879 conn
->session_info
->unix_info
->unix_name
));
3880 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3884 /* note: normaly there're 48 bytes,
3885 * but we didn't use the last 6 bytes for now
3888 fsp
= file_fsp(req
, SVAL(params
,0));
3890 if (!check_fsp_ntquota_handle(conn
, req
,
3892 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3894 req
, NT_STATUS_INVALID_HANDLE
);
3898 if (total_data
< 42) {
3899 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3903 NT_STATUS_INVALID_PARAMETER
);
3907 /* unknown_1 24 NULL bytes in pdata*/
3909 /* the soft quotas 8 bytes (uint64_t)*/
3910 quotas
.softlim
= BVAL(pdata
,24);
3912 /* the hard quotas 8 bytes (uint64_t)*/
3913 quotas
.hardlim
= BVAL(pdata
,32);
3915 /* quota_flags 2 bytes **/
3916 quotas
.qflags
= SVAL(pdata
,40);
3918 /* unknown_2 6 NULL bytes follow*/
3920 /* now set the quotas */
3921 if (vfs_set_ntquota(fsp
, SMB_USER_FS_QUOTA_TYPE
, NULL
, "as
)!=0) {
3922 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn
))));
3923 reply_nterror(req
, map_nt_error_from_unix(errno
));
3930 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3932 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
3938 * sending this reply works fine,
3939 * but I'm not sure it's the same
3940 * like windows do...
3943 reply_outbuf(req
, 10, 0);
3946 #if defined(HAVE_POSIX_ACLS)
3947 /****************************************************************************
3948 Utility function to count the number of entries in a POSIX acl.
3949 ****************************************************************************/
3951 static unsigned int count_acl_entries(connection_struct
*conn
, SMB_ACL_T posix_acl
)
3953 unsigned int ace_count
= 0;
3954 int entry_id
= SMB_ACL_FIRST_ENTRY
;
3955 SMB_ACL_ENTRY_T entry
;
3957 while ( posix_acl
&& (sys_acl_get_entry(posix_acl
, entry_id
, &entry
) == 1)) {
3959 if (entry_id
== SMB_ACL_FIRST_ENTRY
) {
3960 entry_id
= SMB_ACL_NEXT_ENTRY
;
3967 /****************************************************************************
3968 Utility function to marshall a POSIX acl into wire format.
3969 ****************************************************************************/
3971 static bool marshall_posix_acl(connection_struct
*conn
, char *pdata
, SMB_STRUCT_STAT
*pst
, SMB_ACL_T posix_acl
)
3973 int entry_id
= SMB_ACL_FIRST_ENTRY
;
3974 SMB_ACL_ENTRY_T entry
;
3976 while ( posix_acl
&& (sys_acl_get_entry(posix_acl
, entry_id
, &entry
) == 1)) {
3977 SMB_ACL_TAG_T tagtype
;
3978 SMB_ACL_PERMSET_T permset
;
3979 unsigned char perms
= 0;
3980 unsigned int own_grp
;
3983 if (entry_id
== SMB_ACL_FIRST_ENTRY
) {
3984 entry_id
= SMB_ACL_NEXT_ENTRY
;
3987 if (sys_acl_get_tag_type(entry
, &tagtype
) == -1) {
3988 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3992 if (sys_acl_get_permset(entry
, &permset
) == -1) {
3993 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3997 perms
|= (sys_acl_get_perm(permset
, SMB_ACL_READ
) ? SMB_POSIX_ACL_READ
: 0);
3998 perms
|= (sys_acl_get_perm(permset
, SMB_ACL_WRITE
) ? SMB_POSIX_ACL_WRITE
: 0);
3999 perms
|= (sys_acl_get_perm(permset
, SMB_ACL_EXECUTE
) ? SMB_POSIX_ACL_EXECUTE
: 0);
4001 SCVAL(pdata
,1,perms
);
4004 case SMB_ACL_USER_OBJ
:
4005 SCVAL(pdata
,0,SMB_POSIX_ACL_USER_OBJ
);
4006 own_grp
= (unsigned int)pst
->st_ex_uid
;
4007 SIVAL(pdata
,2,own_grp
);
4012 uid_t
*puid
= (uid_t
*)sys_acl_get_qualifier(entry
);
4014 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
4017 own_grp
= (unsigned int)*puid
;
4018 SCVAL(pdata
,0,SMB_POSIX_ACL_USER
);
4019 SIVAL(pdata
,2,own_grp
);
4023 case SMB_ACL_GROUP_OBJ
:
4024 SCVAL(pdata
,0,SMB_POSIX_ACL_GROUP_OBJ
);
4025 own_grp
= (unsigned int)pst
->st_ex_gid
;
4026 SIVAL(pdata
,2,own_grp
);
4031 gid_t
*pgid
= (gid_t
*)sys_acl_get_qualifier(entry
);
4033 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
4036 own_grp
= (unsigned int)*pgid
;
4037 SCVAL(pdata
,0,SMB_POSIX_ACL_GROUP
);
4038 SIVAL(pdata
,2,own_grp
);
4043 SCVAL(pdata
,0,SMB_POSIX_ACL_MASK
);
4044 SIVAL(pdata
,2,0xFFFFFFFF);
4045 SIVAL(pdata
,6,0xFFFFFFFF);
4048 SCVAL(pdata
,0,SMB_POSIX_ACL_OTHER
);
4049 SIVAL(pdata
,2,0xFFFFFFFF);
4050 SIVAL(pdata
,6,0xFFFFFFFF);
4053 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
4056 pdata
+= SMB_POSIX_ACL_ENTRY_SIZE
;
4063 /****************************************************************************
4064 Store the FILE_UNIX_BASIC info.
4065 ****************************************************************************/
4067 static char *store_file_unix_basic(connection_struct
*conn
,
4070 const SMB_STRUCT_STAT
*psbuf
)
4072 uint64_t file_index
= get_FileIndex(conn
, psbuf
);
4075 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
4076 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf
->st_ex_mode
));
4078 SOFF_T(pdata
,0,get_file_size_stat(psbuf
)); /* File size 64 Bit */
4081 SOFF_T(pdata
,0,SMB_VFS_GET_ALLOC_SIZE(conn
,fsp
,psbuf
)); /* Number of bytes used on disk - 64 Bit */
4084 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER
, pdata
, psbuf
->st_ex_ctime
); /* Change Time 64 Bit */
4085 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER
,pdata
+8, psbuf
->st_ex_atime
); /* Last access time 64 Bit */
4086 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER
, pdata
+16, psbuf
->st_ex_mtime
); /* Last modification time 64 Bit */
4089 SIVAL(pdata
,0,psbuf
->st_ex_uid
); /* user id for the owner */
4093 SIVAL(pdata
,0,psbuf
->st_ex_gid
); /* group id of owner */
4097 SIVAL(pdata
,0,unix_filetype(psbuf
->st_ex_mode
));
4100 if (S_ISBLK(psbuf
->st_ex_mode
) || S_ISCHR(psbuf
->st_ex_mode
)) {
4101 devno
= psbuf
->st_ex_rdev
;
4103 devno
= psbuf
->st_ex_dev
;
4106 SIVAL(pdata
,0,unix_dev_major(devno
)); /* Major device number if type is device */
4110 SIVAL(pdata
,0,unix_dev_minor(devno
)); /* Minor device number if type is device */
4114 SINO_T_VAL(pdata
,0,(SMB_INO_T
)file_index
); /* inode number */
4117 SIVAL(pdata
,0, unix_perms_to_wire(psbuf
->st_ex_mode
)); /* Standard UNIX file permissions */
4121 SIVAL(pdata
,0,psbuf
->st_ex_nlink
); /* number of hard links */
4128 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
4129 * the chflags(2) (or equivalent) flags.
4131 * XXX: this really should be behind the VFS interface. To do this, we would
4132 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
4133 * Each VFS module could then implement its own mapping as appropriate for the
4134 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
4136 static const struct {unsigned stat_fflag
; unsigned smb_fflag
;}
4140 { UF_NODUMP
, EXT_DO_NOT_BACKUP
},
4144 { UF_IMMUTABLE
, EXT_IMMUTABLE
},
4148 { UF_APPEND
, EXT_OPEN_APPEND_ONLY
},
4152 { UF_HIDDEN
, EXT_HIDDEN
},
4155 /* Do not remove. We need to guarantee that this array has at least one
4156 * entry to build on HP-UX.
4162 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT
*psbuf
,
4163 uint32
*smb_fflags
, uint32
*smb_fmask
)
4167 for (i
= 0; i
< ARRAY_SIZE(info2_flags_map
); ++i
) {
4168 *smb_fmask
|= info2_flags_map
[i
].smb_fflag
;
4169 if (psbuf
->st_ex_flags
& info2_flags_map
[i
].stat_fflag
) {
4170 *smb_fflags
|= info2_flags_map
[i
].smb_fflag
;
4175 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT
*psbuf
,
4176 const uint32 smb_fflags
,
4177 const uint32 smb_fmask
,
4180 uint32 max_fmask
= 0;
4183 *stat_fflags
= psbuf
->st_ex_flags
;
4185 /* For each flags requested in smb_fmask, check the state of the
4186 * corresponding flag in smb_fflags and set or clear the matching
4190 for (i
= 0; i
< ARRAY_SIZE(info2_flags_map
); ++i
) {
4191 max_fmask
|= info2_flags_map
[i
].smb_fflag
;
4192 if (smb_fmask
& info2_flags_map
[i
].smb_fflag
) {
4193 if (smb_fflags
& info2_flags_map
[i
].smb_fflag
) {
4194 *stat_fflags
|= info2_flags_map
[i
].stat_fflag
;
4196 *stat_fflags
&= ~info2_flags_map
[i
].stat_fflag
;
4201 /* If smb_fmask is asking to set any bits that are not supported by
4202 * our flag mappings, we should fail.
4204 if ((smb_fmask
& max_fmask
) != smb_fmask
) {
4212 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
4213 * of file flags and birth (create) time.
4215 static char *store_file_unix_basic_info2(connection_struct
*conn
,
4218 const SMB_STRUCT_STAT
*psbuf
)
4220 uint32 file_flags
= 0;
4221 uint32 flags_mask
= 0;
4223 pdata
= store_file_unix_basic(conn
, pdata
, fsp
, psbuf
);
4225 /* Create (birth) time 64 bit */
4226 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER
,pdata
, psbuf
->st_ex_btime
);
4229 map_info2_flags_from_sbuf(psbuf
, &file_flags
, &flags_mask
);
4230 SIVAL(pdata
, 0, file_flags
); /* flags */
4231 SIVAL(pdata
, 4, flags_mask
); /* mask */
4237 static NTSTATUS
marshall_stream_info(unsigned int num_streams
,
4238 const struct stream_struct
*streams
,
4240 unsigned int max_data_bytes
,
4241 unsigned int *data_size
)
4244 unsigned int ofs
= 0;
4246 if (max_data_bytes
< 32) {
4247 return NT_STATUS_INFO_LENGTH_MISMATCH
;
4250 for (i
= 0; i
< num_streams
; i
++) {
4251 unsigned int next_offset
;
4253 smb_ucs2_t
*namebuf
;
4255 if (!push_ucs2_talloc(talloc_tos(), &namebuf
,
4256 streams
[i
].name
, &namelen
) ||
4259 return NT_STATUS_INVALID_PARAMETER
;
4263 * name_buf is now null-terminated, we need to marshall as not
4270 * We cannot overflow ...
4272 if ((ofs
+ 24 + namelen
) > max_data_bytes
) {
4273 DEBUG(10, ("refusing to overflow reply at stream %u\n",
4275 TALLOC_FREE(namebuf
);
4276 return STATUS_BUFFER_OVERFLOW
;
4279 SIVAL(data
, ofs
+4, namelen
);
4280 SOFF_T(data
, ofs
+8, streams
[i
].size
);
4281 SOFF_T(data
, ofs
+16, streams
[i
].alloc_size
);
4282 memcpy(data
+ofs
+24, namebuf
, namelen
);
4283 TALLOC_FREE(namebuf
);
4285 next_offset
= ofs
+ 24 + namelen
;
4287 if (i
== num_streams
-1) {
4288 SIVAL(data
, ofs
, 0);
4291 unsigned int align
= ndr_align_size(next_offset
, 8);
4293 if ((next_offset
+ align
) > max_data_bytes
) {
4294 DEBUG(10, ("refusing to overflow align "
4295 "reply at stream %u\n",
4297 TALLOC_FREE(namebuf
);
4298 return STATUS_BUFFER_OVERFLOW
;
4301 memset(data
+next_offset
, 0, align
);
4302 next_offset
+= align
;
4304 SIVAL(data
, ofs
, next_offset
- ofs
);
4311 DEBUG(10, ("max_data: %u, data_size: %u\n", max_data_bytes
, ofs
));
4315 return NT_STATUS_OK
;
4318 /****************************************************************************
4319 Reply to a TRANSACT2_QFILEINFO on a PIPE !
4320 ****************************************************************************/
4322 static void call_trans2qpipeinfo(connection_struct
*conn
,
4323 struct smb_request
*req
,
4324 unsigned int tran_call
,
4325 char **pparams
, int total_params
,
4326 char **ppdata
, int total_data
,
4327 unsigned int max_data_bytes
)
4329 char *params
= *pparams
;
4330 char *pdata
= *ppdata
;
4331 unsigned int data_size
= 0;
4332 unsigned int param_size
= 2;
4337 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4341 if (total_params
< 4) {
4342 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4346 fsp
= file_fsp(req
, SVAL(params
,0));
4347 if (!fsp_is_np(fsp
)) {
4348 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
4352 info_level
= SVAL(params
,2);
4354 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
4355 if (*pparams
== NULL
) {
4356 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
4361 if (max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
< max_data_bytes
) {
4362 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4365 data_size
= max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
;
4366 *ppdata
= (char *)SMB_REALLOC(*ppdata
, data_size
);
4367 if (*ppdata
== NULL
) {
4368 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
4373 switch (info_level
) {
4374 case SMB_FILE_STANDARD_INFORMATION
:
4376 SOFF_T(pdata
,0,4096LL);
4383 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
4387 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, param_size
, *ppdata
, data_size
,
4393 NTSTATUS
smbd_do_qfilepathinfo(connection_struct
*conn
,
4394 TALLOC_CTX
*mem_ctx
,
4395 uint16_t info_level
,
4397 struct smb_filename
*smb_fname
,
4398 bool delete_pending
,
4399 struct timespec write_time_ts
,
4400 struct ea_list
*ea_list
,
4401 int lock_data_count
,
4404 unsigned int max_data_bytes
,
4405 size_t *fixed_portion
,
4407 unsigned int *pdata_size
)
4409 char *pdata
= *ppdata
;
4410 char *dstart
, *dend
;
4411 unsigned int data_size
;
4412 struct timespec create_time_ts
, mtime_ts
, atime_ts
, ctime_ts
;
4413 time_t create_time
, mtime
, atime
, c_time
;
4414 SMB_STRUCT_STAT
*psbuf
= &smb_fname
->st
;
4421 uint64_t file_size
= 0;
4423 uint64_t allocation_size
= 0;
4424 uint64_t file_index
= 0;
4425 uint32_t access_mask
= 0;
4427 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
4428 return NT_STATUS_INVALID_LEVEL
;
4431 DEBUG(5,("smbd_do_qfilepathinfo: %s (%s) level=%d max_data=%u\n",
4432 smb_fname_str_dbg(smb_fname
),
4434 info_level
, max_data_bytes
));
4436 mode
= dos_mode(conn
, smb_fname
);
4437 nlink
= psbuf
->st_ex_nlink
;
4439 if (nlink
&& (mode
&FILE_ATTRIBUTE_DIRECTORY
)) {
4443 if ((nlink
> 0) && delete_pending
) {
4447 if (max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
< max_data_bytes
) {
4448 return NT_STATUS_INVALID_PARAMETER
;
4451 data_size
= max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
;
4452 *ppdata
= (char *)SMB_REALLOC(*ppdata
, data_size
);
4453 if (*ppdata
== NULL
) {
4454 return NT_STATUS_NO_MEMORY
;
4458 dend
= dstart
+ data_size
- 1;
4460 if (!null_timespec(write_time_ts
) && !INFO_LEVEL_IS_UNIX(info_level
)) {
4461 update_stat_ex_mtime(psbuf
, write_time_ts
);
4464 create_time_ts
= get_create_timespec(conn
, fsp
, smb_fname
);
4465 mtime_ts
= psbuf
->st_ex_mtime
;
4466 atime_ts
= psbuf
->st_ex_atime
;
4467 ctime_ts
= get_change_timespec(conn
, fsp
, smb_fname
);
4469 if (lp_dos_filetime_resolution(SNUM(conn
))) {
4470 dos_filetime_timespec(&create_time_ts
);
4471 dos_filetime_timespec(&mtime_ts
);
4472 dos_filetime_timespec(&atime_ts
);
4473 dos_filetime_timespec(&ctime_ts
);
4476 create_time
= convert_timespec_to_time_t(create_time_ts
);
4477 mtime
= convert_timespec_to_time_t(mtime_ts
);
4478 atime
= convert_timespec_to_time_t(atime_ts
);
4479 c_time
= convert_timespec_to_time_t(ctime_ts
);
4481 p
= strrchr_m(smb_fname
->base_name
,'/');
4483 base_name
= smb_fname
->base_name
;
4487 /* NT expects the name to be in an exact form of the *full*
4488 filename. See the trans2 torture test */
4489 if (ISDOT(base_name
)) {
4490 dos_fname
= talloc_strdup(mem_ctx
, "\\");
4492 return NT_STATUS_NO_MEMORY
;
4495 dos_fname
= talloc_asprintf(mem_ctx
,
4497 smb_fname
->base_name
);
4499 return NT_STATUS_NO_MEMORY
;
4501 if (is_ntfs_stream_smb_fname(smb_fname
)) {
4502 dos_fname
= talloc_asprintf(dos_fname
, "%s",
4503 smb_fname
->stream_name
);
4505 return NT_STATUS_NO_MEMORY
;
4509 string_replace(dos_fname
, '/', '\\');
4512 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
, fsp
, psbuf
);
4515 /* Do we have this path open ? */
4517 struct file_id fileid
= vfs_file_id_from_sbuf(conn
, psbuf
);
4518 fsp1
= file_find_di_first(conn
->sconn
, fileid
);
4519 if (fsp1
&& fsp1
->initial_allocation_size
) {
4520 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
, fsp1
, psbuf
);
4524 if (!(mode
& FILE_ATTRIBUTE_DIRECTORY
)) {
4525 file_size
= get_file_size_stat(psbuf
);
4529 pos
= fsp
->fh
->position_information
;
4533 access_mask
= fsp
->access_mask
;
4535 /* GENERIC_EXECUTE mapping from Windows */
4536 access_mask
= 0x12019F;
4539 /* This should be an index number - looks like
4542 I think this causes us to fail the IFSKIT
4543 BasicFileInformationTest. -tpot */
4544 file_index
= get_FileIndex(conn
, psbuf
);
4548 switch (info_level
) {
4549 case SMB_INFO_STANDARD
:
4550 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4552 srv_put_dos_date2(pdata
,l1_fdateCreation
,create_time
);
4553 srv_put_dos_date2(pdata
,l1_fdateLastAccess
,atime
);
4554 srv_put_dos_date2(pdata
,l1_fdateLastWrite
,mtime
); /* write time */
4555 SIVAL(pdata
,l1_cbFile
,(uint32
)file_size
);
4556 SIVAL(pdata
,l1_cbFileAlloc
,(uint32
)allocation_size
);
4557 SSVAL(pdata
,l1_attrFile
,mode
);
4560 case SMB_INFO_QUERY_EA_SIZE
:
4562 unsigned int ea_size
=
4563 estimate_ea_size(conn
, fsp
,
4565 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4567 srv_put_dos_date2(pdata
,0,create_time
);
4568 srv_put_dos_date2(pdata
,4,atime
);
4569 srv_put_dos_date2(pdata
,8,mtime
); /* write time */
4570 SIVAL(pdata
,12,(uint32
)file_size
);
4571 SIVAL(pdata
,16,(uint32
)allocation_size
);
4572 SSVAL(pdata
,20,mode
);
4573 SIVAL(pdata
,22,ea_size
);
4577 case SMB_INFO_IS_NAME_VALID
:
4578 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4580 /* os/2 needs this ? really ?*/
4581 return NT_STATUS_DOS(ERRDOS
, ERRbadfunc
);
4583 /* This is only reached for qpathinfo */
4587 case SMB_INFO_QUERY_EAS_FROM_LIST
:
4589 size_t total_ea_len
= 0;
4590 struct ea_list
*ea_file_list
= NULL
;
4591 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4594 get_ea_list_from_file(mem_ctx
, conn
, fsp
,
4596 &total_ea_len
, &ea_file_list
);
4597 if (!NT_STATUS_IS_OK(status
)) {
4601 ea_list
= ea_list_union(ea_list
, ea_file_list
, &total_ea_len
);
4603 if (!ea_list
|| (total_ea_len
> data_size
)) {
4605 SIVAL(pdata
,0,4); /* EA List Length must be set to 4 if no EA's. */
4609 data_size
= fill_ea_buffer(mem_ctx
, pdata
, data_size
, conn
, ea_list
);
4613 case SMB_INFO_QUERY_ALL_EAS
:
4615 /* We have data_size bytes to put EA's into. */
4616 size_t total_ea_len
= 0;
4617 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4619 status
= get_ea_list_from_file(mem_ctx
, conn
, fsp
,
4621 &total_ea_len
, &ea_list
);
4622 if (!NT_STATUS_IS_OK(status
)) {
4626 if (!ea_list
|| (total_ea_len
> data_size
)) {
4628 SIVAL(pdata
,0,4); /* EA List Length must be set to 4 if no EA's. */
4632 data_size
= fill_ea_buffer(mem_ctx
, pdata
, data_size
, conn
, ea_list
);
4636 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
4638 /* This is FileFullEaInformation - 0xF which maps to
4639 * 1015 (decimal) in smbd_do_setfilepathinfo. */
4641 /* We have data_size bytes to put EA's into. */
4642 size_t total_ea_len
= 0;
4643 struct ea_list
*ea_file_list
= NULL
;
4645 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
4647 /*TODO: add filtering and index handling */
4650 get_ea_list_from_file(mem_ctx
, conn
, fsp
,
4652 &total_ea_len
, &ea_file_list
);
4653 if (!NT_STATUS_IS_OK(status
)) {
4656 if (!ea_file_list
) {
4657 return NT_STATUS_NO_EAS_ON_FILE
;
4660 status
= fill_ea_chained_buffer(mem_ctx
,
4664 conn
, ea_file_list
);
4665 if (!NT_STATUS_IS_OK(status
)) {
4671 case SMB_FILE_BASIC_INFORMATION
:
4672 case SMB_QUERY_FILE_BASIC_INFO
:
4674 if (info_level
== SMB_QUERY_FILE_BASIC_INFO
) {
4675 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4676 data_size
= 36; /* w95 returns 40 bytes not 36 - why ?. */
4678 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4682 put_long_date_timespec(conn
->ts_res
,pdata
,create_time_ts
);
4683 put_long_date_timespec(conn
->ts_res
,pdata
+8,atime_ts
);
4684 put_long_date_timespec(conn
->ts_res
,pdata
+16,mtime_ts
); /* write time */
4685 put_long_date_timespec(conn
->ts_res
,pdata
+24,ctime_ts
); /* change time */
4686 SIVAL(pdata
,32,mode
);
4688 DEBUG(5,("SMB_QFBI - "));
4689 DEBUG(5,("create: %s ", ctime(&create_time
)));
4690 DEBUG(5,("access: %s ", ctime(&atime
)));
4691 DEBUG(5,("write: %s ", ctime(&mtime
)));
4692 DEBUG(5,("change: %s ", ctime(&c_time
)));
4693 DEBUG(5,("mode: %x\n", mode
));
4694 *fixed_portion
= data_size
;
4697 case SMB_FILE_STANDARD_INFORMATION
:
4698 case SMB_QUERY_FILE_STANDARD_INFO
:
4700 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4702 SOFF_T(pdata
,0,allocation_size
);
4703 SOFF_T(pdata
,8,file_size
);
4704 SIVAL(pdata
,16,nlink
);
4705 SCVAL(pdata
,20,delete_pending
?1:0);
4706 SCVAL(pdata
,21,(mode
&FILE_ATTRIBUTE_DIRECTORY
)?1:0);
4707 SSVAL(pdata
,22,0); /* Padding. */
4708 *fixed_portion
= 24;
4711 case SMB_FILE_EA_INFORMATION
:
4712 case SMB_QUERY_FILE_EA_INFO
:
4714 unsigned int ea_size
=
4715 estimate_ea_size(conn
, fsp
, smb_fname
);
4716 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4719 SIVAL(pdata
,0,ea_size
);
4723 /* Get the 8.3 name - used if NT SMB was negotiated. */
4724 case SMB_QUERY_FILE_ALT_NAME_INFO
:
4725 case SMB_FILE_ALTERNATE_NAME_INFORMATION
:
4728 char mangled_name
[13];
4729 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4730 if (!name_to_8_3(base_name
,mangled_name
,
4731 True
,conn
->params
)) {
4732 return NT_STATUS_NO_MEMORY
;
4734 len
= srvstr_push(dstart
, flags2
,
4735 pdata
+4, mangled_name
,
4736 PTR_DIFF(dend
, pdata
+4),
4738 data_size
= 4 + len
;
4744 case SMB_QUERY_FILE_NAME_INFO
:
4748 this must be *exactly* right for ACLs on mapped drives to work
4750 len
= srvstr_push(dstart
, flags2
,
4752 PTR_DIFF(dend
, pdata
+4),
4754 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4755 data_size
= 4 + len
;
4760 case SMB_FILE_ALLOCATION_INFORMATION
:
4761 case SMB_QUERY_FILE_ALLOCATION_INFO
:
4762 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4764 SOFF_T(pdata
,0,allocation_size
);
4767 case SMB_FILE_END_OF_FILE_INFORMATION
:
4768 case SMB_QUERY_FILE_END_OF_FILEINFO
:
4769 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4771 SOFF_T(pdata
,0,file_size
);
4774 case SMB_QUERY_FILE_ALL_INFO
:
4775 case SMB_FILE_ALL_INFORMATION
:
4778 unsigned int ea_size
=
4779 estimate_ea_size(conn
, fsp
, smb_fname
);
4780 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4781 put_long_date_timespec(conn
->ts_res
,pdata
,create_time_ts
);
4782 put_long_date_timespec(conn
->ts_res
,pdata
+8,atime_ts
);
4783 put_long_date_timespec(conn
->ts_res
,pdata
+16,mtime_ts
); /* write time */
4784 put_long_date_timespec(conn
->ts_res
,pdata
+24,ctime_ts
); /* change time */
4785 SIVAL(pdata
,32,mode
);
4786 SIVAL(pdata
,36,0); /* padding. */
4788 SOFF_T(pdata
,0,allocation_size
);
4789 SOFF_T(pdata
,8,file_size
);
4790 SIVAL(pdata
,16,nlink
);
4791 SCVAL(pdata
,20,delete_pending
);
4792 SCVAL(pdata
,21,(mode
&FILE_ATTRIBUTE_DIRECTORY
)?1:0);
4795 SIVAL(pdata
,0,ea_size
);
4796 pdata
+= 4; /* EA info */
4797 len
= srvstr_push(dstart
, flags2
,
4799 PTR_DIFF(dend
, pdata
+4),
4803 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4804 *fixed_portion
= 10;
4808 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
4811 unsigned int ea_size
=
4812 estimate_ea_size(conn
, fsp
, smb_fname
);
4813 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
4814 put_long_date_timespec(conn
->ts_res
,pdata
+0x00,create_time_ts
);
4815 put_long_date_timespec(conn
->ts_res
,pdata
+0x08,atime_ts
);
4816 put_long_date_timespec(conn
->ts_res
,pdata
+0x10,mtime_ts
); /* write time */
4817 put_long_date_timespec(conn
->ts_res
,pdata
+0x18,ctime_ts
); /* change time */
4818 SIVAL(pdata
, 0x20, mode
);
4819 SIVAL(pdata
, 0x24, 0); /* padding. */
4820 SBVAL(pdata
, 0x28, allocation_size
);
4821 SBVAL(pdata
, 0x30, file_size
);
4822 SIVAL(pdata
, 0x38, nlink
);
4823 SCVAL(pdata
, 0x3C, delete_pending
);
4824 SCVAL(pdata
, 0x3D, (mode
&FILE_ATTRIBUTE_DIRECTORY
)?1:0);
4825 SSVAL(pdata
, 0x3E, 0); /* padding */
4826 SBVAL(pdata
, 0x40, file_index
);
4827 SIVAL(pdata
, 0x48, ea_size
);
4828 SIVAL(pdata
, 0x4C, access_mask
);
4829 SBVAL(pdata
, 0x50, pos
);
4830 SIVAL(pdata
, 0x58, mode
); /*TODO: mode != mode fix this!!! */
4831 SIVAL(pdata
, 0x5C, 0); /* No alignment needed. */
4835 len
= srvstr_push(dstart
, flags2
,
4837 PTR_DIFF(dend
, pdata
+4),
4841 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4842 *fixed_portion
= 104;
4845 case SMB_FILE_INTERNAL_INFORMATION
:
4847 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4848 SBVAL(pdata
, 0, file_index
);
4853 case SMB_FILE_ACCESS_INFORMATION
:
4854 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4855 SIVAL(pdata
, 0, access_mask
);
4860 case SMB_FILE_NAME_INFORMATION
:
4861 /* Pathname with leading '\'. */
4864 byte_len
= dos_PutUniCode(pdata
+4,dos_fname
,(size_t)max_data_bytes
,False
);
4865 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4866 SIVAL(pdata
,0,byte_len
);
4867 data_size
= 4 + byte_len
;
4871 case SMB_FILE_DISPOSITION_INFORMATION
:
4872 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4874 SCVAL(pdata
,0,delete_pending
);
4878 case SMB_FILE_POSITION_INFORMATION
:
4879 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4881 SOFF_T(pdata
,0,pos
);
4885 case SMB_FILE_MODE_INFORMATION
:
4886 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4887 SIVAL(pdata
,0,mode
);
4892 case SMB_FILE_ALIGNMENT_INFORMATION
:
4893 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4894 SIVAL(pdata
,0,0); /* No alignment needed. */
4900 * NT4 server just returns "invalid query" to this - if we try
4901 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4904 /* The first statement above is false - verified using Thursby
4905 * client against NT4 -- gcolley.
4907 case SMB_QUERY_FILE_STREAM_INFO
:
4908 case SMB_FILE_STREAM_INFORMATION
: {
4909 unsigned int num_streams
= 0;
4910 struct stream_struct
*streams
= NULL
;
4912 DEBUG(10,("smbd_do_qfilepathinfo: "
4913 "SMB_FILE_STREAM_INFORMATION\n"));
4915 if (is_ntfs_stream_smb_fname(smb_fname
)) {
4916 return NT_STATUS_INVALID_PARAMETER
;
4919 status
= vfs_streaminfo(conn
, fsp
, smb_fname
->base_name
,
4920 talloc_tos(), &num_streams
, &streams
);
4922 if (!NT_STATUS_IS_OK(status
)) {
4923 DEBUG(10, ("could not get stream info: %s\n",
4924 nt_errstr(status
)));
4928 status
= marshall_stream_info(num_streams
, streams
,
4929 pdata
, max_data_bytes
,
4932 if (!NT_STATUS_IS_OK(status
)) {
4933 DEBUG(10, ("marshall_stream_info failed: %s\n",
4934 nt_errstr(status
)));
4935 TALLOC_FREE(streams
);
4939 TALLOC_FREE(streams
);
4941 *fixed_portion
= 32;
4945 case SMB_QUERY_COMPRESSION_INFO
:
4946 case SMB_FILE_COMPRESSION_INFORMATION
:
4947 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4948 SOFF_T(pdata
,0,file_size
);
4949 SIVAL(pdata
,8,0); /* ??? */
4950 SIVAL(pdata
,12,0); /* ??? */
4952 *fixed_portion
= 16;
4955 case SMB_FILE_NETWORK_OPEN_INFORMATION
:
4956 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4957 put_long_date_timespec(conn
->ts_res
,pdata
,create_time_ts
);
4958 put_long_date_timespec(conn
->ts_res
,pdata
+8,atime_ts
);
4959 put_long_date_timespec(conn
->ts_res
,pdata
+16,mtime_ts
); /* write time */
4960 put_long_date_timespec(conn
->ts_res
,pdata
+24,ctime_ts
); /* change time */
4961 SOFF_T(pdata
,32,allocation_size
);
4962 SOFF_T(pdata
,40,file_size
);
4963 SIVAL(pdata
,48,mode
);
4964 SIVAL(pdata
,52,0); /* ??? */
4966 *fixed_portion
= 56;
4969 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION
:
4970 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4971 SIVAL(pdata
,0,mode
);
4978 * CIFS UNIX Extensions.
4981 case SMB_QUERY_FILE_UNIX_BASIC
:
4983 pdata
= store_file_unix_basic(conn
, pdata
, fsp
, psbuf
);
4984 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4986 DEBUG(4,("smbd_do_qfilepathinfo: "
4987 "SMB_QUERY_FILE_UNIX_BASIC\n"));
4988 dump_data(4, (uint8_t *)(*ppdata
), data_size
);
4992 case SMB_QUERY_FILE_UNIX_INFO2
:
4994 pdata
= store_file_unix_basic_info2(conn
, pdata
, fsp
, psbuf
);
4995 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4999 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
5001 for (i
=0; i
<100; i
++)
5002 DEBUG(4,("%d=%x, ",i
, (*ppdata
)[i
]));
5008 case SMB_QUERY_FILE_UNIX_LINK
:
5011 char *buffer
= talloc_array(mem_ctx
, char, PATH_MAX
+1);
5014 return NT_STATUS_NO_MEMORY
;
5017 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
5019 if(!S_ISLNK(psbuf
->st_ex_mode
)) {
5020 return NT_STATUS_DOS(ERRSRV
, ERRbadlink
);
5023 return NT_STATUS_DOS(ERRDOS
, ERRbadlink
);
5025 len
= SMB_VFS_READLINK(conn
,
5026 smb_fname
->base_name
,
5029 return map_nt_error_from_unix(errno
);
5032 len
= srvstr_push(dstart
, flags2
,
5034 PTR_DIFF(dend
, pdata
),
5037 data_size
= PTR_DIFF(pdata
,(*ppdata
));
5042 #if defined(HAVE_POSIX_ACLS)
5043 case SMB_QUERY_POSIX_ACL
:
5045 SMB_ACL_T file_acl
= NULL
;
5046 SMB_ACL_T def_acl
= NULL
;
5047 uint16 num_file_acls
= 0;
5048 uint16 num_def_acls
= 0;
5050 if (fsp
&& fsp
->fh
->fd
!= -1) {
5051 file_acl
= SMB_VFS_SYS_ACL_GET_FD(fsp
,
5055 SMB_VFS_SYS_ACL_GET_FILE(conn
,
5056 smb_fname
->base_name
,
5057 SMB_ACL_TYPE_ACCESS
,
5061 if (file_acl
== NULL
&& no_acl_syscall_error(errno
)) {
5062 DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
5063 "not implemented on "
5064 "filesystem containing %s\n",
5065 smb_fname
->base_name
));
5066 return NT_STATUS_NOT_IMPLEMENTED
;
5069 if (S_ISDIR(psbuf
->st_ex_mode
)) {
5070 if (fsp
&& fsp
->is_directory
) {
5072 SMB_VFS_SYS_ACL_GET_FILE(
5074 fsp
->fsp_name
->base_name
,
5075 SMB_ACL_TYPE_DEFAULT
,
5079 SMB_VFS_SYS_ACL_GET_FILE(
5081 smb_fname
->base_name
,
5082 SMB_ACL_TYPE_DEFAULT
,
5085 def_acl
= free_empty_sys_acl(conn
, def_acl
);
5088 num_file_acls
= count_acl_entries(conn
, file_acl
);
5089 num_def_acls
= count_acl_entries(conn
, def_acl
);
5091 if ( data_size
< (num_file_acls
+ num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
+ SMB_POSIX_ACL_HEADER_SIZE
) {
5092 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
5094 (unsigned int)((num_file_acls
+ num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
+
5095 SMB_POSIX_ACL_HEADER_SIZE
) ));
5097 TALLOC_FREE(file_acl
);
5100 TALLOC_FREE(def_acl
);
5102 return NT_STATUS_BUFFER_TOO_SMALL
;
5105 SSVAL(pdata
,0,SMB_POSIX_ACL_VERSION
);
5106 SSVAL(pdata
,2,num_file_acls
);
5107 SSVAL(pdata
,4,num_def_acls
);
5108 if (!marshall_posix_acl(conn
, pdata
+ SMB_POSIX_ACL_HEADER_SIZE
, psbuf
, file_acl
)) {
5110 TALLOC_FREE(file_acl
);
5113 TALLOC_FREE(def_acl
);
5115 return NT_STATUS_INTERNAL_ERROR
;
5117 if (!marshall_posix_acl(conn
, pdata
+ SMB_POSIX_ACL_HEADER_SIZE
+ (num_file_acls
*SMB_POSIX_ACL_ENTRY_SIZE
), psbuf
, def_acl
)) {
5119 TALLOC_FREE(file_acl
);
5122 TALLOC_FREE(def_acl
);
5124 return NT_STATUS_INTERNAL_ERROR
;
5128 TALLOC_FREE(file_acl
);
5131 TALLOC_FREE(def_acl
);
5133 data_size
= (num_file_acls
+ num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
+ SMB_POSIX_ACL_HEADER_SIZE
;
5139 case SMB_QUERY_POSIX_LOCK
:
5144 enum brl_type lock_type
;
5146 /* We need an open file with a real fd for this. */
5147 if (!fsp
|| fsp
->fh
->fd
== -1) {
5148 return NT_STATUS_INVALID_LEVEL
;
5151 if (lock_data_count
!= POSIX_LOCK_DATA_SIZE
) {
5152 return NT_STATUS_INVALID_PARAMETER
;
5155 switch (SVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
)) {
5156 case POSIX_LOCK_TYPE_READ
:
5157 lock_type
= READ_LOCK
;
5159 case POSIX_LOCK_TYPE_WRITE
:
5160 lock_type
= WRITE_LOCK
;
5162 case POSIX_LOCK_TYPE_UNLOCK
:
5164 /* There's no point in asking for an unlock... */
5165 return NT_STATUS_INVALID_PARAMETER
;
5168 smblctx
= (uint64_t)IVAL(pdata
, POSIX_LOCK_PID_OFFSET
);
5169 #if defined(HAVE_LONGLONG)
5170 offset
= BVAL(pdata
,POSIX_LOCK_START_OFFSET
);
5171 count
= BVAL(pdata
,POSIX_LOCK_LEN_OFFSET
);
5172 #else /* HAVE_LONGLONG */
5173 offset
= (uint64_t)IVAL(pdata
,POSIX_LOCK_START_OFFSET
);
5174 count
= (uint64_t)IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
);
5175 #endif /* HAVE_LONGLONG */
5177 status
= query_lock(fsp
,
5184 if (ERROR_WAS_LOCK_DENIED(status
)) {
5185 /* Here we need to report who has it locked... */
5186 data_size
= POSIX_LOCK_DATA_SIZE
;
5188 SSVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
, lock_type
);
5189 SSVAL(pdata
, POSIX_LOCK_FLAGS_OFFSET
, 0);
5190 SIVAL(pdata
, POSIX_LOCK_PID_OFFSET
, (uint32_t)smblctx
);
5191 #if defined(HAVE_LONGLONG)
5192 SBVAL(pdata
, POSIX_LOCK_START_OFFSET
, offset
);
5193 SBVAL(pdata
, POSIX_LOCK_LEN_OFFSET
, count
);
5194 #else /* HAVE_LONGLONG */
5195 SIVAL(pdata
, POSIX_LOCK_START_OFFSET
, offset
);
5196 SIVAL(pdata
, POSIX_LOCK_LEN_OFFSET
, count
);
5197 #endif /* HAVE_LONGLONG */
5199 } else if (NT_STATUS_IS_OK(status
)) {
5200 /* For success we just return a copy of what we sent
5201 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
5202 data_size
= POSIX_LOCK_DATA_SIZE
;
5203 memcpy(pdata
, lock_data
, POSIX_LOCK_DATA_SIZE
);
5204 SSVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
, POSIX_LOCK_TYPE_UNLOCK
);
5212 return NT_STATUS_INVALID_LEVEL
;
5215 *pdata_size
= data_size
;
5216 return NT_STATUS_OK
;
5219 /****************************************************************************
5220 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
5221 file name or file id).
5222 ****************************************************************************/
5224 static void call_trans2qfilepathinfo(connection_struct
*conn
,
5225 struct smb_request
*req
,
5226 unsigned int tran_call
,
5227 char **pparams
, int total_params
,
5228 char **ppdata
, int total_data
,
5229 unsigned int max_data_bytes
)
5231 char *params
= *pparams
;
5232 char *pdata
= *ppdata
;
5234 unsigned int data_size
= 0;
5235 unsigned int param_size
= 2;
5236 struct smb_filename
*smb_fname
= NULL
;
5237 bool delete_pending
= False
;
5238 struct timespec write_time_ts
;
5239 files_struct
*fsp
= NULL
;
5240 struct file_id fileid
;
5241 struct ea_list
*ea_list
= NULL
;
5242 int lock_data_count
= 0;
5243 char *lock_data
= NULL
;
5244 size_t fixed_portion
;
5245 NTSTATUS status
= NT_STATUS_OK
;
5248 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5252 ZERO_STRUCT(write_time_ts
);
5254 if (tran_call
== TRANSACT2_QFILEINFO
) {
5255 if (total_params
< 4) {
5256 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5261 call_trans2qpipeinfo(conn
, req
, tran_call
,
5262 pparams
, total_params
,
5268 fsp
= file_fsp(req
, SVAL(params
,0));
5269 info_level
= SVAL(params
,2);
5271 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level
));
5273 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
5274 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
5278 /* Initial check for valid fsp ptr. */
5279 if (!check_fsp_open(conn
, req
, fsp
)) {
5283 smb_fname
= cp_smb_filename(talloc_tos(), fsp
->fsp_name
);
5284 if (smb_fname
== NULL
) {
5285 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5289 if(fsp
->fake_file_handle
) {
5291 * This is actually for the QUOTA_FAKE_FILE --metze
5294 /* We know this name is ok, it's already passed the checks. */
5296 } else if(fsp
->fh
->fd
== -1) {
5298 * This is actually a QFILEINFO on a directory
5299 * handle (returned from an NT SMB). NT5.0 seems
5300 * to do this call. JRA.
5303 if (INFO_LEVEL_IS_UNIX(info_level
)) {
5304 /* Always do lstat for UNIX calls. */
5305 if (SMB_VFS_LSTAT(conn
, smb_fname
)) {
5306 DEBUG(3,("call_trans2qfilepathinfo: "
5307 "SMB_VFS_LSTAT of %s failed "
5309 smb_fname_str_dbg(smb_fname
),
5312 map_nt_error_from_unix(errno
));
5315 } else if (SMB_VFS_STAT(conn
, smb_fname
)) {
5316 DEBUG(3,("call_trans2qfilepathinfo: "
5317 "SMB_VFS_STAT of %s failed (%s)\n",
5318 smb_fname_str_dbg(smb_fname
),
5321 map_nt_error_from_unix(errno
));
5325 fileid
= vfs_file_id_from_sbuf(conn
, &smb_fname
->st
);
5326 get_file_infos(fileid
, fsp
->name_hash
, &delete_pending
, &write_time_ts
);
5329 * Original code - this is an open file.
5331 if (SMB_VFS_FSTAT(fsp
, &smb_fname
->st
) != 0) {
5332 DEBUG(3, ("fstat of %s failed (%s)\n",
5333 fsp_fnum_dbg(fsp
), strerror(errno
)));
5335 map_nt_error_from_unix(errno
));
5338 fileid
= vfs_file_id_from_sbuf(conn
, &smb_fname
->st
);
5339 get_file_infos(fileid
, fsp
->name_hash
, &delete_pending
, &write_time_ts
);
5345 uint32_t ucf_flags
= 0;
5348 if (total_params
< 7) {
5349 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5353 info_level
= SVAL(params
,0);
5355 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level
));
5357 if (INFO_LEVEL_IS_UNIX(info_level
)) {
5358 if (!lp_unix_extensions()) {
5359 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
5362 if (info_level
== SMB_QUERY_FILE_UNIX_BASIC
||
5363 info_level
== SMB_QUERY_FILE_UNIX_INFO2
||
5364 info_level
== SMB_QUERY_FILE_UNIX_LINK
) {
5365 ucf_flags
|= UCF_UNIX_NAME_LOOKUP
;
5369 srvstr_get_path(req
, params
, req
->flags2
, &fname
, ¶ms
[6],
5371 STR_TERMINATE
, &status
);
5372 if (!NT_STATUS_IS_OK(status
)) {
5373 reply_nterror(req
, status
);
5377 status
= filename_convert(req
,
5379 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
5384 if (!NT_STATUS_IS_OK(status
)) {
5385 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
5386 reply_botherror(req
,
5387 NT_STATUS_PATH_NOT_COVERED
,
5388 ERRSRV
, ERRbadpath
);
5391 reply_nterror(req
, status
);
5395 /* If this is a stream, check if there is a delete_pending. */
5396 if ((conn
->fs_capabilities
& FILE_NAMED_STREAMS
)
5397 && is_ntfs_stream_smb_fname(smb_fname
)) {
5398 struct smb_filename
*smb_fname_base
;
5400 /* Create an smb_filename with stream_name == NULL. */
5401 smb_fname_base
= synthetic_smb_fname(
5402 talloc_tos(), smb_fname
->base_name
,
5404 if (smb_fname_base
== NULL
) {
5405 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5409 if (INFO_LEVEL_IS_UNIX(info_level
)) {
5410 /* Always do lstat for UNIX calls. */
5411 if (SMB_VFS_LSTAT(conn
, smb_fname_base
) != 0) {
5412 DEBUG(3,("call_trans2qfilepathinfo: "
5413 "SMB_VFS_LSTAT of %s failed "
5415 smb_fname_str_dbg(smb_fname_base
),
5417 TALLOC_FREE(smb_fname_base
);
5419 map_nt_error_from_unix(errno
));
5423 if (SMB_VFS_STAT(conn
, smb_fname_base
) != 0) {
5424 DEBUG(3,("call_trans2qfilepathinfo: "
5425 "fileinfo of %s failed "
5427 smb_fname_str_dbg(smb_fname_base
),
5429 TALLOC_FREE(smb_fname_base
);
5431 map_nt_error_from_unix(errno
));
5436 status
= file_name_hash(conn
,
5437 smb_fname_str_dbg(smb_fname_base
),
5439 if (!NT_STATUS_IS_OK(status
)) {
5440 TALLOC_FREE(smb_fname_base
);
5441 reply_nterror(req
, status
);
5445 fileid
= vfs_file_id_from_sbuf(conn
,
5446 &smb_fname_base
->st
);
5447 TALLOC_FREE(smb_fname_base
);
5448 get_file_infos(fileid
, name_hash
, &delete_pending
, NULL
);
5449 if (delete_pending
) {
5450 reply_nterror(req
, NT_STATUS_DELETE_PENDING
);
5455 if (INFO_LEVEL_IS_UNIX(info_level
)) {
5456 /* Always do lstat for UNIX calls. */
5457 if (SMB_VFS_LSTAT(conn
, smb_fname
)) {
5458 DEBUG(3,("call_trans2qfilepathinfo: "
5459 "SMB_VFS_LSTAT of %s failed (%s)\n",
5460 smb_fname_str_dbg(smb_fname
),
5463 map_nt_error_from_unix(errno
));
5468 if (SMB_VFS_STAT(conn
, smb_fname
) != 0) {
5469 DEBUG(3,("call_trans2qfilepathinfo: "
5470 "SMB_VFS_STAT of %s failed (%s)\n",
5471 smb_fname_str_dbg(smb_fname
),
5474 map_nt_error_from_unix(errno
));
5479 status
= file_name_hash(conn
,
5480 smb_fname_str_dbg(smb_fname
),
5482 if (!NT_STATUS_IS_OK(status
)) {
5483 reply_nterror(req
, status
);
5487 fileid
= vfs_file_id_from_sbuf(conn
, &smb_fname
->st
);
5488 get_file_infos(fileid
, name_hash
, &delete_pending
, &write_time_ts
);
5489 if (delete_pending
) {
5490 reply_nterror(req
, NT_STATUS_DELETE_PENDING
);
5495 DEBUG(3,("call_trans2qfilepathinfo %s (%s) level=%d call=%d "
5496 "total_data=%d\n", smb_fname_str_dbg(smb_fname
),
5498 info_level
,tran_call
,total_data
));
5500 /* Pull out any data sent here before we realloc. */
5501 switch (info_level
) {
5502 case SMB_INFO_QUERY_EAS_FROM_LIST
:
5504 /* Pull any EA list from the data portion. */
5507 if (total_data
< 4) {
5509 req
, NT_STATUS_INVALID_PARAMETER
);
5512 ea_size
= IVAL(pdata
,0);
5514 if (total_data
> 0 && ea_size
!= total_data
) {
5515 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5516 total_data=%u (should be %u)\n", (unsigned int)total_data
, (unsigned int)IVAL(pdata
,0) ));
5518 req
, NT_STATUS_INVALID_PARAMETER
);
5522 if (!lp_ea_support(SNUM(conn
))) {
5523 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
5527 /* Pull out the list of names. */
5528 ea_list
= read_ea_name_list(req
, pdata
+ 4, ea_size
- 4);
5531 req
, NT_STATUS_INVALID_PARAMETER
);
5537 case SMB_QUERY_POSIX_LOCK
:
5539 if (fsp
== NULL
|| fsp
->fh
->fd
== -1) {
5540 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
5544 if (total_data
!= POSIX_LOCK_DATA_SIZE
) {
5546 req
, NT_STATUS_INVALID_PARAMETER
);
5550 /* Copy the lock range data. */
5551 lock_data
= (char *)talloc_memdup(
5552 req
, pdata
, total_data
);
5554 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5557 lock_data_count
= total_data
;
5563 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
5564 if (*pparams
== NULL
) {
5565 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5572 * draft-leach-cifs-v1-spec-02.txt
5573 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
5576 * The requested information is placed in the Data portion of the
5577 * transaction response. For the information levels greater than 0x100,
5578 * the transaction response has 1 parameter word which should be
5579 * ignored by the client.
5581 * However Windows only follows this rule for the IS_NAME_VALID call.
5583 switch (info_level
) {
5584 case SMB_INFO_IS_NAME_VALID
:
5589 if ((info_level
& 0xFF00) == 0xFF00) {
5591 * We use levels that start with 0xFF00
5592 * internally to represent SMB2 specific levels
5594 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
5598 status
= smbd_do_qfilepathinfo(conn
, req
, info_level
,
5600 delete_pending
, write_time_ts
,
5602 lock_data_count
, lock_data
,
5603 req
->flags2
, max_data_bytes
,
5605 ppdata
, &data_size
);
5606 if (!NT_STATUS_IS_OK(status
)) {
5607 reply_nterror(req
, status
);
5610 if (fixed_portion
> max_data_bytes
) {
5611 reply_nterror(req
, NT_STATUS_INFO_LENGTH_MISMATCH
);
5615 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, param_size
, *ppdata
, data_size
,
5621 /****************************************************************************
5622 Set a hard link (called by UNIX extensions and by NT rename with HARD link
5624 ****************************************************************************/
5626 NTSTATUS
hardlink_internals(TALLOC_CTX
*ctx
,
5627 connection_struct
*conn
,
5628 struct smb_request
*req
,
5629 bool overwrite_if_exists
,
5630 const struct smb_filename
*smb_fname_old
,
5631 struct smb_filename
*smb_fname_new
)
5633 NTSTATUS status
= NT_STATUS_OK
;
5635 /* source must already exist. */
5636 if (!VALID_STAT(smb_fname_old
->st
)) {
5637 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5640 if (VALID_STAT(smb_fname_new
->st
)) {
5641 if (overwrite_if_exists
) {
5642 if (S_ISDIR(smb_fname_new
->st
.st_ex_mode
)) {
5643 return NT_STATUS_FILE_IS_A_DIRECTORY
;
5645 status
= unlink_internals(conn
,
5647 FILE_ATTRIBUTE_NORMAL
,
5650 if (!NT_STATUS_IS_OK(status
)) {
5654 /* Disallow if newname already exists. */
5655 return NT_STATUS_OBJECT_NAME_COLLISION
;
5659 /* No links from a directory. */
5660 if (S_ISDIR(smb_fname_old
->st
.st_ex_mode
)) {
5661 return NT_STATUS_FILE_IS_A_DIRECTORY
;
5664 /* Setting a hardlink to/from a stream isn't currently supported. */
5665 if (is_ntfs_stream_smb_fname(smb_fname_old
) ||
5666 is_ntfs_stream_smb_fname(smb_fname_new
)) {
5667 return NT_STATUS_INVALID_PARAMETER
;
5670 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
5671 smb_fname_old
->base_name
, smb_fname_new
->base_name
));
5673 if (SMB_VFS_LINK(conn
, smb_fname_old
->base_name
,
5674 smb_fname_new
->base_name
) != 0) {
5675 status
= map_nt_error_from_unix(errno
);
5676 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
5677 nt_errstr(status
), smb_fname_old
->base_name
,
5678 smb_fname_new
->base_name
));
5683 /****************************************************************************
5684 Deal with setting the time from any of the setfilepathinfo functions.
5685 NOTE !!!! The check for FILE_WRITE_ATTRIBUTES access must be done *before*
5686 calling this function.
5687 ****************************************************************************/
5689 NTSTATUS
smb_set_file_time(connection_struct
*conn
,
5691 const struct smb_filename
*smb_fname
,
5692 struct smb_file_time
*ft
,
5693 bool setting_write_time
)
5695 struct smb_filename smb_fname_base
;
5697 FILE_NOTIFY_CHANGE_LAST_ACCESS
5698 |FILE_NOTIFY_CHANGE_LAST_WRITE
5699 |FILE_NOTIFY_CHANGE_CREATION
;
5701 if (!VALID_STAT(smb_fname
->st
)) {
5702 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5705 /* get some defaults (no modifications) if any info is zero or -1. */
5706 if (null_timespec(ft
->create_time
)) {
5707 action
&= ~FILE_NOTIFY_CHANGE_CREATION
;
5710 if (null_timespec(ft
->atime
)) {
5711 action
&= ~FILE_NOTIFY_CHANGE_LAST_ACCESS
;
5714 if (null_timespec(ft
->mtime
)) {
5715 action
&= ~FILE_NOTIFY_CHANGE_LAST_WRITE
;
5718 if (!setting_write_time
) {
5719 /* ft->mtime comes from change time, not write time. */
5720 action
&= ~FILE_NOTIFY_CHANGE_LAST_WRITE
;
5723 /* Ensure the resolution is the correct for
5724 * what we can store on this filesystem. */
5726 round_timespec(conn
->ts_res
, &ft
->create_time
);
5727 round_timespec(conn
->ts_res
, &ft
->ctime
);
5728 round_timespec(conn
->ts_res
, &ft
->atime
);
5729 round_timespec(conn
->ts_res
, &ft
->mtime
);
5731 DEBUG(5,("smb_set_filetime: actime: %s\n ",
5732 time_to_asc(convert_timespec_to_time_t(ft
->atime
))));
5733 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
5734 time_to_asc(convert_timespec_to_time_t(ft
->mtime
))));
5735 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
5736 time_to_asc(convert_timespec_to_time_t(ft
->ctime
))));
5737 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
5738 time_to_asc(convert_timespec_to_time_t(ft
->create_time
))));
5740 if (setting_write_time
) {
5742 * This was a Windows setfileinfo on an open file.
5743 * NT does this a lot. We also need to
5744 * set the time here, as it can be read by
5745 * FindFirst/FindNext and with the patch for bug #2045
5746 * in smbd/fileio.c it ensures that this timestamp is
5747 * kept sticky even after a write. We save the request
5748 * away and will set it on file close and after a write. JRA.
5751 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
5752 time_to_asc(convert_timespec_to_time_t(ft
->mtime
))));
5755 if (fsp
->base_fsp
) {
5756 set_sticky_write_time_fsp(fsp
->base_fsp
,
5759 set_sticky_write_time_fsp(fsp
, ft
->mtime
);
5762 set_sticky_write_time_path(
5763 vfs_file_id_from_sbuf(conn
, &smb_fname
->st
),
5768 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5770 /* Always call ntimes on the base, even if a stream was passed in. */
5771 smb_fname_base
= *smb_fname
;
5772 smb_fname_base
.stream_name
= NULL
;
5774 if(file_ntimes(conn
, &smb_fname_base
, ft
)!=0) {
5775 return map_nt_error_from_unix(errno
);
5778 notify_fname(conn
, NOTIFY_ACTION_MODIFIED
, action
,
5779 smb_fname
->base_name
);
5780 return NT_STATUS_OK
;
5783 /****************************************************************************
5784 Deal with setting the dosmode from any of the setfilepathinfo functions.
5785 NB. The check for FILE_WRITE_ATTRIBUTES access on this path must have been
5786 done before calling this function.
5787 ****************************************************************************/
5789 static NTSTATUS
smb_set_file_dosmode(connection_struct
*conn
,
5790 const struct smb_filename
*smb_fname
,
5793 struct smb_filename
*smb_fname_base
;
5796 if (!VALID_STAT(smb_fname
->st
)) {
5797 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5800 /* Always operate on the base_name, even if a stream was passed in. */
5801 smb_fname_base
= synthetic_smb_fname(
5802 talloc_tos(), smb_fname
->base_name
, NULL
, &smb_fname
->st
);
5803 if (smb_fname_base
== NULL
) {
5804 return NT_STATUS_NO_MEMORY
;
5808 if (S_ISDIR(smb_fname_base
->st
.st_ex_mode
)) {
5809 dosmode
|= FILE_ATTRIBUTE_DIRECTORY
;
5811 dosmode
&= ~FILE_ATTRIBUTE_DIRECTORY
;
5815 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode
));
5817 /* check the mode isn't different, before changing it */
5818 if ((dosmode
!= 0) && (dosmode
!= dos_mode(conn
, smb_fname_base
))) {
5819 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
5820 "0x%x\n", smb_fname_str_dbg(smb_fname_base
),
5821 (unsigned int)dosmode
));
5823 if(file_set_dosmode(conn
, smb_fname_base
, dosmode
, NULL
,
5825 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
5827 smb_fname_str_dbg(smb_fname_base
),
5829 status
= map_nt_error_from_unix(errno
);
5833 status
= NT_STATUS_OK
;
5835 TALLOC_FREE(smb_fname_base
);
5839 /****************************************************************************
5840 Deal with setting the size from any of the setfilepathinfo functions.
5841 ****************************************************************************/
5843 static NTSTATUS
smb_set_file_size(connection_struct
*conn
,
5844 struct smb_request
*req
,
5846 const struct smb_filename
*smb_fname
,
5847 const SMB_STRUCT_STAT
*psbuf
,
5849 bool fail_after_createfile
)
5851 NTSTATUS status
= NT_STATUS_OK
;
5852 struct smb_filename
*smb_fname_tmp
= NULL
;
5853 files_struct
*new_fsp
= NULL
;
5855 if (!VALID_STAT(*psbuf
)) {
5856 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5859 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size
));
5861 if (size
== get_file_size_stat(psbuf
)) {
5862 return NT_STATUS_OK
;
5865 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5866 smb_fname_str_dbg(smb_fname
), (double)size
));
5868 if (fsp
&& fsp
->fh
->fd
!= -1) {
5869 /* Handle based call. */
5870 if (!(fsp
->access_mask
& FILE_WRITE_DATA
)) {
5871 return NT_STATUS_ACCESS_DENIED
;
5874 if (vfs_set_filelen(fsp
, size
) == -1) {
5875 return map_nt_error_from_unix(errno
);
5877 trigger_write_time_update_immediate(fsp
);
5878 return NT_STATUS_OK
;
5881 smb_fname_tmp
= cp_smb_filename(talloc_tos(), smb_fname
);
5882 if (smb_fname_tmp
== NULL
) {
5883 return NT_STATUS_NO_MEMORY
;
5886 smb_fname_tmp
->st
= *psbuf
;
5888 status
= SMB_VFS_CREATE_FILE(
5891 0, /* root_dir_fid */
5892 smb_fname_tmp
, /* fname */
5893 FILE_WRITE_DATA
, /* access_mask */
5894 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
5896 FILE_OPEN
, /* create_disposition*/
5897 0, /* create_options */
5898 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
5899 0, /* oplock_request */
5900 0, /* allocation_size */
5901 0, /* private_flags */
5904 &new_fsp
, /* result */
5907 TALLOC_FREE(smb_fname_tmp
);
5909 if (!NT_STATUS_IS_OK(status
)) {
5910 /* NB. We check for open_was_deferred in the caller. */
5914 /* See RAW-SFILEINFO-END-OF-FILE */
5915 if (fail_after_createfile
) {
5916 close_file(req
, new_fsp
,NORMAL_CLOSE
);
5917 return NT_STATUS_INVALID_LEVEL
;
5920 if (vfs_set_filelen(new_fsp
, size
) == -1) {
5921 status
= map_nt_error_from_unix(errno
);
5922 close_file(req
, new_fsp
,NORMAL_CLOSE
);
5926 trigger_write_time_update_immediate(new_fsp
);
5927 close_file(req
, new_fsp
,NORMAL_CLOSE
);
5928 return NT_STATUS_OK
;
5931 /****************************************************************************
5932 Deal with SMB_INFO_SET_EA.
5933 ****************************************************************************/
5935 static NTSTATUS
smb_info_set_ea(connection_struct
*conn
,
5939 const struct smb_filename
*smb_fname
)
5941 struct ea_list
*ea_list
= NULL
;
5942 TALLOC_CTX
*ctx
= NULL
;
5943 NTSTATUS status
= NT_STATUS_OK
;
5945 if (total_data
< 10) {
5947 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5948 length. They seem to have no effect. Bug #3212. JRA */
5950 if ((total_data
== 4) && (IVAL(pdata
,0) == 4)) {
5951 /* We're done. We only get EA info in this call. */
5952 return NT_STATUS_OK
;
5955 return NT_STATUS_INVALID_PARAMETER
;
5958 if (IVAL(pdata
,0) > total_data
) {
5959 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5960 IVAL(pdata
,0), (unsigned int)total_data
));
5961 return NT_STATUS_INVALID_PARAMETER
;
5965 ea_list
= read_ea_list(ctx
, pdata
+ 4, total_data
- 4);
5967 return NT_STATUS_INVALID_PARAMETER
;
5970 status
= set_ea(conn
, fsp
, smb_fname
, ea_list
);
5975 /****************************************************************************
5976 Deal with SMB_FILE_FULL_EA_INFORMATION set.
5977 ****************************************************************************/
5979 static NTSTATUS
smb_set_file_full_ea_info(connection_struct
*conn
,
5984 struct ea_list
*ea_list
= NULL
;
5988 return NT_STATUS_INVALID_HANDLE
;
5991 if (!lp_ea_support(SNUM(conn
))) {
5992 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
5993 "EA's not supported.\n",
5994 (unsigned int)total_data
));
5995 return NT_STATUS_EAS_NOT_SUPPORTED
;
5998 if (total_data
< 10) {
5999 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
6001 (unsigned int)total_data
));
6002 return NT_STATUS_INVALID_PARAMETER
;
6005 ea_list
= read_nttrans_ea_list(talloc_tos(),
6010 return NT_STATUS_INVALID_PARAMETER
;
6013 status
= set_ea(conn
, fsp
, fsp
->fsp_name
, ea_list
);
6015 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
6016 smb_fname_str_dbg(fsp
->fsp_name
),
6017 nt_errstr(status
) ));
6023 /****************************************************************************
6024 Deal with SMB_SET_FILE_DISPOSITION_INFO.
6025 ****************************************************************************/
6027 static NTSTATUS
smb_set_file_disposition_info(connection_struct
*conn
,
6031 struct smb_filename
*smb_fname
)
6033 NTSTATUS status
= NT_STATUS_OK
;
6034 bool delete_on_close
;
6037 if (total_data
< 1) {
6038 return NT_STATUS_INVALID_PARAMETER
;
6042 return NT_STATUS_INVALID_HANDLE
;
6045 delete_on_close
= (CVAL(pdata
,0) ? True
: False
);
6046 dosmode
= dos_mode(conn
, smb_fname
);
6048 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
6049 "delete_on_close = %u\n",
6050 smb_fname_str_dbg(smb_fname
),
6051 (unsigned int)dosmode
,
6052 (unsigned int)delete_on_close
));
6054 if (delete_on_close
) {
6055 status
= can_set_delete_on_close(fsp
, dosmode
);
6056 if (!NT_STATUS_IS_OK(status
)) {
6061 /* The set is across all open files on this dev/inode pair. */
6062 if (!set_delete_on_close(fsp
, delete_on_close
,
6063 conn
->session_info
->security_token
,
6064 conn
->session_info
->unix_token
)) {
6065 return NT_STATUS_ACCESS_DENIED
;
6067 return NT_STATUS_OK
;
6070 /****************************************************************************
6071 Deal with SMB_FILE_POSITION_INFORMATION.
6072 ****************************************************************************/
6074 static NTSTATUS
smb_file_position_information(connection_struct
*conn
,
6079 uint64_t position_information
;
6081 if (total_data
< 8) {
6082 return NT_STATUS_INVALID_PARAMETER
;
6086 /* Ignore on pathname based set. */
6087 return NT_STATUS_OK
;
6090 position_information
= (uint64_t)IVAL(pdata
,0);
6091 position_information
|= (((uint64_t)IVAL(pdata
,4)) << 32);
6093 DEBUG(10,("smb_file_position_information: Set file position "
6094 "information for file %s to %.0f\n", fsp_str_dbg(fsp
),
6095 (double)position_information
));
6096 fsp
->fh
->position_information
= position_information
;
6097 return NT_STATUS_OK
;
6100 /****************************************************************************
6101 Deal with SMB_FILE_MODE_INFORMATION.
6102 ****************************************************************************/
6104 static NTSTATUS
smb_file_mode_information(connection_struct
*conn
,
6110 if (total_data
< 4) {
6111 return NT_STATUS_INVALID_PARAMETER
;
6113 mode
= IVAL(pdata
,0);
6114 if (mode
!= 0 && mode
!= 2 && mode
!= 4 && mode
!= 6) {
6115 return NT_STATUS_INVALID_PARAMETER
;
6117 return NT_STATUS_OK
;
6120 /****************************************************************************
6121 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
6122 ****************************************************************************/
6124 static NTSTATUS
smb_set_file_unix_link(connection_struct
*conn
,
6125 struct smb_request
*req
,
6128 const struct smb_filename
*smb_fname
)
6130 char *link_target
= NULL
;
6131 const char *newname
= smb_fname
->base_name
;
6132 TALLOC_CTX
*ctx
= talloc_tos();
6134 /* Set a symbolic link. */
6135 /* Don't allow this if follow links is false. */
6137 if (total_data
== 0) {
6138 return NT_STATUS_INVALID_PARAMETER
;
6141 if (!lp_follow_symlinks(SNUM(conn
))) {
6142 return NT_STATUS_ACCESS_DENIED
;
6145 srvstr_pull_talloc(ctx
, pdata
, req
->flags2
, &link_target
, pdata
,
6146 total_data
, STR_TERMINATE
);
6149 return NT_STATUS_INVALID_PARAMETER
;
6152 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
6153 newname
, link_target
));
6155 if (SMB_VFS_SYMLINK(conn
,link_target
,newname
) != 0) {
6156 return map_nt_error_from_unix(errno
);
6159 return NT_STATUS_OK
;
6162 /****************************************************************************
6163 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
6164 ****************************************************************************/
6166 static NTSTATUS
smb_set_file_unix_hlink(connection_struct
*conn
,
6167 struct smb_request
*req
,
6168 const char *pdata
, int total_data
,
6169 struct smb_filename
*smb_fname_new
)
6171 char *oldname
= NULL
;
6172 struct smb_filename
*smb_fname_old
= NULL
;
6173 TALLOC_CTX
*ctx
= talloc_tos();
6174 NTSTATUS status
= NT_STATUS_OK
;
6176 /* Set a hard link. */
6177 if (total_data
== 0) {
6178 return NT_STATUS_INVALID_PARAMETER
;
6181 srvstr_get_path(ctx
, pdata
, req
->flags2
, &oldname
, pdata
,
6182 total_data
, STR_TERMINATE
, &status
);
6183 if (!NT_STATUS_IS_OK(status
)) {
6187 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
6188 smb_fname_str_dbg(smb_fname_new
), oldname
));
6190 status
= filename_convert(ctx
,
6192 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6197 if (!NT_STATUS_IS_OK(status
)) {
6201 return hardlink_internals(ctx
, conn
, req
, false,
6202 smb_fname_old
, smb_fname_new
);
6205 /****************************************************************************
6206 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
6207 ****************************************************************************/
6209 static NTSTATUS
smb2_file_rename_information(connection_struct
*conn
,
6210 struct smb_request
*req
,
6214 struct smb_filename
*smb_fname_src
)
6218 char *newname
= NULL
;
6219 struct smb_filename
*smb_fname_dst
= NULL
;
6220 NTSTATUS status
= NT_STATUS_OK
;
6221 TALLOC_CTX
*ctx
= talloc_tos();
6224 return NT_STATUS_INVALID_HANDLE
;
6227 if (total_data
< 20) {
6228 return NT_STATUS_INVALID_PARAMETER
;
6231 overwrite
= (CVAL(pdata
,0) ? True
: False
);
6232 len
= IVAL(pdata
,16);
6234 if (len
> (total_data
- 20) || (len
== 0)) {
6235 return NT_STATUS_INVALID_PARAMETER
;
6238 srvstr_get_path(ctx
, pdata
, req
->flags2
, &newname
,
6239 &pdata
[20], len
, STR_TERMINATE
,
6241 if (!NT_STATUS_IS_OK(status
)) {
6245 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
6248 status
= filename_convert(ctx
,
6250 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6255 if (!NT_STATUS_IS_OK(status
)) {
6259 if (fsp
->base_fsp
) {
6260 /* newname must be a stream name. */
6261 if (newname
[0] != ':') {
6262 return NT_STATUS_NOT_SUPPORTED
;
6265 /* Create an smb_fname to call rename_internals_fsp() with. */
6266 smb_fname_dst
= synthetic_smb_fname(
6267 talloc_tos(), fsp
->base_fsp
->fsp_name
->base_name
,
6269 if (smb_fname_dst
== NULL
) {
6270 status
= NT_STATUS_NO_MEMORY
;
6275 * Set the original last component, since
6276 * rename_internals_fsp() requires it.
6278 smb_fname_dst
->original_lcomp
= talloc_strdup(smb_fname_dst
,
6280 if (smb_fname_dst
->original_lcomp
== NULL
) {
6281 status
= NT_STATUS_NO_MEMORY
;
6287 DEBUG(10,("smb2_file_rename_information: "
6288 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
6289 fsp_fnum_dbg(fsp
), fsp_str_dbg(fsp
),
6290 smb_fname_str_dbg(smb_fname_dst
)));
6291 status
= rename_internals_fsp(conn
, fsp
, smb_fname_dst
,
6292 (FILE_ATTRIBUTE_HIDDEN
|FILE_ATTRIBUTE_SYSTEM
),
6296 TALLOC_FREE(smb_fname_dst
);
6300 static NTSTATUS
smb_file_link_information(connection_struct
*conn
,
6301 struct smb_request
*req
,
6305 struct smb_filename
*smb_fname_src
)
6309 char *newname
= NULL
;
6310 struct smb_filename
*smb_fname_dst
= NULL
;
6311 NTSTATUS status
= NT_STATUS_OK
;
6312 TALLOC_CTX
*ctx
= talloc_tos();
6315 return NT_STATUS_INVALID_HANDLE
;
6318 if (total_data
< 20) {
6319 return NT_STATUS_INVALID_PARAMETER
;
6322 overwrite
= (CVAL(pdata
,0) ? true : false);
6323 len
= IVAL(pdata
,16);
6325 if (len
> (total_data
- 20) || (len
== 0)) {
6326 return NT_STATUS_INVALID_PARAMETER
;
6329 srvstr_get_path(ctx
, pdata
, req
->flags2
, &newname
,
6330 &pdata
[20], len
, STR_TERMINATE
,
6332 if (!NT_STATUS_IS_OK(status
)) {
6336 DEBUG(10,("smb_file_link_information: got name |%s|\n",
6339 status
= filename_convert(ctx
,
6341 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6346 if (!NT_STATUS_IS_OK(status
)) {
6350 if (fsp
->base_fsp
) {
6351 /* No stream names. */
6352 return NT_STATUS_NOT_SUPPORTED
;
6355 DEBUG(10,("smb_file_link_information: "
6356 "SMB_FILE_LINK_INFORMATION (%s) %s -> %s\n",
6357 fsp_fnum_dbg(fsp
), fsp_str_dbg(fsp
),
6358 smb_fname_str_dbg(smb_fname_dst
)));
6359 status
= hardlink_internals(ctx
,
6366 TALLOC_FREE(smb_fname_dst
);
6370 /****************************************************************************
6371 Deal with SMB_FILE_RENAME_INFORMATION.
6372 ****************************************************************************/
6374 static NTSTATUS
smb_file_rename_information(connection_struct
*conn
,
6375 struct smb_request
*req
,
6379 struct smb_filename
*smb_fname_src
)
6384 char *newname
= NULL
;
6385 struct smb_filename
*smb_fname_dst
= NULL
;
6386 bool dest_has_wcard
= False
;
6387 NTSTATUS status
= NT_STATUS_OK
;
6389 TALLOC_CTX
*ctx
= talloc_tos();
6391 if (total_data
< 13) {
6392 return NT_STATUS_INVALID_PARAMETER
;
6395 overwrite
= (CVAL(pdata
,0) ? True
: False
);
6396 root_fid
= IVAL(pdata
,4);
6397 len
= IVAL(pdata
,8);
6399 if (len
> (total_data
- 12) || (len
== 0) || (root_fid
!= 0)) {
6400 return NT_STATUS_INVALID_PARAMETER
;
6403 srvstr_get_path_wcard(ctx
, pdata
, req
->flags2
, &newname
, &pdata
[12],
6406 if (!NT_STATUS_IS_OK(status
)) {
6410 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
6413 status
= resolve_dfspath_wcard(ctx
, conn
,
6414 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6417 !conn
->sconn
->using_smb2
,
6420 if (!NT_STATUS_IS_OK(status
)) {
6424 /* Check the new name has no '/' characters. */
6425 if (strchr_m(newname
, '/')) {
6426 return NT_STATUS_NOT_SUPPORTED
;
6429 if (fsp
&& fsp
->base_fsp
) {
6430 /* newname must be a stream name. */
6431 if (newname
[0] != ':') {
6432 return NT_STATUS_NOT_SUPPORTED
;
6435 /* Create an smb_fname to call rename_internals_fsp() with. */
6436 smb_fname_dst
= synthetic_smb_fname(
6437 talloc_tos(), fsp
->base_fsp
->fsp_name
->base_name
,
6439 if (smb_fname_dst
== NULL
) {
6440 status
= NT_STATUS_NO_MEMORY
;
6445 * Set the original last component, since
6446 * rename_internals_fsp() requires it.
6448 smb_fname_dst
->original_lcomp
= talloc_strdup(smb_fname_dst
,
6450 if (smb_fname_dst
->original_lcomp
== NULL
) {
6451 status
= NT_STATUS_NO_MEMORY
;
6457 * Build up an smb_fname_dst based on the filename passed in.
6458 * We basically just strip off the last component, and put on
6459 * the newname instead.
6461 char *base_name
= NULL
;
6463 /* newname must *not* be a stream name. */
6464 if (newname
[0] == ':') {
6465 return NT_STATUS_NOT_SUPPORTED
;
6469 * Strip off the last component (filename) of the path passed
6472 base_name
= talloc_strdup(ctx
, smb_fname_src
->base_name
);
6474 return NT_STATUS_NO_MEMORY
;
6476 p
= strrchr_m(base_name
, '/');
6480 base_name
= talloc_strdup(ctx
, "");
6482 return NT_STATUS_NO_MEMORY
;
6485 /* Append the new name. */
6486 base_name
= talloc_asprintf_append(base_name
,
6490 return NT_STATUS_NO_MEMORY
;
6493 status
= unix_convert(ctx
, conn
, base_name
, &smb_fname_dst
,
6496 UCF_ALWAYS_ALLOW_WCARD_LCOMP
:
6499 /* If an error we expect this to be
6500 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
6502 if (!NT_STATUS_IS_OK(status
)) {
6503 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND
,
6507 /* Create an smb_fname to call rename_internals_fsp() */
6508 smb_fname_dst
= synthetic_smb_fname(
6509 ctx
, base_name
, NULL
, NULL
);
6510 if (smb_fname_dst
== NULL
) {
6511 status
= NT_STATUS_NO_MEMORY
;
6518 DEBUG(10,("smb_file_rename_information: "
6519 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
6520 fsp_fnum_dbg(fsp
), fsp_str_dbg(fsp
),
6521 smb_fname_str_dbg(smb_fname_dst
)));
6522 status
= rename_internals_fsp(conn
, fsp
, smb_fname_dst
, 0,
6525 DEBUG(10,("smb_file_rename_information: "
6526 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
6527 smb_fname_str_dbg(smb_fname_src
),
6528 smb_fname_str_dbg(smb_fname_dst
)));
6529 status
= rename_internals(ctx
, conn
, req
, smb_fname_src
,
6530 smb_fname_dst
, 0, overwrite
, false,
6532 FILE_WRITE_ATTRIBUTES
);
6535 TALLOC_FREE(smb_fname_dst
);
6539 /****************************************************************************
6540 Deal with SMB_SET_POSIX_ACL.
6541 ****************************************************************************/
6543 #if defined(HAVE_POSIX_ACLS)
6544 static NTSTATUS
smb_set_posix_acl(connection_struct
*conn
,
6548 const struct smb_filename
*smb_fname
)
6550 uint16 posix_acl_version
;
6551 uint16 num_file_acls
;
6552 uint16 num_def_acls
;
6553 bool valid_file_acls
= True
;
6554 bool valid_def_acls
= True
;
6556 if (total_data
< SMB_POSIX_ACL_HEADER_SIZE
) {
6557 return NT_STATUS_INVALID_PARAMETER
;
6559 posix_acl_version
= SVAL(pdata
,0);
6560 num_file_acls
= SVAL(pdata
,2);
6561 num_def_acls
= SVAL(pdata
,4);
6563 if (num_file_acls
== SMB_POSIX_IGNORE_ACE_ENTRIES
) {
6564 valid_file_acls
= False
;
6568 if (num_def_acls
== SMB_POSIX_IGNORE_ACE_ENTRIES
) {
6569 valid_def_acls
= False
;
6573 if (posix_acl_version
!= SMB_POSIX_ACL_VERSION
) {
6574 return NT_STATUS_INVALID_PARAMETER
;
6577 if (total_data
< SMB_POSIX_ACL_HEADER_SIZE
+
6578 (num_file_acls
+num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
) {
6579 return NT_STATUS_INVALID_PARAMETER
;
6582 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
6583 smb_fname
? smb_fname_str_dbg(smb_fname
) : fsp_str_dbg(fsp
),
6584 (unsigned int)num_file_acls
,
6585 (unsigned int)num_def_acls
));
6587 if (valid_file_acls
&& !set_unix_posix_acl(conn
, fsp
,
6588 smb_fname
->base_name
, num_file_acls
,
6589 pdata
+ SMB_POSIX_ACL_HEADER_SIZE
)) {
6590 return map_nt_error_from_unix(errno
);
6593 if (valid_def_acls
&& !set_unix_posix_default_acl(conn
,
6594 smb_fname
->base_name
, &smb_fname
->st
, num_def_acls
,
6595 pdata
+ SMB_POSIX_ACL_HEADER_SIZE
+
6596 (num_file_acls
*SMB_POSIX_ACL_ENTRY_SIZE
))) {
6597 return map_nt_error_from_unix(errno
);
6599 return NT_STATUS_OK
;
6603 /****************************************************************************
6604 Deal with SMB_SET_POSIX_LOCK.
6605 ****************************************************************************/
6607 static NTSTATUS
smb_set_posix_lock(connection_struct
*conn
,
6608 struct smb_request
*req
,
6616 bool blocking_lock
= False
;
6617 enum brl_type lock_type
;
6619 NTSTATUS status
= NT_STATUS_OK
;
6621 if (fsp
== NULL
|| fsp
->fh
->fd
== -1) {
6622 return NT_STATUS_INVALID_HANDLE
;
6625 if (total_data
!= POSIX_LOCK_DATA_SIZE
) {
6626 return NT_STATUS_INVALID_PARAMETER
;
6629 switch (SVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
)) {
6630 case POSIX_LOCK_TYPE_READ
:
6631 lock_type
= READ_LOCK
;
6633 case POSIX_LOCK_TYPE_WRITE
:
6634 /* Return the right POSIX-mappable error code for files opened read-only. */
6635 if (!fsp
->can_write
) {
6636 return NT_STATUS_INVALID_HANDLE
;
6638 lock_type
= WRITE_LOCK
;
6640 case POSIX_LOCK_TYPE_UNLOCK
:
6641 lock_type
= UNLOCK_LOCK
;
6644 return NT_STATUS_INVALID_PARAMETER
;
6647 if (SVAL(pdata
,POSIX_LOCK_FLAGS_OFFSET
) == POSIX_LOCK_FLAG_NOWAIT
) {
6648 blocking_lock
= False
;
6649 } else if (SVAL(pdata
,POSIX_LOCK_FLAGS_OFFSET
) == POSIX_LOCK_FLAG_WAIT
) {
6650 blocking_lock
= True
;
6652 return NT_STATUS_INVALID_PARAMETER
;
6655 if (!lp_blocking_locks(SNUM(conn
))) {
6656 blocking_lock
= False
;
6659 smblctx
= (uint64_t)IVAL(pdata
, POSIX_LOCK_PID_OFFSET
);
6660 #if defined(HAVE_LONGLONG)
6661 offset
= (((uint64_t) IVAL(pdata
,(POSIX_LOCK_START_OFFSET
+4))) << 32) |
6662 ((uint64_t) IVAL(pdata
,POSIX_LOCK_START_OFFSET
));
6663 count
= (((uint64_t) IVAL(pdata
,(POSIX_LOCK_LEN_OFFSET
+4))) << 32) |
6664 ((uint64_t) IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
));
6665 #else /* HAVE_LONGLONG */
6666 offset
= (uint64_t)IVAL(pdata
,POSIX_LOCK_START_OFFSET
);
6667 count
= (uint64_t)IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
);
6668 #endif /* HAVE_LONGLONG */
6670 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
6671 "smblctx = %llu, count = %.0f, offset = %.0f\n",
6673 (unsigned int)lock_type
,
6674 (unsigned long long)smblctx
,
6678 if (lock_type
== UNLOCK_LOCK
) {
6679 status
= do_unlock(req
->sconn
->msg_ctx
,
6686 uint64_t block_smblctx
;
6688 struct byte_range_lock
*br_lck
= do_lock(req
->sconn
->msg_ctx
,
6699 if (br_lck
&& blocking_lock
&& ERROR_WAS_LOCK_DENIED(status
)) {
6701 * A blocking lock was requested. Package up
6702 * this smb into a queued request and push it
6703 * onto the blocking lock queue.
6705 if(push_blocking_lock_request(br_lck
,
6708 -1, /* infinite timeout. */
6716 TALLOC_FREE(br_lck
);
6720 TALLOC_FREE(br_lck
);
6726 /****************************************************************************
6727 Deal with SMB_SET_FILE_BASIC_INFO.
6728 ****************************************************************************/
6730 static NTSTATUS
smb_set_file_basic_info(connection_struct
*conn
,
6734 const struct smb_filename
*smb_fname
)
6736 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
6737 struct smb_file_time ft
;
6739 NTSTATUS status
= NT_STATUS_OK
;
6743 if (total_data
< 36) {
6744 return NT_STATUS_INVALID_PARAMETER
;
6747 status
= check_access(conn
, fsp
, smb_fname
, FILE_WRITE_ATTRIBUTES
);
6748 if (!NT_STATUS_IS_OK(status
)) {
6752 /* Set the attributes */
6753 dosmode
= IVAL(pdata
,32);
6754 status
= smb_set_file_dosmode(conn
, smb_fname
, dosmode
);
6755 if (!NT_STATUS_IS_OK(status
)) {
6760 ft
.create_time
= interpret_long_date(pdata
);
6763 ft
.atime
= interpret_long_date(pdata
+8);
6766 ft
.mtime
= interpret_long_date(pdata
+16);
6769 ft
.ctime
= interpret_long_date(pdata
+24);
6771 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
6772 smb_fname_str_dbg(smb_fname
)));
6774 return smb_set_file_time(conn
, fsp
, smb_fname
, &ft
,
6778 /****************************************************************************
6779 Deal with SMB_INFO_STANDARD.
6780 ****************************************************************************/
6782 static NTSTATUS
smb_set_info_standard(connection_struct
*conn
,
6786 const struct smb_filename
*smb_fname
)
6789 struct smb_file_time ft
;
6793 if (total_data
< 12) {
6794 return NT_STATUS_INVALID_PARAMETER
;
6798 ft
.create_time
= convert_time_t_to_timespec(srv_make_unix_date2(pdata
));
6800 ft
.atime
= convert_time_t_to_timespec(srv_make_unix_date2(pdata
+4));
6802 ft
.mtime
= convert_time_t_to_timespec(srv_make_unix_date2(pdata
+8));
6804 DEBUG(10,("smb_set_info_standard: file %s\n",
6805 smb_fname_str_dbg(smb_fname
)));
6807 status
= check_access(conn
, fsp
, smb_fname
, FILE_WRITE_ATTRIBUTES
);
6808 if (!NT_STATUS_IS_OK(status
)) {
6812 return smb_set_file_time(conn
,
6819 /****************************************************************************
6820 Deal with SMB_SET_FILE_ALLOCATION_INFO.
6821 ****************************************************************************/
6823 static NTSTATUS
smb_set_file_allocation_info(connection_struct
*conn
,
6824 struct smb_request
*req
,
6828 struct smb_filename
*smb_fname
)
6830 uint64_t allocation_size
= 0;
6831 NTSTATUS status
= NT_STATUS_OK
;
6832 files_struct
*new_fsp
= NULL
;
6834 if (!VALID_STAT(smb_fname
->st
)) {
6835 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
6838 if (total_data
< 8) {
6839 return NT_STATUS_INVALID_PARAMETER
;
6842 allocation_size
= (uint64_t)IVAL(pdata
,0);
6843 allocation_size
|= (((uint64_t)IVAL(pdata
,4)) << 32);
6844 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
6845 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname
),
6846 (double)allocation_size
));
6848 if (allocation_size
) {
6849 allocation_size
= smb_roundup(conn
, allocation_size
);
6852 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
6853 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname
),
6854 (double)allocation_size
));
6856 if (fsp
&& fsp
->fh
->fd
!= -1) {
6857 /* Open file handle. */
6858 if (!(fsp
->access_mask
& FILE_WRITE_DATA
)) {
6859 return NT_STATUS_ACCESS_DENIED
;
6862 /* Only change if needed. */
6863 if (allocation_size
!= get_file_size_stat(&smb_fname
->st
)) {
6864 if (vfs_allocate_file_space(fsp
, allocation_size
) == -1) {
6865 return map_nt_error_from_unix(errno
);
6868 /* But always update the time. */
6870 * This is equivalent to a write. Ensure it's seen immediately
6871 * if there are no pending writes.
6873 trigger_write_time_update_immediate(fsp
);
6874 return NT_STATUS_OK
;
6877 /* Pathname or stat or directory file. */
6878 status
= SMB_VFS_CREATE_FILE(
6881 0, /* root_dir_fid */
6882 smb_fname
, /* fname */
6883 FILE_WRITE_DATA
, /* access_mask */
6884 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
6886 FILE_OPEN
, /* create_disposition*/
6887 0, /* create_options */
6888 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
6889 0, /* oplock_request */
6890 0, /* allocation_size */
6891 0, /* private_flags */
6894 &new_fsp
, /* result */
6897 if (!NT_STATUS_IS_OK(status
)) {
6898 /* NB. We check for open_was_deferred in the caller. */
6902 /* Only change if needed. */
6903 if (allocation_size
!= get_file_size_stat(&smb_fname
->st
)) {
6904 if (vfs_allocate_file_space(new_fsp
, allocation_size
) == -1) {
6905 status
= map_nt_error_from_unix(errno
);
6906 close_file(req
, new_fsp
, NORMAL_CLOSE
);
6911 /* Changing the allocation size should set the last mod time. */
6913 * This is equivalent to a write. Ensure it's seen immediately
6914 * if there are no pending writes.
6916 trigger_write_time_update_immediate(new_fsp
);
6917 close_file(req
, new_fsp
, NORMAL_CLOSE
);
6918 return NT_STATUS_OK
;
6921 /****************************************************************************
6922 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
6923 ****************************************************************************/
6925 static NTSTATUS
smb_set_file_end_of_file_info(connection_struct
*conn
,
6926 struct smb_request
*req
,
6930 const struct smb_filename
*smb_fname
,
6931 bool fail_after_createfile
)
6935 if (total_data
< 8) {
6936 return NT_STATUS_INVALID_PARAMETER
;
6939 size
= IVAL(pdata
,0);
6940 size
|= (((off_t
)IVAL(pdata
,4)) << 32);
6941 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
6942 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname
),
6945 return smb_set_file_size(conn
, req
,
6950 fail_after_createfile
);
6953 /****************************************************************************
6954 Allow a UNIX info mknod.
6955 ****************************************************************************/
6957 static NTSTATUS
smb_unix_mknod(connection_struct
*conn
,
6960 const struct smb_filename
*smb_fname
)
6962 uint32 file_type
= IVAL(pdata
,56);
6963 #if defined(HAVE_MAKEDEV)
6964 uint32 dev_major
= IVAL(pdata
,60);
6965 uint32 dev_minor
= IVAL(pdata
,68);
6967 SMB_DEV_T dev
= (SMB_DEV_T
)0;
6968 uint32 raw_unixmode
= IVAL(pdata
,84);
6972 if (total_data
< 100) {
6973 return NT_STATUS_INVALID_PARAMETER
;
6976 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
6977 PERM_NEW_FILE
, &unixmode
);
6978 if (!NT_STATUS_IS_OK(status
)) {
6982 #if defined(HAVE_MAKEDEV)
6983 dev
= makedev(dev_major
, dev_minor
);
6986 switch (file_type
) {
6987 #if defined(S_IFIFO)
6988 case UNIX_TYPE_FIFO
:
6989 unixmode
|= S_IFIFO
;
6992 #if defined(S_IFSOCK)
6993 case UNIX_TYPE_SOCKET
:
6994 unixmode
|= S_IFSOCK
;
6997 #if defined(S_IFCHR)
6998 case UNIX_TYPE_CHARDEV
:
6999 unixmode
|= S_IFCHR
;
7002 #if defined(S_IFBLK)
7003 case UNIX_TYPE_BLKDEV
:
7004 unixmode
|= S_IFBLK
;
7008 return NT_STATUS_INVALID_PARAMETER
;
7011 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
7012 "%.0f mode 0%o for file %s\n", (double)dev
,
7013 (unsigned int)unixmode
, smb_fname_str_dbg(smb_fname
)));
7015 /* Ok - do the mknod. */
7016 if (SMB_VFS_MKNOD(conn
, smb_fname
->base_name
, unixmode
, dev
) != 0) {
7017 return map_nt_error_from_unix(errno
);
7020 /* If any of the other "set" calls fail we
7021 * don't want to end up with a half-constructed mknod.
7024 if (lp_inherit_permissions(SNUM(conn
))) {
7026 if (!parent_dirname(talloc_tos(), smb_fname
->base_name
,
7028 return NT_STATUS_NO_MEMORY
;
7030 inherit_access_posix_acl(conn
, parent
, smb_fname
->base_name
,
7032 TALLOC_FREE(parent
);
7035 return NT_STATUS_OK
;
7038 /****************************************************************************
7039 Deal with SMB_SET_FILE_UNIX_BASIC.
7040 ****************************************************************************/
7042 static NTSTATUS
smb_set_file_unix_basic(connection_struct
*conn
,
7043 struct smb_request
*req
,
7047 const struct smb_filename
*smb_fname
)
7049 struct smb_file_time ft
;
7050 uint32 raw_unixmode
;
7053 uid_t set_owner
= (uid_t
)SMB_UID_NO_CHANGE
;
7054 gid_t set_grp
= (uid_t
)SMB_GID_NO_CHANGE
;
7055 NTSTATUS status
= NT_STATUS_OK
;
7056 bool delete_on_fail
= False
;
7057 enum perm_type ptype
;
7058 files_struct
*all_fsps
= NULL
;
7059 bool modify_mtime
= true;
7061 struct smb_filename
*smb_fname_tmp
= NULL
;
7062 SMB_STRUCT_STAT sbuf
;
7066 if (total_data
< 100) {
7067 return NT_STATUS_INVALID_PARAMETER
;
7070 if(IVAL(pdata
, 0) != SMB_SIZE_NO_CHANGE_LO
&&
7071 IVAL(pdata
, 4) != SMB_SIZE_NO_CHANGE_HI
) {
7072 size
=IVAL(pdata
,0); /* first 8 Bytes are size */
7073 size
|= (((off_t
)IVAL(pdata
,4)) << 32);
7076 ft
.atime
= interpret_long_date(pdata
+24); /* access_time */
7077 ft
.mtime
= interpret_long_date(pdata
+32); /* modification_time */
7078 set_owner
= (uid_t
)IVAL(pdata
,40);
7079 set_grp
= (gid_t
)IVAL(pdata
,48);
7080 raw_unixmode
= IVAL(pdata
,84);
7082 if (VALID_STAT(smb_fname
->st
)) {
7083 if (S_ISDIR(smb_fname
->st
.st_ex_mode
)) {
7084 ptype
= PERM_EXISTING_DIR
;
7086 ptype
= PERM_EXISTING_FILE
;
7089 ptype
= PERM_NEW_FILE
;
7092 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
7094 if (!NT_STATUS_IS_OK(status
)) {
7098 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
7099 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
7100 smb_fname_str_dbg(smb_fname
), (double)size
,
7101 (unsigned int)set_owner
, (unsigned int)set_grp
,
7102 (int)raw_unixmode
));
7104 sbuf
= smb_fname
->st
;
7106 if (!VALID_STAT(sbuf
)) {
7108 * The only valid use of this is to create character and block
7109 * devices, and named pipes. This is deprecated (IMHO) and
7110 * a new info level should be used for mknod. JRA.
7113 status
= smb_unix_mknod(conn
,
7117 if (!NT_STATUS_IS_OK(status
)) {
7121 smb_fname_tmp
= cp_smb_filename(talloc_tos(), smb_fname
);
7122 if (smb_fname_tmp
== NULL
) {
7123 return NT_STATUS_NO_MEMORY
;
7126 if (SMB_VFS_STAT(conn
, smb_fname_tmp
) != 0) {
7127 status
= map_nt_error_from_unix(errno
);
7128 TALLOC_FREE(smb_fname_tmp
);
7129 SMB_VFS_UNLINK(conn
, smb_fname
);
7133 sbuf
= smb_fname_tmp
->st
;
7134 smb_fname
= smb_fname_tmp
;
7136 /* Ensure we don't try and change anything else. */
7137 raw_unixmode
= SMB_MODE_NO_CHANGE
;
7138 size
= get_file_size_stat(&sbuf
);
7139 ft
.atime
= sbuf
.st_ex_atime
;
7140 ft
.mtime
= sbuf
.st_ex_mtime
;
7142 * We continue here as we might want to change the
7145 delete_on_fail
= True
;
7149 /* Horrible backwards compatibility hack as an old server bug
7150 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
7154 size
= get_file_size_stat(&sbuf
);
7159 * Deal with the UNIX specific mode set.
7162 if (raw_unixmode
!= SMB_MODE_NO_CHANGE
) {
7165 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7166 "setting mode 0%o for file %s\n",
7167 (unsigned int)unixmode
,
7168 smb_fname_str_dbg(smb_fname
)));
7169 if (fsp
&& fsp
->fh
->fd
!= -1) {
7170 ret
= SMB_VFS_FCHMOD(fsp
, unixmode
);
7172 ret
= SMB_VFS_CHMOD(conn
, smb_fname
->base_name
, unixmode
);
7175 return map_nt_error_from_unix(errno
);
7180 * Deal with the UNIX specific uid set.
7183 if ((set_owner
!= (uid_t
)SMB_UID_NO_CHANGE
) &&
7184 (sbuf
.st_ex_uid
!= set_owner
)) {
7187 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7188 "changing owner %u for path %s\n",
7189 (unsigned int)set_owner
,
7190 smb_fname_str_dbg(smb_fname
)));
7192 if (fsp
&& fsp
->fh
->fd
!= -1) {
7193 ret
= SMB_VFS_FCHOWN(fsp
, set_owner
, (gid_t
)-1);
7196 * UNIX extensions calls must always operate
7199 ret
= SMB_VFS_LCHOWN(conn
, smb_fname
->base_name
,
7200 set_owner
, (gid_t
)-1);
7204 status
= map_nt_error_from_unix(errno
);
7205 if (delete_on_fail
) {
7206 SMB_VFS_UNLINK(conn
, smb_fname
);
7213 * Deal with the UNIX specific gid set.
7216 if ((set_grp
!= (uid_t
)SMB_GID_NO_CHANGE
) &&
7217 (sbuf
.st_ex_gid
!= set_grp
)) {
7220 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7221 "changing group %u for file %s\n",
7222 (unsigned int)set_owner
,
7223 smb_fname_str_dbg(smb_fname
)));
7224 if (fsp
&& fsp
->fh
->fd
!= -1) {
7225 ret
= SMB_VFS_FCHOWN(fsp
, set_owner
, (gid_t
)-1);
7228 * UNIX extensions calls must always operate
7231 ret
= SMB_VFS_LCHOWN(conn
, smb_fname
->base_name
, (uid_t
)-1,
7235 status
= map_nt_error_from_unix(errno
);
7236 if (delete_on_fail
) {
7237 SMB_VFS_UNLINK(conn
, smb_fname
);
7243 /* Deal with any size changes. */
7245 status
= smb_set_file_size(conn
, req
,
7251 if (!NT_STATUS_IS_OK(status
)) {
7255 /* Deal with any time changes. */
7256 if (null_timespec(ft
.mtime
) && null_timespec(ft
.atime
)) {
7257 /* No change, don't cancel anything. */
7261 id
= vfs_file_id_from_sbuf(conn
, &sbuf
);
7262 for(all_fsps
= file_find_di_first(conn
->sconn
, id
); all_fsps
;
7263 all_fsps
= file_find_di_next(all_fsps
)) {
7265 * We're setting the time explicitly for UNIX.
7266 * Cancel any pending changes over all handles.
7268 all_fsps
->update_write_time_on_close
= false;
7269 TALLOC_FREE(all_fsps
->update_write_time_event
);
7273 * Override the "setting_write_time"
7274 * parameter here as it almost does what
7275 * we need. Just remember if we modified
7276 * mtime and send the notify ourselves.
7278 if (null_timespec(ft
.mtime
)) {
7279 modify_mtime
= false;
7282 status
= smb_set_file_time(conn
,
7288 notify_fname(conn
, NOTIFY_ACTION_MODIFIED
,
7289 FILE_NOTIFY_CHANGE_LAST_WRITE
, smb_fname
->base_name
);
7294 /****************************************************************************
7295 Deal with SMB_SET_FILE_UNIX_INFO2.
7296 ****************************************************************************/
7298 static NTSTATUS
smb_set_file_unix_info2(connection_struct
*conn
,
7299 struct smb_request
*req
,
7303 const struct smb_filename
*smb_fname
)
7309 if (total_data
< 116) {
7310 return NT_STATUS_INVALID_PARAMETER
;
7313 /* Start by setting all the fields that are common between UNIX_BASIC
7316 status
= smb_set_file_unix_basic(conn
, req
, pdata
, total_data
,
7318 if (!NT_STATUS_IS_OK(status
)) {
7322 smb_fflags
= IVAL(pdata
, 108);
7323 smb_fmask
= IVAL(pdata
, 112);
7325 /* NB: We should only attempt to alter the file flags if the client
7326 * sends a non-zero mask.
7328 if (smb_fmask
!= 0) {
7329 int stat_fflags
= 0;
7331 if (!map_info2_flags_to_sbuf(&smb_fname
->st
, smb_fflags
,
7332 smb_fmask
, &stat_fflags
)) {
7333 /* Client asked to alter a flag we don't understand. */
7334 return NT_STATUS_INVALID_PARAMETER
;
7337 if (fsp
&& fsp
->fh
->fd
!= -1) {
7338 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
7339 return NT_STATUS_NOT_SUPPORTED
;
7341 if (SMB_VFS_CHFLAGS(conn
, smb_fname
->base_name
,
7342 stat_fflags
) != 0) {
7343 return map_nt_error_from_unix(errno
);
7348 /* XXX: need to add support for changing the create_time here. You
7349 * can do this for paths on Darwin with setattrlist(2). The right way
7350 * to hook this up is probably by extending the VFS utimes interface.
7353 return NT_STATUS_OK
;
7356 /****************************************************************************
7357 Create a directory with POSIX semantics.
7358 ****************************************************************************/
7360 static NTSTATUS
smb_posix_mkdir(connection_struct
*conn
,
7361 struct smb_request
*req
,
7364 struct smb_filename
*smb_fname
,
7365 int *pdata_return_size
)
7367 NTSTATUS status
= NT_STATUS_OK
;
7368 uint32 raw_unixmode
= 0;
7369 uint32 mod_unixmode
= 0;
7370 mode_t unixmode
= (mode_t
)0;
7371 files_struct
*fsp
= NULL
;
7372 uint16 info_level_return
= 0;
7374 char *pdata
= *ppdata
;
7376 if (total_data
< 18) {
7377 return NT_STATUS_INVALID_PARAMETER
;
7380 raw_unixmode
= IVAL(pdata
,8);
7381 /* Next 4 bytes are not yet defined. */
7383 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
7384 PERM_NEW_DIR
, &unixmode
);
7385 if (!NT_STATUS_IS_OK(status
)) {
7389 mod_unixmode
= (uint32
)unixmode
| FILE_FLAG_POSIX_SEMANTICS
;
7391 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
7392 smb_fname_str_dbg(smb_fname
), (unsigned int)unixmode
));
7394 status
= SMB_VFS_CREATE_FILE(
7397 0, /* root_dir_fid */
7398 smb_fname
, /* fname */
7399 FILE_READ_ATTRIBUTES
, /* access_mask */
7400 FILE_SHARE_NONE
, /* share_access */
7401 FILE_CREATE
, /* create_disposition*/
7402 FILE_DIRECTORY_FILE
, /* create_options */
7403 mod_unixmode
, /* file_attributes */
7404 0, /* oplock_request */
7405 0, /* allocation_size */
7406 0, /* private_flags */
7412 if (NT_STATUS_IS_OK(status
)) {
7413 close_file(req
, fsp
, NORMAL_CLOSE
);
7416 info_level_return
= SVAL(pdata
,16);
7418 if (info_level_return
== SMB_QUERY_FILE_UNIX_BASIC
) {
7419 *pdata_return_size
= 12 + SMB_FILE_UNIX_BASIC_SIZE
;
7420 } else if (info_level_return
== SMB_QUERY_FILE_UNIX_INFO2
) {
7421 *pdata_return_size
= 12 + SMB_FILE_UNIX_INFO2_SIZE
;
7423 *pdata_return_size
= 12;
7426 /* Realloc the data size */
7427 *ppdata
= (char *)SMB_REALLOC(*ppdata
,*pdata_return_size
);
7428 if (*ppdata
== NULL
) {
7429 *pdata_return_size
= 0;
7430 return NT_STATUS_NO_MEMORY
;
7434 SSVAL(pdata
,0,NO_OPLOCK_RETURN
);
7435 SSVAL(pdata
,2,0); /* No fnum. */
7436 SIVAL(pdata
,4,info
); /* Was directory created. */
7438 switch (info_level_return
) {
7439 case SMB_QUERY_FILE_UNIX_BASIC
:
7440 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_BASIC
);
7441 SSVAL(pdata
,10,0); /* Padding. */
7442 store_file_unix_basic(conn
, pdata
+ 12, fsp
,
7445 case SMB_QUERY_FILE_UNIX_INFO2
:
7446 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_INFO2
);
7447 SSVAL(pdata
,10,0); /* Padding. */
7448 store_file_unix_basic_info2(conn
, pdata
+ 12, fsp
,
7452 SSVAL(pdata
,8,SMB_NO_INFO_LEVEL_RETURNED
);
7453 SSVAL(pdata
,10,0); /* Padding. */
7460 /****************************************************************************
7461 Open/Create a file with POSIX semantics.
7462 ****************************************************************************/
7464 #define SMB_O_RDONLY_MAPPING (FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA)
7465 #define SMB_O_WRONLY_MAPPING (FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA)
7467 static NTSTATUS
smb_posix_open(connection_struct
*conn
,
7468 struct smb_request
*req
,
7471 struct smb_filename
*smb_fname
,
7472 int *pdata_return_size
)
7474 bool extended_oplock_granted
= False
;
7475 char *pdata
= *ppdata
;
7477 uint32 wire_open_mode
= 0;
7478 uint32 raw_unixmode
= 0;
7479 uint32 mod_unixmode
= 0;
7480 uint32 create_disp
= 0;
7481 uint32 access_mask
= 0;
7482 uint32 create_options
= FILE_NON_DIRECTORY_FILE
;
7483 NTSTATUS status
= NT_STATUS_OK
;
7484 mode_t unixmode
= (mode_t
)0;
7485 files_struct
*fsp
= NULL
;
7486 int oplock_request
= 0;
7488 uint16 info_level_return
= 0;
7490 if (total_data
< 18) {
7491 return NT_STATUS_INVALID_PARAMETER
;
7494 flags
= IVAL(pdata
,0);
7495 oplock_request
= (flags
& REQUEST_OPLOCK
) ? EXCLUSIVE_OPLOCK
: 0;
7496 if (oplock_request
) {
7497 oplock_request
|= (flags
& REQUEST_BATCH_OPLOCK
) ? BATCH_OPLOCK
: 0;
7500 wire_open_mode
= IVAL(pdata
,4);
7502 if (wire_open_mode
== (SMB_O_CREAT
|SMB_O_DIRECTORY
)) {
7503 return smb_posix_mkdir(conn
, req
,
7510 switch (wire_open_mode
& SMB_ACCMODE
) {
7512 access_mask
= SMB_O_RDONLY_MAPPING
;
7515 access_mask
= SMB_O_WRONLY_MAPPING
;
7518 access_mask
= (SMB_O_RDONLY_MAPPING
|
7519 SMB_O_WRONLY_MAPPING
);
7522 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
7523 (unsigned int)wire_open_mode
));
7524 return NT_STATUS_INVALID_PARAMETER
;
7527 wire_open_mode
&= ~SMB_ACCMODE
;
7529 /* First take care of O_CREAT|O_EXCL interactions. */
7530 switch (wire_open_mode
& (SMB_O_CREAT
| SMB_O_EXCL
)) {
7531 case (SMB_O_CREAT
| SMB_O_EXCL
):
7532 /* File exists fail. File not exist create. */
7533 create_disp
= FILE_CREATE
;
7536 /* File exists open. File not exist create. */
7537 create_disp
= FILE_OPEN_IF
;
7540 /* O_EXCL on its own without O_CREAT is undefined.
7541 We deliberately ignore it as some versions of
7542 Linux CIFSFS can send a bare O_EXCL on the
7543 wire which other filesystems in the kernel
7544 ignore. See bug 9519 for details. */
7549 /* File exists open. File not exist fail. */
7550 create_disp
= FILE_OPEN
;
7553 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
7554 (unsigned int)wire_open_mode
));
7555 return NT_STATUS_INVALID_PARAMETER
;
7558 /* Next factor in the effects of O_TRUNC. */
7559 wire_open_mode
&= ~(SMB_O_CREAT
| SMB_O_EXCL
);
7561 if (wire_open_mode
& SMB_O_TRUNC
) {
7562 switch (create_disp
) {
7564 /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
7565 /* Leave create_disp alone as
7566 (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
7568 /* File exists fail. File not exist create. */
7571 /* SMB_O_CREAT | SMB_O_TRUNC */
7572 /* File exists overwrite. File not exist create. */
7573 create_disp
= FILE_OVERWRITE_IF
;
7577 /* File exists overwrite. File not exist fail. */
7578 create_disp
= FILE_OVERWRITE
;
7581 /* Cannot get here. */
7582 smb_panic("smb_posix_open: logic error");
7583 return NT_STATUS_INVALID_PARAMETER
;
7587 raw_unixmode
= IVAL(pdata
,8);
7588 /* Next 4 bytes are not yet defined. */
7590 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
7591 (VALID_STAT(smb_fname
->st
) ?
7592 PERM_EXISTING_FILE
: PERM_NEW_FILE
),
7595 if (!NT_STATUS_IS_OK(status
)) {
7599 mod_unixmode
= (uint32
)unixmode
| FILE_FLAG_POSIX_SEMANTICS
;
7601 if (wire_open_mode
& SMB_O_SYNC
) {
7602 create_options
|= FILE_WRITE_THROUGH
;
7604 if (wire_open_mode
& SMB_O_APPEND
) {
7605 access_mask
|= FILE_APPEND_DATA
;
7607 if (wire_open_mode
& SMB_O_DIRECT
) {
7608 mod_unixmode
|= FILE_FLAG_NO_BUFFERING
;
7611 if ((wire_open_mode
& SMB_O_DIRECTORY
) ||
7612 VALID_STAT_OF_DIR(smb_fname
->st
)) {
7613 if (access_mask
!= SMB_O_RDONLY_MAPPING
) {
7614 return NT_STATUS_FILE_IS_A_DIRECTORY
;
7616 create_options
&= ~FILE_NON_DIRECTORY_FILE
;
7617 create_options
|= FILE_DIRECTORY_FILE
;
7620 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
7621 smb_fname_str_dbg(smb_fname
),
7622 (unsigned int)wire_open_mode
,
7623 (unsigned int)unixmode
));
7625 status
= SMB_VFS_CREATE_FILE(
7628 0, /* root_dir_fid */
7629 smb_fname
, /* fname */
7630 access_mask
, /* access_mask */
7631 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
7633 create_disp
, /* create_disposition*/
7634 create_options
, /* create_options */
7635 mod_unixmode
, /* file_attributes */
7636 oplock_request
, /* oplock_request */
7637 0, /* allocation_size */
7638 0, /* private_flags */
7644 if (!NT_STATUS_IS_OK(status
)) {
7648 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
7649 extended_oplock_granted
= True
;
7652 if(oplock_request
&& EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
7653 extended_oplock_granted
= True
;
7656 info_level_return
= SVAL(pdata
,16);
7658 /* Allocate the correct return size. */
7660 if (info_level_return
== SMB_QUERY_FILE_UNIX_BASIC
) {
7661 *pdata_return_size
= 12 + SMB_FILE_UNIX_BASIC_SIZE
;
7662 } else if (info_level_return
== SMB_QUERY_FILE_UNIX_INFO2
) {
7663 *pdata_return_size
= 12 + SMB_FILE_UNIX_INFO2_SIZE
;
7665 *pdata_return_size
= 12;
7668 /* Realloc the data size */
7669 *ppdata
= (char *)SMB_REALLOC(*ppdata
,*pdata_return_size
);
7670 if (*ppdata
== NULL
) {
7671 close_file(req
, fsp
, ERROR_CLOSE
);
7672 *pdata_return_size
= 0;
7673 return NT_STATUS_NO_MEMORY
;
7677 if (extended_oplock_granted
) {
7678 if (flags
& REQUEST_BATCH_OPLOCK
) {
7679 SSVAL(pdata
,0, BATCH_OPLOCK_RETURN
);
7681 SSVAL(pdata
,0, EXCLUSIVE_OPLOCK_RETURN
);
7683 } else if (fsp
->oplock_type
== LEVEL_II_OPLOCK
) {
7684 SSVAL(pdata
,0, LEVEL_II_OPLOCK_RETURN
);
7686 SSVAL(pdata
,0,NO_OPLOCK_RETURN
);
7689 SSVAL(pdata
,2,fsp
->fnum
);
7690 SIVAL(pdata
,4,info
); /* Was file created etc. */
7692 switch (info_level_return
) {
7693 case SMB_QUERY_FILE_UNIX_BASIC
:
7694 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_BASIC
);
7695 SSVAL(pdata
,10,0); /* padding. */
7696 store_file_unix_basic(conn
, pdata
+ 12, fsp
,
7699 case SMB_QUERY_FILE_UNIX_INFO2
:
7700 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_INFO2
);
7701 SSVAL(pdata
,10,0); /* padding. */
7702 store_file_unix_basic_info2(conn
, pdata
+ 12, fsp
,
7706 SSVAL(pdata
,8,SMB_NO_INFO_LEVEL_RETURNED
);
7707 SSVAL(pdata
,10,0); /* padding. */
7710 return NT_STATUS_OK
;
7713 /****************************************************************************
7714 Delete a file with POSIX semantics.
7715 ****************************************************************************/
7717 static NTSTATUS
smb_posix_unlink(connection_struct
*conn
,
7718 struct smb_request
*req
,
7721 struct smb_filename
*smb_fname
)
7723 NTSTATUS status
= NT_STATUS_OK
;
7724 files_struct
*fsp
= NULL
;
7728 int create_options
= 0;
7730 struct share_mode_lock
*lck
= NULL
;
7732 if (total_data
< 2) {
7733 return NT_STATUS_INVALID_PARAMETER
;
7736 flags
= SVAL(pdata
,0);
7738 if (!VALID_STAT(smb_fname
->st
)) {
7739 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
7742 if ((flags
== SMB_POSIX_UNLINK_DIRECTORY_TARGET
) &&
7743 !VALID_STAT_OF_DIR(smb_fname
->st
)) {
7744 return NT_STATUS_NOT_A_DIRECTORY
;
7747 DEBUG(10,("smb_posix_unlink: %s %s\n",
7748 (flags
== SMB_POSIX_UNLINK_DIRECTORY_TARGET
) ? "directory" : "file",
7749 smb_fname_str_dbg(smb_fname
)));
7751 if (VALID_STAT_OF_DIR(smb_fname
->st
)) {
7752 create_options
|= FILE_DIRECTORY_FILE
;
7755 status
= SMB_VFS_CREATE_FILE(
7758 0, /* root_dir_fid */
7759 smb_fname
, /* fname */
7760 DELETE_ACCESS
, /* access_mask */
7761 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
7763 FILE_OPEN
, /* create_disposition*/
7764 create_options
, /* create_options */
7765 FILE_FLAG_POSIX_SEMANTICS
|0777, /* file_attributes */
7766 0, /* oplock_request */
7767 0, /* allocation_size */
7768 0, /* private_flags */
7774 if (!NT_STATUS_IS_OK(status
)) {
7779 * Don't lie to client. If we can't really delete due to
7780 * non-POSIX opens return SHARING_VIOLATION.
7783 lck
= get_existing_share_mode_lock(talloc_tos(), fsp
->file_id
);
7785 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
7786 "lock for file %s\n", fsp_str_dbg(fsp
)));
7787 close_file(req
, fsp
, NORMAL_CLOSE
);
7788 return NT_STATUS_INVALID_PARAMETER
;
7792 * See if others still have the file open. If this is the case, then
7793 * don't delete. If all opens are POSIX delete we can set the delete
7794 * on close disposition.
7796 for (i
=0; i
<lck
->data
->num_share_modes
; i
++) {
7797 struct share_mode_entry
*e
= &lck
->data
->share_modes
[i
];
7798 if (is_valid_share_mode_entry(e
)) {
7799 if (e
->flags
& SHARE_MODE_FLAG_POSIX_OPEN
) {
7802 if (share_mode_stale_pid(lck
->data
, i
)) {
7805 /* Fail with sharing violation. */
7807 close_file(req
, fsp
, NORMAL_CLOSE
);
7808 return NT_STATUS_SHARING_VIOLATION
;
7813 * Set the delete on close.
7815 status
= smb_set_file_disposition_info(conn
,
7823 if (!NT_STATUS_IS_OK(status
)) {
7824 close_file(req
, fsp
, NORMAL_CLOSE
);
7827 return close_file(req
, fsp
, NORMAL_CLOSE
);
7830 NTSTATUS
smbd_do_setfilepathinfo(connection_struct
*conn
,
7831 struct smb_request
*req
,
7832 TALLOC_CTX
*mem_ctx
,
7833 uint16_t info_level
,
7835 struct smb_filename
*smb_fname
,
7836 char **ppdata
, int total_data
,
7839 char *pdata
= *ppdata
;
7840 NTSTATUS status
= NT_STATUS_OK
;
7841 int data_return_size
= 0;
7845 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
7846 return NT_STATUS_INVALID_LEVEL
;
7849 if (!CAN_WRITE(conn
)) {
7850 /* Allow POSIX opens. The open path will deny
7851 * any non-readonly opens. */
7852 if (info_level
!= SMB_POSIX_PATH_OPEN
) {
7853 return NT_STATUS_DOS(ERRSRV
, ERRaccess
);
7857 DEBUG(3,("smbd_do_setfilepathinfo: %s (%s) info_level=%d "
7858 "totdata=%d\n", smb_fname_str_dbg(smb_fname
),
7860 info_level
, total_data
));
7862 switch (info_level
) {
7864 case SMB_INFO_STANDARD
:
7866 status
= smb_set_info_standard(conn
,
7874 case SMB_INFO_SET_EA
:
7876 status
= smb_info_set_ea(conn
,
7884 case SMB_SET_FILE_BASIC_INFO
:
7885 case SMB_FILE_BASIC_INFORMATION
:
7887 status
= smb_set_file_basic_info(conn
,
7895 case SMB_FILE_ALLOCATION_INFORMATION
:
7896 case SMB_SET_FILE_ALLOCATION_INFO
:
7898 status
= smb_set_file_allocation_info(conn
, req
,
7906 case SMB_FILE_END_OF_FILE_INFORMATION
:
7907 case SMB_SET_FILE_END_OF_FILE_INFO
:
7910 * XP/Win7 both fail after the createfile with
7911 * SMB_SET_FILE_END_OF_FILE_INFO but not
7912 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
7913 * The level is known here, so pass it down
7917 (info_level
== SMB_SET_FILE_END_OF_FILE_INFO
);
7919 status
= smb_set_file_end_of_file_info(conn
, req
,
7928 case SMB_FILE_DISPOSITION_INFORMATION
:
7929 case SMB_SET_FILE_DISPOSITION_INFO
: /* Set delete on close for open file. */
7932 /* JRA - We used to just ignore this on a path ?
7933 * Shouldn't this be invalid level on a pathname
7936 if (tran_call
!= TRANSACT2_SETFILEINFO
) {
7937 return ERROR_NT(NT_STATUS_INVALID_LEVEL
);
7940 status
= smb_set_file_disposition_info(conn
,
7948 case SMB_FILE_POSITION_INFORMATION
:
7950 status
= smb_file_position_information(conn
,
7957 case SMB_FILE_FULL_EA_INFORMATION
:
7959 status
= smb_set_file_full_ea_info(conn
,
7966 /* From tridge Samba4 :
7967 * MODE_INFORMATION in setfileinfo (I have no
7968 * idea what "mode information" on a file is - it takes a value of 0,
7969 * 2, 4 or 6. What could it be?).
7972 case SMB_FILE_MODE_INFORMATION
:
7974 status
= smb_file_mode_information(conn
,
7981 * CIFS UNIX extensions.
7984 case SMB_SET_FILE_UNIX_BASIC
:
7986 status
= smb_set_file_unix_basic(conn
, req
,
7994 case SMB_SET_FILE_UNIX_INFO2
:
7996 status
= smb_set_file_unix_info2(conn
, req
,
8004 case SMB_SET_FILE_UNIX_LINK
:
8007 /* We must have a pathname for this. */
8008 return NT_STATUS_INVALID_LEVEL
;
8010 status
= smb_set_file_unix_link(conn
, req
, pdata
,
8011 total_data
, smb_fname
);
8015 case SMB_SET_FILE_UNIX_HLINK
:
8018 /* We must have a pathname for this. */
8019 return NT_STATUS_INVALID_LEVEL
;
8021 status
= smb_set_file_unix_hlink(conn
, req
,
8027 case SMB_FILE_RENAME_INFORMATION
:
8029 status
= smb_file_rename_information(conn
, req
,
8035 case SMB2_FILE_RENAME_INFORMATION_INTERNAL
:
8037 /* SMB2 rename information. */
8038 status
= smb2_file_rename_information(conn
, req
,
8044 case SMB_FILE_LINK_INFORMATION
:
8046 status
= smb_file_link_information(conn
, req
,
8052 #if defined(HAVE_POSIX_ACLS)
8053 case SMB_SET_POSIX_ACL
:
8055 status
= smb_set_posix_acl(conn
,
8064 case SMB_SET_POSIX_LOCK
:
8067 return NT_STATUS_INVALID_LEVEL
;
8069 status
= smb_set_posix_lock(conn
, req
,
8070 pdata
, total_data
, fsp
);
8074 case SMB_POSIX_PATH_OPEN
:
8077 /* We must have a pathname for this. */
8078 return NT_STATUS_INVALID_LEVEL
;
8081 status
= smb_posix_open(conn
, req
,
8089 case SMB_POSIX_PATH_UNLINK
:
8092 /* We must have a pathname for this. */
8093 return NT_STATUS_INVALID_LEVEL
;
8096 status
= smb_posix_unlink(conn
, req
,
8104 return NT_STATUS_INVALID_LEVEL
;
8107 if (!NT_STATUS_IS_OK(status
)) {
8111 *ret_data_size
= data_return_size
;
8112 return NT_STATUS_OK
;
8115 /****************************************************************************
8116 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
8117 ****************************************************************************/
8119 static void call_trans2setfilepathinfo(connection_struct
*conn
,
8120 struct smb_request
*req
,
8121 unsigned int tran_call
,
8122 char **pparams
, int total_params
,
8123 char **ppdata
, int total_data
,
8124 unsigned int max_data_bytes
)
8126 char *params
= *pparams
;
8127 char *pdata
= *ppdata
;
8129 struct smb_filename
*smb_fname
= NULL
;
8130 files_struct
*fsp
= NULL
;
8131 NTSTATUS status
= NT_STATUS_OK
;
8132 int data_return_size
= 0;
8135 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8139 if (tran_call
== TRANSACT2_SETFILEINFO
) {
8140 if (total_params
< 4) {
8141 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8145 fsp
= file_fsp(req
, SVAL(params
,0));
8146 /* Basic check for non-null fsp. */
8147 if (!check_fsp_open(conn
, req
, fsp
)) {
8150 info_level
= SVAL(params
,2);
8152 smb_fname
= cp_smb_filename(talloc_tos(), fsp
->fsp_name
);
8153 if (smb_fname
== NULL
) {
8154 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8158 if(fsp
->fh
->fd
== -1) {
8160 * This is actually a SETFILEINFO on a directory
8161 * handle (returned from an NT SMB). NT5.0 seems
8162 * to do this call. JRA.
8164 if (INFO_LEVEL_IS_UNIX(info_level
)) {
8165 /* Always do lstat for UNIX calls. */
8166 if (SMB_VFS_LSTAT(conn
, smb_fname
)) {
8167 DEBUG(3,("call_trans2setfilepathinfo: "
8168 "SMB_VFS_LSTAT of %s failed "
8170 smb_fname_str_dbg(smb_fname
),
8172 reply_nterror(req
, map_nt_error_from_unix(errno
));
8176 if (SMB_VFS_STAT(conn
, smb_fname
) != 0) {
8177 DEBUG(3,("call_trans2setfilepathinfo: "
8178 "fileinfo of %s failed (%s)\n",
8179 smb_fname_str_dbg(smb_fname
),
8181 reply_nterror(req
, map_nt_error_from_unix(errno
));
8185 } else if (fsp
->print_file
) {
8187 * Doing a DELETE_ON_CLOSE should cancel a print job.
8189 if ((info_level
== SMB_SET_FILE_DISPOSITION_INFO
) && CVAL(pdata
,0)) {
8190 fsp
->fh
->private_options
|= NTCREATEX_OPTIONS_PRIVATE_DELETE_ON_CLOSE
;
8192 DEBUG(3,("call_trans2setfilepathinfo: "
8193 "Cancelling print job (%s)\n",
8197 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 2,
8203 NT_STATUS_OBJECT_PATH_NOT_FOUND
);
8208 * Original code - this is an open file.
8210 if (SMB_VFS_FSTAT(fsp
, &smb_fname
->st
) != 0) {
8211 DEBUG(3,("call_trans2setfilepathinfo: fstat "
8212 "of %s failed (%s)\n", fsp_fnum_dbg(fsp
),
8214 reply_nterror(req
, map_nt_error_from_unix(errno
));
8220 uint32_t ucf_flags
= 0;
8223 if (total_params
< 7) {
8224 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8228 info_level
= SVAL(params
,0);
8229 srvstr_get_path(req
, params
, req
->flags2
, &fname
, ¶ms
[6],
8230 total_params
- 6, STR_TERMINATE
,
8232 if (!NT_STATUS_IS_OK(status
)) {
8233 reply_nterror(req
, status
);
8237 if (info_level
== SMB_SET_FILE_UNIX_BASIC
||
8238 info_level
== SMB_SET_FILE_UNIX_INFO2
||
8239 info_level
== SMB_FILE_RENAME_INFORMATION
||
8240 info_level
== SMB_POSIX_PATH_UNLINK
) {
8241 ucf_flags
|= UCF_UNIX_NAME_LOOKUP
;
8244 status
= filename_convert(req
, conn
,
8245 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
8250 if (!NT_STATUS_IS_OK(status
)) {
8251 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
8252 reply_botherror(req
,
8253 NT_STATUS_PATH_NOT_COVERED
,
8254 ERRSRV
, ERRbadpath
);
8257 reply_nterror(req
, status
);
8261 if (INFO_LEVEL_IS_UNIX(info_level
)) {
8263 * For CIFS UNIX extensions the target name may not exist.
8266 /* Always do lstat for UNIX calls. */
8267 SMB_VFS_LSTAT(conn
, smb_fname
);
8269 } else if (!VALID_STAT(smb_fname
->st
) &&
8270 SMB_VFS_STAT(conn
, smb_fname
)) {
8271 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
8273 smb_fname_str_dbg(smb_fname
),
8275 reply_nterror(req
, map_nt_error_from_unix(errno
));
8280 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (%s) info_level=%d "
8281 "totdata=%d\n", tran_call
, smb_fname_str_dbg(smb_fname
),
8283 info_level
,total_data
));
8285 /* Realloc the parameter size */
8286 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
8287 if (*pparams
== NULL
) {
8288 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8295 status
= smbd_do_setfilepathinfo(conn
, req
, req
,
8301 if (!NT_STATUS_IS_OK(status
)) {
8302 if (open_was_deferred(req
->sconn
, req
->mid
)) {
8303 /* We have re-scheduled this call. */
8306 if (blocking_lock_was_deferred_smb1(req
->sconn
, req
->mid
)) {
8307 /* We have re-scheduled this call. */
8310 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
8311 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
8312 ERRSRV
, ERRbadpath
);
8315 if (info_level
== SMB_POSIX_PATH_OPEN
) {
8316 reply_openerror(req
, status
);
8321 * Invalid EA name needs to return 2 param bytes,
8322 * not a zero-length error packet.
8324 if (NT_STATUS_EQUAL(status
, STATUS_INVALID_EA_NAME
)) {
8325 send_trans2_replies(conn
, req
, status
, params
, 2, NULL
, 0,
8328 reply_nterror(req
, status
);
8333 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 2, *ppdata
, data_return_size
,
8339 /****************************************************************************
8340 Reply to a TRANS2_MKDIR (make directory with extended attributes).
8341 ****************************************************************************/
8343 static void call_trans2mkdir(connection_struct
*conn
, struct smb_request
*req
,
8344 char **pparams
, int total_params
,
8345 char **ppdata
, int total_data
,
8346 unsigned int max_data_bytes
)
8348 struct smb_filename
*smb_dname
= NULL
;
8349 char *params
= *pparams
;
8350 char *pdata
= *ppdata
;
8351 char *directory
= NULL
;
8352 NTSTATUS status
= NT_STATUS_OK
;
8353 struct ea_list
*ea_list
= NULL
;
8354 TALLOC_CTX
*ctx
= talloc_tos();
8356 if (!CAN_WRITE(conn
)) {
8357 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
8361 if (total_params
< 5) {
8362 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8366 srvstr_get_path(ctx
, params
, req
->flags2
, &directory
, ¶ms
[4],
8367 total_params
- 4, STR_TERMINATE
,
8369 if (!NT_STATUS_IS_OK(status
)) {
8370 reply_nterror(req
, status
);
8374 DEBUG(3,("call_trans2mkdir : name = %s\n", directory
));
8376 status
= filename_convert(ctx
,
8378 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
8384 if (!NT_STATUS_IS_OK(status
)) {
8385 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
8386 reply_botherror(req
,
8387 NT_STATUS_PATH_NOT_COVERED
,
8388 ERRSRV
, ERRbadpath
);
8391 reply_nterror(req
, status
);
8396 * OS/2 workplace shell seems to send SET_EA requests of "null"
8397 * length (4 bytes containing IVAL 4).
8398 * They seem to have no effect. Bug #3212. JRA.
8401 if (total_data
&& (total_data
!= 4)) {
8402 /* Any data in this call is an EA list. */
8403 if (total_data
< 10) {
8404 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8408 if (IVAL(pdata
,0) > total_data
) {
8409 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
8410 IVAL(pdata
,0), (unsigned int)total_data
));
8411 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8415 ea_list
= read_ea_list(talloc_tos(), pdata
+ 4,
8418 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8422 if (!lp_ea_support(SNUM(conn
))) {
8423 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
8427 /* If total_data == 4 Windows doesn't care what values
8428 * are placed in that field, it just ignores them.
8429 * The System i QNTC IBM SMB client puts bad values here,
8430 * so ignore them. */
8432 status
= create_directory(conn
, req
, smb_dname
);
8434 if (!NT_STATUS_IS_OK(status
)) {
8435 reply_nterror(req
, status
);
8439 /* Try and set any given EA. */
8441 status
= set_ea(conn
, NULL
, smb_dname
, ea_list
);
8442 if (!NT_STATUS_IS_OK(status
)) {
8443 reply_nterror(req
, status
);
8448 /* Realloc the parameter and data sizes */
8449 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
8450 if(*pparams
== NULL
) {
8451 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8458 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 2, *ppdata
, 0, max_data_bytes
);
8461 TALLOC_FREE(smb_dname
);
8465 /****************************************************************************
8466 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
8467 We don't actually do this - we just send a null response.
8468 ****************************************************************************/
8470 static void call_trans2findnotifyfirst(connection_struct
*conn
,
8471 struct smb_request
*req
,
8472 char **pparams
, int total_params
,
8473 char **ppdata
, int total_data
,
8474 unsigned int max_data_bytes
)
8476 char *params
= *pparams
;
8479 if (total_params
< 6) {
8480 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8484 info_level
= SVAL(params
,4);
8485 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level
));
8487 switch (info_level
) {
8492 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
8496 /* Realloc the parameter and data sizes */
8497 *pparams
= (char *)SMB_REALLOC(*pparams
,6);
8498 if (*pparams
== NULL
) {
8499 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8504 SSVAL(params
,0,fnf_handle
);
8505 SSVAL(params
,2,0); /* No changes */
8506 SSVAL(params
,4,0); /* No EA errors */
8513 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 6, *ppdata
, 0, max_data_bytes
);
8518 /****************************************************************************
8519 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
8520 changes). Currently this does nothing.
8521 ****************************************************************************/
8523 static void call_trans2findnotifynext(connection_struct
*conn
,
8524 struct smb_request
*req
,
8525 char **pparams
, int total_params
,
8526 char **ppdata
, int total_data
,
8527 unsigned int max_data_bytes
)
8529 char *params
= *pparams
;
8531 DEBUG(3,("call_trans2findnotifynext\n"));
8533 /* Realloc the parameter and data sizes */
8534 *pparams
= (char *)SMB_REALLOC(*pparams
,4);
8535 if (*pparams
== NULL
) {
8536 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8541 SSVAL(params
,0,0); /* No changes */
8542 SSVAL(params
,2,0); /* No EA errors */
8544 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 4, *ppdata
, 0, max_data_bytes
);
8549 /****************************************************************************
8550 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
8551 ****************************************************************************/
8553 static void call_trans2getdfsreferral(connection_struct
*conn
,
8554 struct smb_request
*req
,
8555 char **pparams
, int total_params
,
8556 char **ppdata
, int total_data
,
8557 unsigned int max_data_bytes
)
8559 char *params
= *pparams
;
8560 char *pathname
= NULL
;
8562 int max_referral_level
;
8563 NTSTATUS status
= NT_STATUS_OK
;
8564 TALLOC_CTX
*ctx
= talloc_tos();
8566 DEBUG(10,("call_trans2getdfsreferral\n"));
8568 if (total_params
< 3) {
8569 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8573 max_referral_level
= SVAL(params
,0);
8575 if(!lp_host_msdfs()) {
8576 reply_nterror(req
, NT_STATUS_NOT_IMPLEMENTED
);
8580 srvstr_pull_talloc(ctx
, params
, req
->flags2
, &pathname
, ¶ms
[2],
8581 total_params
- 2, STR_TERMINATE
);
8583 reply_nterror(req
, NT_STATUS_NOT_FOUND
);
8586 if((reply_size
= setup_dfs_referral(conn
, pathname
, max_referral_level
,
8587 ppdata
,&status
)) < 0) {
8588 reply_nterror(req
, status
);
8592 SSVAL((discard_const_p(uint8_t, req
->inbuf
)), smb_flg2
,
8593 SVAL(req
->inbuf
,smb_flg2
) | FLAGS2_DFS_PATHNAMES
);
8594 send_trans2_replies(conn
, req
, NT_STATUS_OK
, 0,0,*ppdata
,reply_size
, max_data_bytes
);
8599 #define LMCAT_SPL 0x53
8600 #define LMFUNC_GETJOBID 0x60
8602 /****************************************************************************
8603 Reply to a TRANS2_IOCTL - used for OS/2 printing.
8604 ****************************************************************************/
8606 static void call_trans2ioctl(connection_struct
*conn
,
8607 struct smb_request
*req
,
8608 char **pparams
, int total_params
,
8609 char **ppdata
, int total_data
,
8610 unsigned int max_data_bytes
)
8612 char *pdata
= *ppdata
;
8613 files_struct
*fsp
= file_fsp(req
, SVAL(req
->vwv
+15, 0));
8615 /* check for an invalid fid before proceeding */
8618 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
8622 if ((SVAL(req
->vwv
+16, 0) == LMCAT_SPL
)
8623 && (SVAL(req
->vwv
+17, 0) == LMFUNC_GETJOBID
)) {
8624 *ppdata
= (char *)SMB_REALLOC(*ppdata
, 32);
8625 if (*ppdata
== NULL
) {
8626 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8631 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
8632 CAN ACCEPT THIS IN UNICODE. JRA. */
8635 SSVAL(pdata
, 0, print_spool_rap_jobid(fsp
->print_file
));
8637 srvstr_push(pdata
, req
->flags2
, pdata
+ 2,
8638 lp_netbios_name(), 15,
8639 STR_ASCII
|STR_TERMINATE
); /* Our NetBIOS name */
8640 srvstr_push(pdata
, req
->flags2
, pdata
+18,
8641 lp_servicename(talloc_tos(), SNUM(conn
)), 13,
8642 STR_ASCII
|STR_TERMINATE
); /* Service name */
8643 send_trans2_replies(conn
, req
, NT_STATUS_OK
, *pparams
, 0, *ppdata
, 32,
8648 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
8649 reply_nterror(req
, NT_STATUS_NOT_IMPLEMENTED
);
8652 /****************************************************************************
8653 Reply to a SMBfindclose (stop trans2 directory search).
8654 ****************************************************************************/
8656 void reply_findclose(struct smb_request
*req
)
8659 struct smbd_server_connection
*sconn
= req
->sconn
;
8661 START_PROFILE(SMBfindclose
);
8664 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8665 END_PROFILE(SMBfindclose
);
8669 dptr_num
= SVALS(req
->vwv
+0, 0);
8671 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num
));
8673 dptr_close(sconn
, &dptr_num
);
8675 reply_outbuf(req
, 0, 0);
8677 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num
));
8679 END_PROFILE(SMBfindclose
);
8683 /****************************************************************************
8684 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
8685 ****************************************************************************/
8687 void reply_findnclose(struct smb_request
*req
)
8691 START_PROFILE(SMBfindnclose
);
8694 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8695 END_PROFILE(SMBfindnclose
);
8699 dptr_num
= SVAL(req
->vwv
+0, 0);
8701 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num
));
8703 /* We never give out valid handles for a
8704 findnotifyfirst - so any dptr_num is ok here.
8707 reply_outbuf(req
, 0, 0);
8709 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num
));
8711 END_PROFILE(SMBfindnclose
);
8715 static void handle_trans2(connection_struct
*conn
, struct smb_request
*req
,
8716 struct trans_state
*state
)
8718 if (get_Protocol() >= PROTOCOL_NT1
) {
8719 req
->flags2
|= 0x40; /* IS_LONG_NAME */
8720 SSVAL((discard_const_p(uint8_t, req
->inbuf
)),smb_flg2
,req
->flags2
);
8723 if (ENCRYPTION_REQUIRED(conn
) && !req
->encrypted
) {
8724 if (state
->call
!= TRANSACT2_QFSINFO
&&
8725 state
->call
!= TRANSACT2_SETFSINFO
) {
8726 DEBUG(0,("handle_trans2: encryption required "
8728 (unsigned int)state
->call
));
8729 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
8734 SMB_PERFCOUNT_SET_SUBOP(&req
->pcd
, state
->call
);
8736 /* Now we must call the relevant TRANS2 function */
8737 switch(state
->call
) {
8738 case TRANSACT2_OPEN
:
8740 START_PROFILE(Trans2_open
);
8741 call_trans2open(conn
, req
,
8742 &state
->param
, state
->total_param
,
8743 &state
->data
, state
->total_data
,
8744 state
->max_data_return
);
8745 END_PROFILE(Trans2_open
);
8749 case TRANSACT2_FINDFIRST
:
8751 START_PROFILE(Trans2_findfirst
);
8752 call_trans2findfirst(conn
, req
,
8753 &state
->param
, state
->total_param
,
8754 &state
->data
, state
->total_data
,
8755 state
->max_data_return
);
8756 END_PROFILE(Trans2_findfirst
);
8760 case TRANSACT2_FINDNEXT
:
8762 START_PROFILE(Trans2_findnext
);
8763 call_trans2findnext(conn
, req
,
8764 &state
->param
, state
->total_param
,
8765 &state
->data
, state
->total_data
,
8766 state
->max_data_return
);
8767 END_PROFILE(Trans2_findnext
);
8771 case TRANSACT2_QFSINFO
:
8773 START_PROFILE(Trans2_qfsinfo
);
8774 call_trans2qfsinfo(conn
, req
,
8775 &state
->param
, state
->total_param
,
8776 &state
->data
, state
->total_data
,
8777 state
->max_data_return
);
8778 END_PROFILE(Trans2_qfsinfo
);
8782 case TRANSACT2_SETFSINFO
:
8784 START_PROFILE(Trans2_setfsinfo
);
8785 call_trans2setfsinfo(conn
, req
,
8786 &state
->param
, state
->total_param
,
8787 &state
->data
, state
->total_data
,
8788 state
->max_data_return
);
8789 END_PROFILE(Trans2_setfsinfo
);
8793 case TRANSACT2_QPATHINFO
:
8794 case TRANSACT2_QFILEINFO
:
8796 START_PROFILE(Trans2_qpathinfo
);
8797 call_trans2qfilepathinfo(conn
, req
, state
->call
,
8798 &state
->param
, state
->total_param
,
8799 &state
->data
, state
->total_data
,
8800 state
->max_data_return
);
8801 END_PROFILE(Trans2_qpathinfo
);
8805 case TRANSACT2_SETPATHINFO
:
8806 case TRANSACT2_SETFILEINFO
:
8808 START_PROFILE(Trans2_setpathinfo
);
8809 call_trans2setfilepathinfo(conn
, req
, state
->call
,
8810 &state
->param
, state
->total_param
,
8811 &state
->data
, state
->total_data
,
8812 state
->max_data_return
);
8813 END_PROFILE(Trans2_setpathinfo
);
8817 case TRANSACT2_FINDNOTIFYFIRST
:
8819 START_PROFILE(Trans2_findnotifyfirst
);
8820 call_trans2findnotifyfirst(conn
, req
,
8821 &state
->param
, state
->total_param
,
8822 &state
->data
, state
->total_data
,
8823 state
->max_data_return
);
8824 END_PROFILE(Trans2_findnotifyfirst
);
8828 case TRANSACT2_FINDNOTIFYNEXT
:
8830 START_PROFILE(Trans2_findnotifynext
);
8831 call_trans2findnotifynext(conn
, req
,
8832 &state
->param
, state
->total_param
,
8833 &state
->data
, state
->total_data
,
8834 state
->max_data_return
);
8835 END_PROFILE(Trans2_findnotifynext
);
8839 case TRANSACT2_MKDIR
:
8841 START_PROFILE(Trans2_mkdir
);
8842 call_trans2mkdir(conn
, req
,
8843 &state
->param
, state
->total_param
,
8844 &state
->data
, state
->total_data
,
8845 state
->max_data_return
);
8846 END_PROFILE(Trans2_mkdir
);
8850 case TRANSACT2_GET_DFS_REFERRAL
:
8852 START_PROFILE(Trans2_get_dfs_referral
);
8853 call_trans2getdfsreferral(conn
, req
,
8854 &state
->param
, state
->total_param
,
8855 &state
->data
, state
->total_data
,
8856 state
->max_data_return
);
8857 END_PROFILE(Trans2_get_dfs_referral
);
8861 case TRANSACT2_IOCTL
:
8863 START_PROFILE(Trans2_ioctl
);
8864 call_trans2ioctl(conn
, req
,
8865 &state
->param
, state
->total_param
,
8866 &state
->data
, state
->total_data
,
8867 state
->max_data_return
);
8868 END_PROFILE(Trans2_ioctl
);
8873 /* Error in request */
8874 DEBUG(2,("Unknown request %d in trans2 call\n", state
->call
));
8875 reply_nterror(req
, NT_STATUS_NOT_IMPLEMENTED
);
8879 /****************************************************************************
8880 Reply to a SMBtrans2.
8881 ****************************************************************************/
8883 void reply_trans2(struct smb_request
*req
)
8885 connection_struct
*conn
= req
->conn
;
8890 unsigned int tran_call
;
8891 struct trans_state
*state
;
8894 START_PROFILE(SMBtrans2
);
8896 if (req
->wct
< 14) {
8897 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8898 END_PROFILE(SMBtrans2
);
8902 dsoff
= SVAL(req
->vwv
+12, 0);
8903 dscnt
= SVAL(req
->vwv
+11, 0);
8904 psoff
= SVAL(req
->vwv
+10, 0);
8905 pscnt
= SVAL(req
->vwv
+9, 0);
8906 tran_call
= SVAL(req
->vwv
+14, 0);
8908 result
= allow_new_trans(conn
->pending_trans
, req
->mid
);
8909 if (!NT_STATUS_IS_OK(result
)) {
8910 DEBUG(2, ("Got invalid trans2 request: %s\n",
8911 nt_errstr(result
)));
8912 reply_nterror(req
, result
);
8913 END_PROFILE(SMBtrans2
);
8918 switch (tran_call
) {
8919 /* List the allowed trans2 calls on IPC$ */
8920 case TRANSACT2_OPEN
:
8921 case TRANSACT2_GET_DFS_REFERRAL
:
8922 case TRANSACT2_QFILEINFO
:
8923 case TRANSACT2_QFSINFO
:
8924 case TRANSACT2_SETFSINFO
:
8927 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
8928 END_PROFILE(SMBtrans2
);
8933 if ((state
= talloc(conn
, struct trans_state
)) == NULL
) {
8934 DEBUG(0, ("talloc failed\n"));
8935 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8936 END_PROFILE(SMBtrans2
);
8940 state
->cmd
= SMBtrans2
;
8942 state
->mid
= req
->mid
;
8943 state
->vuid
= req
->vuid
;
8944 state
->setup_count
= SVAL(req
->vwv
+13, 0);
8945 state
->setup
= NULL
;
8946 state
->total_param
= SVAL(req
->vwv
+0, 0);
8947 state
->param
= NULL
;
8948 state
->total_data
= SVAL(req
->vwv
+1, 0);
8950 state
->max_param_return
= SVAL(req
->vwv
+2, 0);
8951 state
->max_data_return
= SVAL(req
->vwv
+3, 0);
8952 state
->max_setup_return
= SVAL(req
->vwv
+4, 0);
8953 state
->close_on_completion
= BITSETW(req
->vwv
+5, 0);
8954 state
->one_way
= BITSETW(req
->vwv
+5, 1);
8956 state
->call
= tran_call
;
8958 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
8959 is so as a sanity check */
8960 if (state
->setup_count
!= 1) {
8962 * Need to have rc=0 for ioctl to get job id for OS/2.
8963 * Network printing will fail if function is not successful.
8964 * Similar function in reply.c will be used if protocol
8965 * is LANMAN1.0 instead of LM1.2X002.
8966 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
8967 * outbuf doesn't have to be set(only job id is used).
8969 if ( (state
->setup_count
== 4)
8970 && (tran_call
== TRANSACT2_IOCTL
)
8971 && (SVAL(req
->vwv
+16, 0) == LMCAT_SPL
)
8972 && (SVAL(req
->vwv
+17, 0) == LMFUNC_GETJOBID
)) {
8973 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
8975 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state
->setup_count
));
8976 DEBUG(2,("Transaction is %d\n",tran_call
));
8978 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8979 END_PROFILE(SMBtrans2
);
8984 if ((dscnt
> state
->total_data
) || (pscnt
> state
->total_param
))
8987 if (state
->total_data
) {
8989 if (trans_oob(state
->total_data
, 0, dscnt
)
8990 || trans_oob(smb_len(req
->inbuf
), dsoff
, dscnt
)) {
8994 /* Can't use talloc here, the core routines do realloc on the
8995 * params and data. */
8996 state
->data
= (char *)SMB_MALLOC(state
->total_data
);
8997 if (state
->data
== NULL
) {
8998 DEBUG(0,("reply_trans2: data malloc fail for %u "
8999 "bytes !\n", (unsigned int)state
->total_data
));
9001 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
9002 END_PROFILE(SMBtrans2
);
9006 memcpy(state
->data
,smb_base(req
->inbuf
)+dsoff
,dscnt
);
9009 if (state
->total_param
) {
9011 if (trans_oob(state
->total_param
, 0, pscnt
)
9012 || trans_oob(smb_len(req
->inbuf
), psoff
, pscnt
)) {
9016 /* Can't use talloc here, the core routines do realloc on the
9017 * params and data. */
9018 state
->param
= (char *)SMB_MALLOC(state
->total_param
);
9019 if (state
->param
== NULL
) {
9020 DEBUG(0,("reply_trans: param malloc fail for %u "
9021 "bytes !\n", (unsigned int)state
->total_param
));
9022 SAFE_FREE(state
->data
);
9024 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
9025 END_PROFILE(SMBtrans2
);
9029 memcpy(state
->param
,smb_base(req
->inbuf
)+psoff
,pscnt
);
9032 state
->received_data
= dscnt
;
9033 state
->received_param
= pscnt
;
9035 if ((state
->received_param
== state
->total_param
) &&
9036 (state
->received_data
== state
->total_data
)) {
9038 handle_trans2(conn
, req
, state
);
9040 SAFE_FREE(state
->data
);
9041 SAFE_FREE(state
->param
);
9043 END_PROFILE(SMBtrans2
);
9047 DLIST_ADD(conn
->pending_trans
, state
);
9049 /* We need to send an interim response then receive the rest
9050 of the parameter/data bytes */
9051 reply_outbuf(req
, 0, 0);
9052 show_msg((char *)req
->outbuf
);
9053 END_PROFILE(SMBtrans2
);
9058 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
9059 SAFE_FREE(state
->data
);
9060 SAFE_FREE(state
->param
);
9062 END_PROFILE(SMBtrans2
);
9063 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
9067 /****************************************************************************
9068 Reply to a SMBtranss2
9069 ****************************************************************************/
9071 void reply_transs2(struct smb_request
*req
)
9073 connection_struct
*conn
= req
->conn
;
9074 unsigned int pcnt
,poff
,dcnt
,doff
,pdisp
,ddisp
;
9075 struct trans_state
*state
;
9077 START_PROFILE(SMBtranss2
);
9079 show_msg((const char *)req
->inbuf
);
9081 /* Windows clients expect all replies to
9082 a transact secondary (SMBtranss2 0x33)
9083 to have a command code of transact
9084 (SMBtrans2 0x32). See bug #8989
9085 and also [MS-CIFS] section 2.2.4.47.2
9088 req
->cmd
= SMBtrans2
;
9091 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
9092 END_PROFILE(SMBtranss2
);
9096 for (state
= conn
->pending_trans
; state
!= NULL
;
9097 state
= state
->next
) {
9098 if (state
->mid
== req
->mid
) {
9103 if ((state
== NULL
) || (state
->cmd
!= SMBtrans2
)) {
9104 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
9105 END_PROFILE(SMBtranss2
);
9109 /* Revise state->total_param and state->total_data in case they have
9110 changed downwards */
9112 if (SVAL(req
->vwv
+0, 0) < state
->total_param
)
9113 state
->total_param
= SVAL(req
->vwv
+0, 0);
9114 if (SVAL(req
->vwv
+1, 0) < state
->total_data
)
9115 state
->total_data
= SVAL(req
->vwv
+1, 0);
9117 pcnt
= SVAL(req
->vwv
+2, 0);
9118 poff
= SVAL(req
->vwv
+3, 0);
9119 pdisp
= SVAL(req
->vwv
+4, 0);
9121 dcnt
= SVAL(req
->vwv
+5, 0);
9122 doff
= SVAL(req
->vwv
+6, 0);
9123 ddisp
= SVAL(req
->vwv
+7, 0);
9125 state
->received_param
+= pcnt
;
9126 state
->received_data
+= dcnt
;
9128 if ((state
->received_data
> state
->total_data
) ||
9129 (state
->received_param
> state
->total_param
))
9133 if (trans_oob(state
->total_param
, pdisp
, pcnt
)
9134 || trans_oob(smb_len(req
->inbuf
), poff
, pcnt
)) {
9137 memcpy(state
->param
+pdisp
,smb_base(req
->inbuf
)+poff
,pcnt
);
9141 if (trans_oob(state
->total_data
, ddisp
, dcnt
)
9142 || trans_oob(smb_len(req
->inbuf
), doff
, dcnt
)) {
9145 memcpy(state
->data
+ddisp
, smb_base(req
->inbuf
)+doff
,dcnt
);
9148 if ((state
->received_param
< state
->total_param
) ||
9149 (state
->received_data
< state
->total_data
)) {
9150 END_PROFILE(SMBtranss2
);
9154 handle_trans2(conn
, req
, state
);
9156 DLIST_REMOVE(conn
->pending_trans
, state
);
9157 SAFE_FREE(state
->data
);
9158 SAFE_FREE(state
->param
);
9161 END_PROFILE(SMBtranss2
);
9166 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
9167 DLIST_REMOVE(conn
->pending_trans
, state
);
9168 SAFE_FREE(state
->data
);
9169 SAFE_FREE(state
->param
);
9171 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
9172 END_PROFILE(SMBtranss2
);