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 smbXsrv_connection
*xconn
= req
->xconn
;
863 struct smbd_server_connection
*sconn
= xconn
->sconn
;
864 int max_send
= xconn
->smb1
.sessions
.max_send
;
866 /* Modify the data_to_send and datasize and set the error if
867 we're trying to send more than max_data_bytes. We still send
868 the part of the packet(s) that fit. Strange, but needed
871 if (max_data_bytes
> 0 && datasize
> max_data_bytes
) {
872 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
873 max_data_bytes
, datasize
));
874 datasize
= data_to_send
= max_data_bytes
;
878 /* If there genuinely are no parameters or data to send just send the empty packet */
880 if(params_to_send
== 0 && data_to_send
== 0) {
881 reply_outbuf(req
, 10, 0);
882 if (NT_STATUS_V(status
)) {
885 ntstatus_to_dos(status
, &eclass
, &ecode
);
886 error_packet_set((char *)req
->outbuf
,
887 eclass
, ecode
, status
,
890 show_msg((char *)req
->outbuf
);
891 if (!srv_send_smb(sconn
,
894 IS_CONN_ENCRYPTED(conn
),
896 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
898 TALLOC_FREE(req
->outbuf
);
902 /* When sending params and data ensure that both are nicely aligned */
903 /* Only do this alignment when there is also data to send - else
904 can cause NT redirector problems. */
906 if (((params_to_send
% 4) != 0) && (data_to_send
!= 0))
907 data_alignment_offset
= 4 - (params_to_send
% 4);
909 /* Space is bufsize minus Netbios over TCP header minus SMB header */
910 /* The alignment_offset is to align the param bytes on an even byte
911 boundary. NT 4.0 Beta needs this to work correctly. */
913 useable_space
= max_send
- (smb_size
916 + data_alignment_offset
);
918 if (useable_space
< 0) {
919 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
920 "= %d!!!", useable_space
));
921 exit_server_cleanly("send_trans2_replies: Not enough space");
924 while (params_to_send
|| data_to_send
) {
925 /* Calculate whether we will totally or partially fill this packet */
927 total_sent_thistime
= params_to_send
+ data_to_send
;
929 /* We can never send more than useable_space */
931 * Note that 'useable_space' does not include the alignment offsets,
932 * but we must include the alignment offsets in the calculation of
933 * the length of the data we send over the wire, as the alignment offsets
934 * are sent here. Fix from Marc_Jacobsen@hp.com.
937 total_sent_thistime
= MIN(total_sent_thistime
, useable_space
);
939 reply_outbuf(req
, 10, total_sent_thistime
+ alignment_offset
940 + data_alignment_offset
);
942 /* Set total params and data to be sent */
943 SSVAL(req
->outbuf
,smb_tprcnt
,paramsize
);
944 SSVAL(req
->outbuf
,smb_tdrcnt
,datasize
);
946 /* Calculate how many parameters and data we can fit into
947 * this packet. Parameters get precedence
950 params_sent_thistime
= MIN(params_to_send
,useable_space
);
951 data_sent_thistime
= useable_space
- params_sent_thistime
;
952 data_sent_thistime
= MIN(data_sent_thistime
,data_to_send
);
954 SSVAL(req
->outbuf
,smb_prcnt
, params_sent_thistime
);
956 /* smb_proff is the offset from the start of the SMB header to the
957 parameter bytes, however the first 4 bytes of outbuf are
958 the Netbios over TCP header. Thus use smb_base() to subtract
959 them from the calculation */
961 SSVAL(req
->outbuf
,smb_proff
,
962 ((smb_buf(req
->outbuf
)+alignment_offset
)
963 - smb_base(req
->outbuf
)));
965 if(params_sent_thistime
== 0)
966 SSVAL(req
->outbuf
,smb_prdisp
,0);
968 /* Absolute displacement of param bytes sent in this packet */
969 SSVAL(req
->outbuf
,smb_prdisp
,pp
- params
);
971 SSVAL(req
->outbuf
,smb_drcnt
, data_sent_thistime
);
972 if(data_sent_thistime
== 0) {
973 SSVAL(req
->outbuf
,smb_droff
,0);
974 SSVAL(req
->outbuf
,smb_drdisp
, 0);
976 /* The offset of the data bytes is the offset of the
977 parameter bytes plus the number of parameters being sent this time */
978 SSVAL(req
->outbuf
, smb_droff
,
979 ((smb_buf(req
->outbuf
)+alignment_offset
)
980 - smb_base(req
->outbuf
))
981 + params_sent_thistime
+ data_alignment_offset
);
982 SSVAL(req
->outbuf
,smb_drdisp
, pd
- pdata
);
985 /* Initialize the padding for alignment */
987 if (alignment_offset
!= 0) {
988 memset(smb_buf(req
->outbuf
), 0, alignment_offset
);
991 /* Copy the param bytes into the packet */
993 if(params_sent_thistime
) {
994 memcpy((smb_buf(req
->outbuf
)+alignment_offset
), pp
,
995 params_sent_thistime
);
998 /* Copy in the data bytes */
999 if(data_sent_thistime
) {
1000 if (data_alignment_offset
!= 0) {
1001 memset((smb_buf(req
->outbuf
)+alignment_offset
+
1002 params_sent_thistime
), 0,
1003 data_alignment_offset
);
1005 memcpy(smb_buf(req
->outbuf
)+alignment_offset
1006 +params_sent_thistime
+data_alignment_offset
,
1007 pd
,data_sent_thistime
);
1010 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
1011 params_sent_thistime
, data_sent_thistime
, useable_space
));
1012 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
1013 params_to_send
, data_to_send
, paramsize
, datasize
));
1016 error_packet_set((char *)req
->outbuf
,
1017 ERRDOS
,ERRbufferoverflow
,
1018 STATUS_BUFFER_OVERFLOW
,
1020 } else if (NT_STATUS_V(status
)) {
1023 ntstatus_to_dos(status
, &eclass
, &ecode
);
1024 error_packet_set((char *)req
->outbuf
,
1025 eclass
, ecode
, status
,
1029 /* Send the packet */
1030 show_msg((char *)req
->outbuf
);
1031 if (!srv_send_smb(sconn
,
1032 (char *)req
->outbuf
,
1033 true, req
->seqnum
+1,
1034 IS_CONN_ENCRYPTED(conn
),
1036 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
1038 TALLOC_FREE(req
->outbuf
);
1040 pp
+= params_sent_thistime
;
1041 pd
+= data_sent_thistime
;
1043 params_to_send
-= params_sent_thistime
;
1044 data_to_send
-= data_sent_thistime
;
1047 if(params_to_send
< 0 || data_to_send
< 0) {
1048 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
1049 params_to_send
, data_to_send
));
1057 /****************************************************************************
1058 Reply to a TRANSACT2_OPEN.
1059 ****************************************************************************/
1061 static void call_trans2open(connection_struct
*conn
,
1062 struct smb_request
*req
,
1063 char **pparams
, int total_params
,
1064 char **ppdata
, int total_data
,
1065 unsigned int max_data_bytes
)
1067 struct smb_filename
*smb_fname
= NULL
;
1068 char *params
= *pparams
;
1069 char *pdata
= *ppdata
;
1072 bool oplock_request
;
1074 bool return_additional_info
;
1083 int fattr
=0,mtime
=0;
1084 SMB_INO_T inode
= 0;
1087 struct ea_list
*ea_list
= NULL
;
1092 uint32 create_disposition
;
1093 uint32 create_options
= 0;
1094 uint32_t private_flags
= 0;
1095 TALLOC_CTX
*ctx
= talloc_tos();
1098 * Ensure we have enough parameters to perform the operation.
1101 if (total_params
< 29) {
1102 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1106 flags
= SVAL(params
, 0);
1107 deny_mode
= SVAL(params
, 2);
1108 open_attr
= SVAL(params
,6);
1109 oplock_request
= (flags
& REQUEST_OPLOCK
) ? EXCLUSIVE_OPLOCK
: 0;
1110 if (oplock_request
) {
1111 oplock_request
|= (flags
& REQUEST_BATCH_OPLOCK
) ? BATCH_OPLOCK
: 0;
1115 return_additional_info
= BITSETW(params
,0);
1116 open_sattr
= SVAL(params
, 4);
1117 open_time
= make_unix_date3(params
+8);
1119 open_ofun
= SVAL(params
,12);
1120 open_size
= IVAL(params
,14);
1121 pname
= ¶ms
[28];
1124 reply_nterror(req
, NT_STATUS_NETWORK_ACCESS_DENIED
);
1128 srvstr_get_path(ctx
, params
, req
->flags2
, &fname
, pname
,
1129 total_params
- 28, STR_TERMINATE
,
1131 if (!NT_STATUS_IS_OK(status
)) {
1132 reply_nterror(req
, status
);
1136 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
1137 fname
, (unsigned int)deny_mode
, (unsigned int)open_attr
,
1138 (unsigned int)open_ofun
, open_size
));
1140 status
= filename_convert(ctx
,
1142 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
1147 if (!NT_STATUS_IS_OK(status
)) {
1148 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
1149 reply_botherror(req
,
1150 NT_STATUS_PATH_NOT_COVERED
,
1151 ERRSRV
, ERRbadpath
);
1154 reply_nterror(req
, status
);
1158 if (open_ofun
== 0) {
1159 reply_nterror(req
, NT_STATUS_OBJECT_NAME_COLLISION
);
1163 if (!map_open_params_to_ntcreate(smb_fname
->base_name
, deny_mode
,
1165 &access_mask
, &share_mode
,
1166 &create_disposition
,
1169 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
1173 /* Any data in this call is an EA list. */
1174 if (total_data
&& (total_data
!= 4)) {
1175 if (total_data
< 10) {
1176 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1180 if (IVAL(pdata
,0) > total_data
) {
1181 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
1182 IVAL(pdata
,0), (unsigned int)total_data
));
1183 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1187 ea_list
= read_ea_list(talloc_tos(), pdata
+ 4,
1190 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1194 if (!lp_ea_support(SNUM(conn
))) {
1195 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
1199 if (ea_list_has_invalid_name(ea_list
)) {
1201 *pparams
= (char *)SMB_REALLOC(*pparams
, param_len
);
1202 if(*pparams
== NULL
) {
1203 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1207 memset(params
, '\0', param_len
);
1208 send_trans2_replies(conn
, req
, STATUS_INVALID_EA_NAME
,
1209 params
, param_len
, NULL
, 0, max_data_bytes
);
1214 status
= SMB_VFS_CREATE_FILE(
1217 0, /* root_dir_fid */
1218 smb_fname
, /* fname */
1219 access_mask
, /* access_mask */
1220 share_mode
, /* share_access */
1221 create_disposition
, /* create_disposition*/
1222 create_options
, /* create_options */
1223 open_attr
, /* file_attributes */
1224 oplock_request
, /* oplock_request */
1226 open_size
, /* allocation_size */
1229 ea_list
, /* ea_list */
1231 &smb_action
); /* psbuf */
1233 if (!NT_STATUS_IS_OK(status
)) {
1234 if (open_was_deferred(req
->sconn
, req
->mid
)) {
1235 /* We have re-scheduled this call. */
1238 reply_openerror(req
, status
);
1242 size
= get_file_size_stat(&smb_fname
->st
);
1243 fattr
= dos_mode(conn
, smb_fname
);
1244 mtime
= convert_timespec_to_time_t(smb_fname
->st
.st_ex_mtime
);
1245 inode
= smb_fname
->st
.st_ex_ino
;
1246 if (fattr
& FILE_ATTRIBUTE_DIRECTORY
) {
1247 close_file(req
, fsp
, ERROR_CLOSE
);
1248 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
1252 /* Realloc the size of parameters and data we will return */
1253 *pparams
= (char *)SMB_REALLOC(*pparams
, 30);
1254 if(*pparams
== NULL
) {
1255 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1260 SSVAL(params
,0,fsp
->fnum
);
1261 SSVAL(params
,2,fattr
);
1262 srv_put_dos_date2(params
,4, mtime
);
1263 SIVAL(params
,8, (uint32
)size
);
1264 SSVAL(params
,12,deny_mode
);
1265 SSVAL(params
,14,0); /* open_type - file or directory. */
1266 SSVAL(params
,16,0); /* open_state - only valid for IPC device. */
1268 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
1269 smb_action
|= EXTENDED_OPLOCK_GRANTED
;
1272 SSVAL(params
,18,smb_action
);
1275 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1277 SIVAL(params
,20,inode
);
1278 SSVAL(params
,24,0); /* Padding. */
1280 uint32 ea_size
= estimate_ea_size(conn
, fsp
,
1282 SIVAL(params
, 26, ea_size
);
1284 SIVAL(params
, 26, 0);
1287 /* Send the required number of replies */
1288 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 30, *ppdata
, 0, max_data_bytes
);
1290 TALLOC_FREE(smb_fname
);
1293 /*********************************************************
1294 Routine to check if a given string matches exactly.
1295 as a special case a mask of "." does NOT match. That
1296 is required for correct wildcard semantics
1297 Case can be significant or not.
1298 **********************************************************/
1300 static bool exact_match(bool has_wild
,
1301 bool case_sensitive
,
1305 if (mask
[0] == '.' && mask
[1] == 0) {
1313 if (case_sensitive
) {
1314 return strcmp(str
,mask
)==0;
1316 return strcasecmp_m(str
,mask
) == 0;
1320 /****************************************************************************
1321 Return the filetype for UNIX extensions.
1322 ****************************************************************************/
1324 static uint32
unix_filetype(mode_t mode
)
1327 return UNIX_TYPE_FILE
;
1328 else if(S_ISDIR(mode
))
1329 return UNIX_TYPE_DIR
;
1331 else if(S_ISLNK(mode
))
1332 return UNIX_TYPE_SYMLINK
;
1335 else if(S_ISCHR(mode
))
1336 return UNIX_TYPE_CHARDEV
;
1339 else if(S_ISBLK(mode
))
1340 return UNIX_TYPE_BLKDEV
;
1343 else if(S_ISFIFO(mode
))
1344 return UNIX_TYPE_FIFO
;
1347 else if(S_ISSOCK(mode
))
1348 return UNIX_TYPE_SOCKET
;
1351 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode
));
1352 return UNIX_TYPE_UNKNOWN
;
1355 /****************************************************************************
1356 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1357 ****************************************************************************/
1359 enum perm_type
{ PERM_NEW_FILE
, PERM_NEW_DIR
, PERM_EXISTING_FILE
, PERM_EXISTING_DIR
};
1361 static NTSTATUS
unix_perms_from_wire( connection_struct
*conn
,
1362 const SMB_STRUCT_STAT
*psbuf
,
1364 enum perm_type ptype
,
1369 if (perms
== SMB_MODE_NO_CHANGE
) {
1370 if (!VALID_STAT(*psbuf
)) {
1371 return NT_STATUS_INVALID_PARAMETER
;
1373 *ret_perms
= psbuf
->st_ex_mode
;
1374 return NT_STATUS_OK
;
1378 ret
|= ((perms
& UNIX_X_OTH
) ? S_IXOTH
: 0);
1379 ret
|= ((perms
& UNIX_W_OTH
) ? S_IWOTH
: 0);
1380 ret
|= ((perms
& UNIX_R_OTH
) ? S_IROTH
: 0);
1381 ret
|= ((perms
& UNIX_X_GRP
) ? S_IXGRP
: 0);
1382 ret
|= ((perms
& UNIX_W_GRP
) ? S_IWGRP
: 0);
1383 ret
|= ((perms
& UNIX_R_GRP
) ? S_IRGRP
: 0);
1384 ret
|= ((perms
& UNIX_X_USR
) ? S_IXUSR
: 0);
1385 ret
|= ((perms
& UNIX_W_USR
) ? S_IWUSR
: 0);
1386 ret
|= ((perms
& UNIX_R_USR
) ? S_IRUSR
: 0);
1388 ret
|= ((perms
& UNIX_STICKY
) ? S_ISVTX
: 0);
1391 ret
|= ((perms
& UNIX_SET_GID
) ? S_ISGID
: 0);
1394 ret
|= ((perms
& UNIX_SET_UID
) ? S_ISUID
: 0);
1397 if (ptype
== PERM_NEW_FILE
) {
1399 * "create mask"/"force create mode" are
1400 * only applied to new files, not existing ones.
1402 ret
&= lp_create_mask(SNUM(conn
));
1403 /* Add in force bits */
1404 ret
|= lp_force_create_mode(SNUM(conn
));
1405 } else if (ptype
== PERM_NEW_DIR
) {
1407 * "directory mask"/"force directory mode" are
1408 * only applied to new directories, not existing ones.
1410 ret
&= lp_directory_mask(SNUM(conn
));
1411 /* Add in force bits */
1412 ret
|= lp_force_directory_mode(SNUM(conn
));
1416 return NT_STATUS_OK
;
1419 /****************************************************************************
1420 Needed to show the msdfs symlinks as directories. Modifies psbuf
1421 to be a directory if it's a msdfs link.
1422 ****************************************************************************/
1424 static bool check_msdfs_link(connection_struct
*conn
,
1425 const char *pathname
,
1426 SMB_STRUCT_STAT
*psbuf
)
1428 int saved_errno
= errno
;
1429 if(lp_host_msdfs() &&
1430 lp_msdfs_root(SNUM(conn
)) &&
1431 is_msdfs_link(conn
, pathname
, psbuf
)) {
1433 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1436 psbuf
->st_ex_mode
= (psbuf
->st_ex_mode
& 0xFFF) | S_IFDIR
;
1437 errno
= saved_errno
;
1440 errno
= saved_errno
;
1445 /****************************************************************************
1446 Get a level dependent lanman2 dir entry.
1447 ****************************************************************************/
1449 struct smbd_dirptr_lanman2_state
{
1450 connection_struct
*conn
;
1451 uint32_t info_level
;
1452 bool check_mangled_names
;
1454 bool got_exact_match
;
1457 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX
*ctx
,
1463 struct smbd_dirptr_lanman2_state
*state
=
1464 (struct smbd_dirptr_lanman2_state
*)private_data
;
1466 char mangled_name
[13]; /* mangled 8.3 name. */
1470 /* Mangle fname if it's an illegal name. */
1471 if (mangle_must_mangle(dname
, state
->conn
->params
)) {
1472 ok
= name_to_8_3(dname
, mangled_name
,
1473 true, state
->conn
->params
);
1477 fname
= mangled_name
;
1482 got_match
= exact_match(state
->has_wild
,
1483 state
->conn
->case_sensitive
,
1485 state
->got_exact_match
= got_match
;
1487 got_match
= mask_match(fname
, mask
,
1488 state
->conn
->case_sensitive
);
1491 if(!got_match
&& state
->check_mangled_names
&&
1492 !mangle_is_8_3(fname
, false, state
->conn
->params
)) {
1494 * It turns out that NT matches wildcards against
1495 * both long *and* short names. This may explain some
1496 * of the wildcard wierdness from old DOS clients
1497 * that some people have been seeing.... JRA.
1499 /* Force the mangling into 8.3. */
1500 ok
= name_to_8_3(fname
, mangled_name
,
1501 false, state
->conn
->params
);
1506 got_match
= exact_match(state
->has_wild
,
1507 state
->conn
->case_sensitive
,
1508 mangled_name
, mask
);
1509 state
->got_exact_match
= got_match
;
1511 got_match
= mask_match(mangled_name
, mask
,
1512 state
->conn
->case_sensitive
);
1520 *_fname
= talloc_strdup(ctx
, fname
);
1521 if (*_fname
== NULL
) {
1528 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX
*ctx
,
1530 struct smb_filename
*smb_fname
,
1533 struct smbd_dirptr_lanman2_state
*state
=
1534 (struct smbd_dirptr_lanman2_state
*)private_data
;
1535 bool ms_dfs_link
= false;
1538 if (INFO_LEVEL_IS_UNIX(state
->info_level
)) {
1539 if (SMB_VFS_LSTAT(state
->conn
, smb_fname
) != 0) {
1540 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1541 "Couldn't lstat [%s] (%s)\n",
1542 smb_fname_str_dbg(smb_fname
),
1546 } else if (!VALID_STAT(smb_fname
->st
) &&
1547 SMB_VFS_STAT(state
->conn
, smb_fname
) != 0) {
1548 /* Needed to show the msdfs symlinks as
1551 ms_dfs_link
= check_msdfs_link(state
->conn
,
1552 smb_fname
->base_name
,
1555 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1556 "Couldn't stat [%s] (%s)\n",
1557 smb_fname_str_dbg(smb_fname
),
1564 mode
= dos_mode_msdfs(state
->conn
, smb_fname
);
1566 mode
= dos_mode(state
->conn
, smb_fname
);
1573 static bool smbd_marshall_dir_entry(TALLOC_CTX
*ctx
,
1574 connection_struct
*conn
,
1576 uint32_t info_level
,
1577 struct ea_list
*name_list
,
1578 bool check_mangled_names
,
1579 bool requires_resume_key
,
1582 const struct smb_filename
*smb_fname
,
1583 int space_remaining
,
1590 uint64_t *last_entry_off
)
1592 char *p
, *q
, *pdata
= *ppdata
;
1594 uint64_t file_size
= 0;
1595 uint64_t allocation_size
= 0;
1596 uint64_t file_index
= 0;
1598 struct timespec mdate_ts
, adate_ts
, cdate_ts
, create_date_ts
;
1599 time_t mdate
= (time_t)0, adate
= (time_t)0, create_date
= (time_t)0;
1601 char *last_entry_ptr
;
1606 *out_of_space
= false;
1608 ZERO_STRUCT(mdate_ts
);
1609 ZERO_STRUCT(adate_ts
);
1610 ZERO_STRUCT(create_date_ts
);
1611 ZERO_STRUCT(cdate_ts
);
1613 if (!(mode
& FILE_ATTRIBUTE_DIRECTORY
)) {
1614 file_size
= get_file_size_stat(&smb_fname
->st
);
1616 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
, NULL
, &smb_fname
->st
);
1618 file_index
= get_FileIndex(conn
, &smb_fname
->st
);
1620 mdate_ts
= smb_fname
->st
.st_ex_mtime
;
1621 adate_ts
= smb_fname
->st
.st_ex_atime
;
1622 create_date_ts
= get_create_timespec(conn
, NULL
, smb_fname
);
1623 cdate_ts
= get_change_timespec(conn
, NULL
, smb_fname
);
1625 if (lp_dos_filetime_resolution(SNUM(conn
))) {
1626 dos_filetime_timespec(&create_date_ts
);
1627 dos_filetime_timespec(&mdate_ts
);
1628 dos_filetime_timespec(&adate_ts
);
1629 dos_filetime_timespec(&cdate_ts
);
1632 create_date
= convert_timespec_to_time_t(create_date_ts
);
1633 mdate
= convert_timespec_to_time_t(mdate_ts
);
1634 adate
= convert_timespec_to_time_t(adate_ts
);
1636 /* align the record */
1637 SMB_ASSERT(align
>= 1);
1639 off
= (int)PTR_DIFF(pdata
, base_data
);
1640 pad
= (off
+ (align
-1)) & ~(align
-1);
1643 if (pad
&& pad
> space_remaining
) {
1644 *out_of_space
= true;
1645 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1646 "for padding (wanted %u, had %d)\n",
1649 return false; /* Not finished - just out of space */
1653 /* initialize padding to 0 */
1655 memset(pdata
, 0, pad
);
1657 space_remaining
-= pad
;
1659 DEBUG(10,("smbd_marshall_dir_entry: space_remaining = %d\n",
1669 switch (info_level
) {
1670 case SMB_FIND_INFO_STANDARD
:
1671 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1672 if(requires_resume_key
) {
1676 srv_put_dos_date2(p
,0,create_date
);
1677 srv_put_dos_date2(p
,4,adate
);
1678 srv_put_dos_date2(p
,8,mdate
);
1679 SIVAL(p
,12,(uint32
)file_size
);
1680 SIVAL(p
,16,(uint32
)allocation_size
);
1684 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1685 p
+= ucs2_align(base_data
, p
, 0);
1687 len
= srvstr_push(base_data
, flags2
, p
,
1688 fname
, PTR_DIFF(end_data
, p
),
1690 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1692 SCVAL(nameptr
, -1, len
- 2);
1694 SCVAL(nameptr
, -1, 0);
1698 SCVAL(nameptr
, -1, len
- 1);
1700 SCVAL(nameptr
, -1, 0);
1706 case SMB_FIND_EA_SIZE
:
1707 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
1708 if (requires_resume_key
) {
1712 srv_put_dos_date2(p
,0,create_date
);
1713 srv_put_dos_date2(p
,4,adate
);
1714 srv_put_dos_date2(p
,8,mdate
);
1715 SIVAL(p
,12,(uint32
)file_size
);
1716 SIVAL(p
,16,(uint32
)allocation_size
);
1719 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
1721 SIVAL(p
,22,ea_size
); /* Extended attributes */
1725 len
= srvstr_push(base_data
, flags2
,
1726 p
, fname
, PTR_DIFF(end_data
, p
),
1727 STR_TERMINATE
| STR_NOALIGN
);
1728 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1741 SCVAL(nameptr
,0,len
);
1743 SCVAL(p
,0,0); p
+= 1; /* Extra zero byte ? - why.. */
1746 case SMB_FIND_EA_LIST
:
1748 struct ea_list
*file_list
= NULL
;
1752 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
1756 if (requires_resume_key
) {
1760 srv_put_dos_date2(p
,0,create_date
);
1761 srv_put_dos_date2(p
,4,adate
);
1762 srv_put_dos_date2(p
,8,mdate
);
1763 SIVAL(p
,12,(uint32
)file_size
);
1764 SIVAL(p
,16,(uint32
)allocation_size
);
1766 p
+= 22; /* p now points to the EA area. */
1768 status
= get_ea_list_from_file(ctx
, conn
, NULL
,
1770 &ea_len
, &file_list
);
1771 if (!NT_STATUS_IS_OK(status
)) {
1774 name_list
= ea_list_union(name_list
, file_list
, &ea_len
);
1776 /* We need to determine if this entry will fit in the space available. */
1777 /* Max string size is 255 bytes. */
1778 if (PTR_DIFF(p
+ 255 + ea_len
,pdata
) > space_remaining
) {
1779 *out_of_space
= true;
1780 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1781 "(wanted %u, had %d)\n",
1782 (unsigned int)PTR_DIFF(p
+ 255 + ea_len
,pdata
),
1784 return False
; /* Not finished - just out of space */
1787 /* Push the ea_data followed by the name. */
1788 p
+= fill_ea_buffer(ctx
, p
, space_remaining
, conn
, name_list
);
1790 len
= srvstr_push(base_data
, flags2
,
1791 p
+ 1, fname
, PTR_DIFF(end_data
, p
+1),
1792 STR_TERMINATE
| STR_NOALIGN
);
1793 if (flags2
& FLAGS2_UNICODE_STRINGS
) {
1806 SCVAL(nameptr
,0,len
);
1808 SCVAL(p
,0,0); p
+= 1; /* Extra zero byte ? - why.. */
1812 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
1813 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1814 was_8_3
= mangle_is_8_3(fname
, True
, conn
->params
);
1816 SIVAL(p
,0,reskey
); p
+= 4;
1817 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
1818 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
1819 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
1820 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
1821 SOFF_T(p
,0,file_size
); p
+= 8;
1822 SOFF_T(p
,0,allocation_size
); p
+= 8;
1823 SIVAL(p
,0,mode
); p
+= 4;
1824 q
= p
; p
+= 4; /* q is placeholder for name length. */
1825 if (mode
& FILE_ATTRIBUTE_REPARSE_POINT
) {
1826 SIVAL(p
, 0, IO_REPARSE_TAG_DFS
);
1828 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
1830 SIVAL(p
,0,ea_size
); /* Extended attributes */
1833 /* Clear the short name buffer. This is
1834 * IMPORTANT as not doing so will trigger
1835 * a Win2k client bug. JRA.
1837 if (!was_8_3
&& check_mangled_names
) {
1838 char mangled_name
[13]; /* mangled 8.3 name. */
1839 if (!name_to_8_3(fname
,mangled_name
,True
,
1841 /* Error - mangle failed ! */
1842 memset(mangled_name
,'\0',12);
1844 mangled_name
[12] = 0;
1845 len
= srvstr_push(base_data
, flags2
,
1846 p
+2, mangled_name
, 24,
1847 STR_UPPER
|STR_UNICODE
);
1849 memset(p
+ 2 + len
,'\0',24 - len
);
1856 len
= srvstr_push(base_data
, flags2
, p
,
1857 fname
, PTR_DIFF(end_data
, p
),
1858 STR_TERMINATE_ASCII
);
1862 len
= PTR_DIFF(p
, pdata
);
1863 pad
= (len
+ (align
-1)) & ~(align
-1);
1865 * offset to the next entry, the caller
1866 * will overwrite it for the last entry
1867 * that's why we always include the padding
1871 * set padding to zero
1874 memset(p
, 0, pad
- len
);
1881 case SMB_FIND_FILE_DIRECTORY_INFO
:
1882 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1884 SIVAL(p
,0,reskey
); p
+= 4;
1885 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
1886 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
1887 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
1888 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
1889 SOFF_T(p
,0,file_size
); p
+= 8;
1890 SOFF_T(p
,0,allocation_size
); p
+= 8;
1891 SIVAL(p
,0,mode
); p
+= 4;
1892 len
= srvstr_push(base_data
, flags2
,
1893 p
+ 4, fname
, PTR_DIFF(end_data
, p
+4),
1894 STR_TERMINATE_ASCII
);
1898 len
= PTR_DIFF(p
, pdata
);
1899 pad
= (len
+ (align
-1)) & ~(align
-1);
1901 * offset to the next entry, the caller
1902 * will overwrite it for the last entry
1903 * that's why we always include the padding
1907 * set padding to zero
1910 memset(p
, 0, pad
- len
);
1917 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
1918 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1920 SIVAL(p
,0,reskey
); p
+= 4;
1921 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
1922 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
1923 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
1924 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
1925 SOFF_T(p
,0,file_size
); p
+= 8;
1926 SOFF_T(p
,0,allocation_size
); p
+= 8;
1927 SIVAL(p
,0,mode
); p
+= 4;
1928 q
= p
; p
+= 4; /* q is placeholder for name length. */
1930 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
1932 SIVAL(p
,0,ea_size
); /* Extended attributes */
1935 len
= srvstr_push(base_data
, flags2
, p
,
1936 fname
, PTR_DIFF(end_data
, p
),
1937 STR_TERMINATE_ASCII
);
1941 len
= PTR_DIFF(p
, pdata
);
1942 pad
= (len
+ (align
-1)) & ~(align
-1);
1944 * offset to the next entry, the caller
1945 * will overwrite it for the last entry
1946 * that's why we always include the padding
1950 * set padding to zero
1953 memset(p
, 0, pad
- len
);
1960 case SMB_FIND_FILE_NAMES_INFO
:
1961 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1963 SIVAL(p
,0,reskey
); p
+= 4;
1965 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1966 acl on a dir (tridge) */
1967 len
= srvstr_push(base_data
, flags2
, p
,
1968 fname
, PTR_DIFF(end_data
, p
),
1969 STR_TERMINATE_ASCII
);
1973 len
= PTR_DIFF(p
, pdata
);
1974 pad
= (len
+ (align
-1)) & ~(align
-1);
1976 * offset to the next entry, the caller
1977 * will overwrite it for the last entry
1978 * that's why we always include the padding
1982 * set padding to zero
1985 memset(p
, 0, pad
- len
);
1992 case SMB_FIND_ID_FULL_DIRECTORY_INFO
:
1993 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1995 SIVAL(p
,0,reskey
); p
+= 4;
1996 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
1997 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
1998 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
1999 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
2000 SOFF_T(p
,0,file_size
); p
+= 8;
2001 SOFF_T(p
,0,allocation_size
); p
+= 8;
2002 SIVAL(p
,0,mode
); p
+= 4;
2003 q
= p
; p
+= 4; /* q is placeholder for name length. */
2004 if (mode
& FILE_ATTRIBUTE_REPARSE_POINT
) {
2005 SIVAL(p
, 0, IO_REPARSE_TAG_DFS
);
2007 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
2009 SIVAL(p
,0,ea_size
); /* Extended attributes */
2012 SIVAL(p
,0,0); p
+= 4; /* Unknown - reserved ? */
2013 SBVAL(p
,0,file_index
); p
+= 8;
2014 len
= srvstr_push(base_data
, flags2
, p
,
2015 fname
, PTR_DIFF(end_data
, p
),
2016 STR_TERMINATE_ASCII
);
2020 len
= PTR_DIFF(p
, pdata
);
2021 pad
= (len
+ (align
-1)) & ~(align
-1);
2023 * offset to the next entry, the caller
2024 * will overwrite it for the last entry
2025 * that's why we always include the padding
2029 * set padding to zero
2032 memset(p
, 0, pad
- len
);
2039 case SMB_FIND_ID_BOTH_DIRECTORY_INFO
:
2040 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
2041 was_8_3
= mangle_is_8_3(fname
, True
, conn
->params
);
2043 SIVAL(p
,0,reskey
); p
+= 4;
2044 put_long_date_timespec(conn
->ts_res
,p
,create_date_ts
); p
+= 8;
2045 put_long_date_timespec(conn
->ts_res
,p
,adate_ts
); p
+= 8;
2046 put_long_date_timespec(conn
->ts_res
,p
,mdate_ts
); p
+= 8;
2047 put_long_date_timespec(conn
->ts_res
,p
,cdate_ts
); p
+= 8;
2048 SOFF_T(p
,0,file_size
); p
+= 8;
2049 SOFF_T(p
,0,allocation_size
); p
+= 8;
2050 SIVAL(p
,0,mode
); p
+= 4;
2051 q
= p
; p
+= 4; /* q is placeholder for name length */
2052 if (mode
& FILE_ATTRIBUTE_REPARSE_POINT
) {
2053 SIVAL(p
, 0, IO_REPARSE_TAG_DFS
);
2055 unsigned int ea_size
= estimate_ea_size(conn
, NULL
,
2057 SIVAL(p
,0,ea_size
); /* Extended attributes */
2060 /* Clear the short name buffer. This is
2061 * IMPORTANT as not doing so will trigger
2062 * a Win2k client bug. JRA.
2064 if (!was_8_3
&& check_mangled_names
) {
2065 char mangled_name
[13]; /* mangled 8.3 name. */
2066 if (!name_to_8_3(fname
,mangled_name
,True
,
2068 /* Error - mangle failed ! */
2069 memset(mangled_name
,'\0',12);
2071 mangled_name
[12] = 0;
2072 len
= srvstr_push(base_data
, flags2
,
2073 p
+2, mangled_name
, 24,
2074 STR_UPPER
|STR_UNICODE
);
2077 memset(p
+ 2 + len
,'\0',24 - len
);
2084 SSVAL(p
,0,0); p
+= 2; /* Reserved ? */
2085 SBVAL(p
,0,file_index
); p
+= 8;
2086 len
= srvstr_push(base_data
, flags2
, p
,
2087 fname
, PTR_DIFF(end_data
, p
),
2088 STR_TERMINATE_ASCII
);
2092 len
= PTR_DIFF(p
, pdata
);
2093 pad
= (len
+ (align
-1)) & ~(align
-1);
2095 * offset to the next entry, the caller
2096 * will overwrite it for the last entry
2097 * that's why we always include the padding
2101 * set padding to zero
2104 memset(p
, 0, pad
- len
);
2111 /* CIFS UNIX Extension. */
2113 case SMB_FIND_FILE_UNIX
:
2114 case SMB_FIND_FILE_UNIX_INFO2
:
2116 SIVAL(p
,0,reskey
); p
+= 4; /* Used for continuing search. */
2118 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
2120 if (info_level
== SMB_FIND_FILE_UNIX
) {
2121 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
2122 p
= store_file_unix_basic(conn
, p
,
2123 NULL
, &smb_fname
->st
);
2124 len
= srvstr_push(base_data
, flags2
, p
,
2125 fname
, PTR_DIFF(end_data
, p
),
2128 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
2129 p
= store_file_unix_basic_info2(conn
, p
,
2130 NULL
, &smb_fname
->st
);
2133 len
= srvstr_push(base_data
, flags2
, p
, fname
,
2134 PTR_DIFF(end_data
, p
), 0);
2135 SIVAL(nameptr
, 0, len
);
2140 len
= PTR_DIFF(p
, pdata
);
2141 pad
= (len
+ (align
-1)) & ~(align
-1);
2143 * offset to the next entry, the caller
2144 * will overwrite it for the last entry
2145 * that's why we always include the padding
2149 * set padding to zero
2152 memset(p
, 0, pad
- len
);
2157 /* End of SMB_QUERY_FILE_UNIX_BASIC */
2165 if (PTR_DIFF(p
,pdata
) > space_remaining
) {
2166 *out_of_space
= true;
2167 DEBUG(9,("smbd_marshall_dir_entry: out of space "
2168 "(wanted %u, had %d)\n",
2169 (unsigned int)PTR_DIFF(p
,pdata
),
2171 return false; /* Not finished - just out of space */
2174 /* Setup the last entry pointer, as an offset from base_data */
2175 *last_entry_off
= PTR_DIFF(last_entry_ptr
,base_data
);
2176 /* Advance the data pointer to the next slot */
2182 bool smbd_dirptr_lanman2_entry(TALLOC_CTX
*ctx
,
2183 connection_struct
*conn
,
2184 struct dptr_struct
*dirptr
,
2186 const char *path_mask
,
2189 int requires_resume_key
,
2197 int space_remaining
,
2199 bool *got_exact_match
,
2200 int *_last_entry_off
,
2201 struct ea_list
*name_list
)
2204 const char *mask
= NULL
;
2205 long prev_dirpos
= 0;
2208 struct smb_filename
*smb_fname
= NULL
;
2209 struct smbd_dirptr_lanman2_state state
;
2211 uint64_t last_entry_off
= 0;
2215 state
.info_level
= info_level
;
2216 state
.check_mangled_names
= lp_mangled_names(conn
->params
);
2217 state
.has_wild
= dptr_has_wild(dirptr
);
2218 state
.got_exact_match
= false;
2220 *out_of_space
= false;
2221 *got_exact_match
= false;
2223 p
= strrchr_m(path_mask
,'/');
2234 ok
= smbd_dirptr_get_entry(ctx
,
2240 smbd_dirptr_lanman2_match_fn
,
2241 smbd_dirptr_lanman2_mode_fn
,
2251 *got_exact_match
= state
.got_exact_match
;
2253 ok
= smbd_marshall_dir_entry(ctx
,
2258 state
.check_mangled_names
,
2259 requires_resume_key
,
2272 TALLOC_FREE(smb_fname
);
2273 if (*out_of_space
) {
2274 dptr_SeekDir(dirptr
, prev_dirpos
);
2281 *_last_entry_off
= last_entry_off
;
2285 static bool get_lanman2_dir_entry(TALLOC_CTX
*ctx
,
2286 connection_struct
*conn
,
2287 struct dptr_struct
*dirptr
,
2289 const char *path_mask
,
2292 bool requires_resume_key
,
2298 int space_remaining
,
2300 bool *got_exact_match
,
2301 int *last_entry_off
,
2302 struct ea_list
*name_list
)
2305 const bool do_pad
= true;
2307 if (info_level
>= 1 && info_level
<= 3) {
2308 /* No alignment on earlier info levels. */
2312 return smbd_dirptr_lanman2_entry(ctx
, conn
, dirptr
, flags2
,
2313 path_mask
, dirtype
, info_level
,
2314 requires_resume_key
, dont_descend
, ask_sharemode
,
2316 ppdata
, base_data
, end_data
,
2318 out_of_space
, got_exact_match
,
2319 last_entry_off
, name_list
);
2322 /****************************************************************************
2323 Reply to a TRANS2_FINDFIRST.
2324 ****************************************************************************/
2326 static void call_trans2findfirst(connection_struct
*conn
,
2327 struct smb_request
*req
,
2328 char **pparams
, int total_params
,
2329 char **ppdata
, int total_data
,
2330 unsigned int max_data_bytes
)
2332 /* We must be careful here that we don't return more than the
2333 allowed number of data bytes. If this means returning fewer than
2334 maxentries then so be it. We assume that the redirector has
2335 enough room for the fixed number of parameter bytes it has
2337 struct smb_filename
*smb_dname
= NULL
;
2338 char *params
= *pparams
;
2339 char *pdata
= *ppdata
;
2343 uint16 findfirst_flags
;
2344 bool close_after_first
;
2346 bool requires_resume_key
;
2348 char *directory
= NULL
;
2351 int last_entry_off
=0;
2355 bool finished
= False
;
2356 bool dont_descend
= False
;
2357 bool out_of_space
= False
;
2358 int space_remaining
;
2359 bool mask_contains_wcard
= False
;
2360 struct ea_list
*ea_list
= NULL
;
2361 NTSTATUS ntstatus
= NT_STATUS_OK
;
2362 bool ask_sharemode
= lp_parm_bool(SNUM(conn
), "smbd", "search ask sharemode", true);
2363 TALLOC_CTX
*ctx
= talloc_tos();
2364 struct dptr_struct
*dirptr
= NULL
;
2365 struct smbd_server_connection
*sconn
= req
->sconn
;
2366 uint32_t ucf_flags
= (UCF_SAVE_LCOMP
| UCF_ALWAYS_ALLOW_WCARD_LCOMP
);
2367 bool backup_priv
= false;
2369 if (total_params
< 13) {
2370 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2374 dirtype
= SVAL(params
,0);
2375 maxentries
= SVAL(params
,2);
2376 findfirst_flags
= SVAL(params
,4);
2377 close_after_first
= (findfirst_flags
& FLAG_TRANS2_FIND_CLOSE
);
2378 close_if_end
= (findfirst_flags
& FLAG_TRANS2_FIND_CLOSE_IF_END
);
2379 requires_resume_key
= (findfirst_flags
& FLAG_TRANS2_FIND_REQUIRE_RESUME
);
2380 backup_priv
= ((findfirst_flags
& FLAG_TRANS2_FIND_BACKUP_INTENT
) &&
2381 security_token_has_privilege(get_current_nttok(conn
),
2384 info_level
= SVAL(params
,6);
2386 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2387 close_if_end = %d requires_resume_key = %d backup_priv = %d level = 0x%x, max_data_bytes = %d\n",
2388 (unsigned int)dirtype
, maxentries
, close_after_first
, close_if_end
, requires_resume_key
,
2390 info_level
, max_data_bytes
));
2393 /* W2K3 seems to treat zero as 1. */
2397 switch (info_level
) {
2398 case SMB_FIND_INFO_STANDARD
:
2399 case SMB_FIND_EA_SIZE
:
2400 case SMB_FIND_EA_LIST
:
2401 case SMB_FIND_FILE_DIRECTORY_INFO
:
2402 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
2403 case SMB_FIND_FILE_NAMES_INFO
:
2404 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
2405 case SMB_FIND_ID_FULL_DIRECTORY_INFO
:
2406 case SMB_FIND_ID_BOTH_DIRECTORY_INFO
:
2408 case SMB_FIND_FILE_UNIX
:
2409 case SMB_FIND_FILE_UNIX_INFO2
:
2410 /* Always use filesystem for UNIX mtime query. */
2411 ask_sharemode
= false;
2412 if (!lp_unix_extensions()) {
2413 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2416 ucf_flags
|= UCF_UNIX_NAME_LOOKUP
;
2419 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2423 srvstr_get_path_wcard(ctx
, params
, req
->flags2
, &directory
,
2424 params
+12, total_params
- 12,
2425 STR_TERMINATE
, &ntstatus
, &mask_contains_wcard
);
2426 if (!NT_STATUS_IS_OK(ntstatus
)) {
2427 reply_nterror(req
, ntstatus
);
2433 ntstatus
= filename_convert_with_privilege(ctx
,
2438 &mask_contains_wcard
,
2441 ntstatus
= filename_convert(ctx
, conn
,
2442 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
2445 &mask_contains_wcard
,
2449 if (!NT_STATUS_IS_OK(ntstatus
)) {
2450 if (NT_STATUS_EQUAL(ntstatus
,NT_STATUS_PATH_NOT_COVERED
)) {
2451 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
2452 ERRSRV
, ERRbadpath
);
2455 reply_nterror(req
, ntstatus
);
2459 mask
= smb_dname
->original_lcomp
;
2461 directory
= smb_dname
->base_name
;
2463 p
= strrchr_m(directory
,'/');
2465 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2466 if((directory
[0] == '.') && (directory
[1] == '\0')) {
2467 mask
= talloc_strdup(ctx
,"*");
2469 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2472 mask_contains_wcard
= True
;
2478 if (p
== NULL
|| p
== directory
) {
2479 /* Ensure we don't have a directory name of "". */
2480 directory
= talloc_strdup(talloc_tos(), ".");
2482 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2487 DEBUG(5,("dir=%s, mask = %s\n",directory
, mask
));
2489 if (info_level
== SMB_FIND_EA_LIST
) {
2492 if (total_data
< 4) {
2493 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2497 ea_size
= IVAL(pdata
,0);
2498 if (ea_size
!= total_data
) {
2499 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2500 total_data=%u (should be %u)\n", (unsigned int)total_data
, (unsigned int)IVAL(pdata
,0) ));
2501 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2505 if (!lp_ea_support(SNUM(conn
))) {
2506 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
2510 /* Pull out the list of names. */
2511 ea_list
= read_ea_name_list(ctx
, pdata
+ 4, ea_size
- 4);
2513 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2518 if (max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
< max_data_bytes
) {
2519 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2523 *ppdata
= (char *)SMB_REALLOC(
2524 *ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
2525 if(*ppdata
== NULL
) {
2526 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2530 data_end
= pdata
+ max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
- 1;
2532 /* Realloc the params space */
2533 *pparams
= (char *)SMB_REALLOC(*pparams
, 10);
2534 if (*pparams
== NULL
) {
2535 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2540 /* Save the wildcard match and attribs we are using on this directory -
2541 needed as lanman2 assumes these are being saved between calls */
2543 ntstatus
= dptr_create(conn
,
2551 mask_contains_wcard
,
2555 if (!NT_STATUS_IS_OK(ntstatus
)) {
2556 reply_nterror(req
, ntstatus
);
2561 /* Remember this in case we have
2562 to do a findnext. */
2563 dptr_set_priv(dirptr
);
2566 dptr_num
= dptr_dnum(dirptr
);
2567 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num
, mask
, dirtype
));
2569 /* Initialize per TRANS2_FIND_FIRST operation data */
2570 dptr_init_search_op(dirptr
);
2572 /* We don't need to check for VOL here as this is returned by
2573 a different TRANS2 call. */
2575 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2576 directory
,lp_dont_descend(ctx
, SNUM(conn
))));
2577 if (in_list(directory
,lp_dont_descend(ctx
, SNUM(conn
)),conn
->case_sensitive
))
2578 dont_descend
= True
;
2581 space_remaining
= max_data_bytes
;
2582 out_of_space
= False
;
2584 for (i
=0;(i
<maxentries
) && !finished
&& !out_of_space
;i
++) {
2585 bool got_exact_match
= False
;
2587 /* this is a heuristic to avoid seeking the dirptr except when
2588 absolutely necessary. It allows for a filename of about 40 chars */
2589 if (space_remaining
< DIRLEN_GUESS
&& numentries
> 0) {
2590 out_of_space
= True
;
2593 finished
= !get_lanman2_dir_entry(ctx
,
2597 mask
,dirtype
,info_level
,
2598 requires_resume_key
,dont_descend
,
2601 space_remaining
, &out_of_space
,
2603 &last_entry_off
, ea_list
);
2606 if (finished
&& out_of_space
)
2609 if (!finished
&& !out_of_space
)
2613 * As an optimisation if we know we aren't looking
2614 * for a wildcard name (ie. the name matches the wildcard exactly)
2615 * then we can finish on any (first) match.
2616 * This speeds up large directory searches. JRA.
2622 /* Ensure space_remaining never goes -ve. */
2623 if (PTR_DIFF(p
,pdata
) > max_data_bytes
) {
2624 space_remaining
= 0;
2625 out_of_space
= true;
2627 space_remaining
= max_data_bytes
- PTR_DIFF(p
,pdata
);
2631 /* Check if we can close the dirptr */
2632 if(close_after_first
|| (finished
&& close_if_end
)) {
2633 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num
));
2634 dptr_close(sconn
, &dptr_num
);
2638 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2639 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2640 * the protocol level is less than NT1. Tested with smbclient. JRA.
2641 * This should fix the OS/2 client bug #2335.
2644 if(numentries
== 0) {
2645 dptr_close(sconn
, &dptr_num
);
2646 if (get_Protocol() < PROTOCOL_NT1
) {
2647 reply_force_doserror(req
, ERRDOS
, ERRnofiles
);
2650 reply_botherror(req
, NT_STATUS_NO_SUCH_FILE
,
2651 ERRDOS
, ERRbadfile
);
2656 /* At this point pdata points to numentries directory entries. */
2658 /* Set up the return parameter block */
2659 SSVAL(params
,0,dptr_num
);
2660 SSVAL(params
,2,numentries
);
2661 SSVAL(params
,4,finished
);
2662 SSVAL(params
,6,0); /* Never an EA error */
2663 SSVAL(params
,8,last_entry_off
);
2665 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 10, pdata
, PTR_DIFF(p
,pdata
),
2668 if ((! *directory
) && dptr_path(sconn
, dptr_num
)) {
2669 directory
= talloc_strdup(talloc_tos(),dptr_path(sconn
, dptr_num
));
2671 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2675 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2676 smb_fn_name(req
->cmd
),
2677 mask
, directory
, dirtype
, numentries
) );
2680 * Force a name mangle here to ensure that the
2681 * mask as an 8.3 name is top of the mangled cache.
2682 * The reasons for this are subtle. Don't remove
2683 * this code unless you know what you are doing
2684 * (see PR#13758). JRA.
2687 if(!mangle_is_8_3_wildcards( mask
, False
, conn
->params
)) {
2688 char mangled_name
[13];
2689 name_to_8_3(mask
, mangled_name
, True
, conn
->params
);
2697 TALLOC_FREE(smb_dname
);
2701 /****************************************************************************
2702 Reply to a TRANS2_FINDNEXT.
2703 ****************************************************************************/
2705 static void call_trans2findnext(connection_struct
*conn
,
2706 struct smb_request
*req
,
2707 char **pparams
, int total_params
,
2708 char **ppdata
, int total_data
,
2709 unsigned int max_data_bytes
)
2711 /* We must be careful here that we don't return more than the
2712 allowed number of data bytes. If this means returning fewer than
2713 maxentries then so be it. We assume that the redirector has
2714 enough room for the fixed number of parameter bytes it has
2716 char *params
= *pparams
;
2717 char *pdata
= *ppdata
;
2723 uint16 findnext_flags
;
2724 bool close_after_request
;
2726 bool requires_resume_key
;
2728 bool mask_contains_wcard
= False
;
2729 char *resume_name
= NULL
;
2730 const char *mask
= NULL
;
2731 const char *directory
= NULL
;
2735 int i
, last_entry_off
=0;
2736 bool finished
= False
;
2737 bool dont_descend
= False
;
2738 bool out_of_space
= False
;
2739 int space_remaining
;
2740 struct ea_list
*ea_list
= NULL
;
2741 NTSTATUS ntstatus
= NT_STATUS_OK
;
2742 bool ask_sharemode
= lp_parm_bool(SNUM(conn
), "smbd", "search ask sharemode", true);
2743 TALLOC_CTX
*ctx
= talloc_tos();
2744 struct dptr_struct
*dirptr
;
2745 struct smbd_server_connection
*sconn
= req
->sconn
;
2746 bool backup_priv
= false;
2748 if (total_params
< 13) {
2749 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2753 dptr_num
= SVAL(params
,0);
2754 maxentries
= SVAL(params
,2);
2755 info_level
= SVAL(params
,4);
2756 resume_key
= IVAL(params
,6);
2757 findnext_flags
= SVAL(params
,10);
2758 close_after_request
= (findnext_flags
& FLAG_TRANS2_FIND_CLOSE
);
2759 close_if_end
= (findnext_flags
& FLAG_TRANS2_FIND_CLOSE_IF_END
);
2760 requires_resume_key
= (findnext_flags
& FLAG_TRANS2_FIND_REQUIRE_RESUME
);
2761 continue_bit
= (findnext_flags
& FLAG_TRANS2_FIND_CONTINUE
);
2763 if (!continue_bit
) {
2764 /* We only need resume_name if continue_bit is zero. */
2765 srvstr_get_path_wcard(ctx
, params
, req
->flags2
, &resume_name
,
2767 total_params
- 12, STR_TERMINATE
, &ntstatus
,
2768 &mask_contains_wcard
);
2769 if (!NT_STATUS_IS_OK(ntstatus
)) {
2770 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2771 complain (it thinks we're asking for the directory above the shared
2772 path or an invalid name). Catch this as the resume name is only compared, never used in
2773 a file access. JRA. */
2774 srvstr_pull_talloc(ctx
, params
, req
->flags2
,
2775 &resume_name
, params
+12,
2779 if (!resume_name
|| !(ISDOT(resume_name
) || ISDOTDOT(resume_name
))) {
2780 reply_nterror(req
, ntstatus
);
2786 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2787 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2788 resume_key = %d resume name = %s continue=%d level = %d\n",
2789 dptr_num
, max_data_bytes
, maxentries
, close_after_request
, close_if_end
,
2790 requires_resume_key
, resume_key
,
2791 resume_name
? resume_name
: "(NULL)", continue_bit
, info_level
));
2794 /* W2K3 seems to treat zero as 1. */
2798 switch (info_level
) {
2799 case SMB_FIND_INFO_STANDARD
:
2800 case SMB_FIND_EA_SIZE
:
2801 case SMB_FIND_EA_LIST
:
2802 case SMB_FIND_FILE_DIRECTORY_INFO
:
2803 case SMB_FIND_FILE_FULL_DIRECTORY_INFO
:
2804 case SMB_FIND_FILE_NAMES_INFO
:
2805 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO
:
2806 case SMB_FIND_ID_FULL_DIRECTORY_INFO
:
2807 case SMB_FIND_ID_BOTH_DIRECTORY_INFO
:
2809 case SMB_FIND_FILE_UNIX
:
2810 case SMB_FIND_FILE_UNIX_INFO2
:
2811 /* Always use filesystem for UNIX mtime query. */
2812 ask_sharemode
= false;
2813 if (!lp_unix_extensions()) {
2814 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2819 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
2823 if (info_level
== SMB_FIND_EA_LIST
) {
2826 if (total_data
< 4) {
2827 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2831 ea_size
= IVAL(pdata
,0);
2832 if (ea_size
!= total_data
) {
2833 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2834 total_data=%u (should be %u)\n", (unsigned int)total_data
, (unsigned int)IVAL(pdata
,0) ));
2835 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2839 if (!lp_ea_support(SNUM(conn
))) {
2840 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
2844 /* Pull out the list of names. */
2845 ea_list
= read_ea_name_list(ctx
, pdata
+ 4, ea_size
- 4);
2847 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2852 if (max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
< max_data_bytes
) {
2853 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2857 *ppdata
= (char *)SMB_REALLOC(
2858 *ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
2859 if(*ppdata
== NULL
) {
2860 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2865 data_end
= pdata
+ max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
- 1;
2867 /* Realloc the params space */
2868 *pparams
= (char *)SMB_REALLOC(*pparams
, 6*SIZEOFWORD
);
2869 if(*pparams
== NULL
) {
2870 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2876 /* Check that the dptr is valid */
2877 if(!(dirptr
= dptr_fetch_lanman2(sconn
, dptr_num
))) {
2878 reply_nterror(req
, STATUS_NO_MORE_FILES
);
2882 directory
= dptr_path(sconn
, dptr_num
);
2884 /* Get the wildcard mask from the dptr */
2885 if((mask
= dptr_wcard(sconn
, dptr_num
))== NULL
) {
2886 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num
));
2887 reply_nterror(req
, STATUS_NO_MORE_FILES
);
2891 /* Get the attr mask from the dptr */
2892 dirtype
= dptr_attr(sconn
, dptr_num
);
2894 backup_priv
= dptr_get_priv(dirptr
);
2896 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld) "
2897 "backup_priv = %d\n",
2898 dptr_num
, mask
, dirtype
,
2900 dptr_TellDir(dirptr
),
2903 /* Initialize per TRANS2_FIND_NEXT operation data */
2904 dptr_init_search_op(dirptr
);
2906 /* We don't need to check for VOL here as this is returned by
2907 a different TRANS2 call. */
2909 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2910 directory
,lp_dont_descend(ctx
, SNUM(conn
))));
2911 if (in_list(directory
,lp_dont_descend(ctx
, SNUM(conn
)),conn
->case_sensitive
))
2912 dont_descend
= True
;
2915 space_remaining
= max_data_bytes
;
2916 out_of_space
= False
;
2923 * Seek to the correct position. We no longer use the resume key but
2924 * depend on the last file name instead.
2927 if(!continue_bit
&& resume_name
&& *resume_name
) {
2930 long current_pos
= 0;
2932 * Remember, name_to_8_3 is called by
2933 * get_lanman2_dir_entry(), so the resume name
2934 * could be mangled. Ensure we check the unmangled name.
2937 if (mangle_is_mangled(resume_name
, conn
->params
)) {
2938 char *new_resume_name
= NULL
;
2939 mangle_lookup_name_from_8_3(ctx
,
2943 if (new_resume_name
) {
2944 resume_name
= new_resume_name
;
2949 * Fix for NT redirector problem triggered by resume key indexes
2950 * changing between directory scans. We now return a resume key of 0
2951 * and instead look for the filename to continue from (also given
2952 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2953 * findfirst/findnext (as is usual) then the directory pointer
2954 * should already be at the correct place.
2957 finished
= !dptr_SearchDir(dirptr
, resume_name
, ¤t_pos
, &st
);
2958 } /* end if resume_name && !continue_bit */
2960 for (i
=0;(i
<(int)maxentries
) && !finished
&& !out_of_space
;i
++) {
2961 bool got_exact_match
= False
;
2963 /* this is a heuristic to avoid seeking the dirptr except when
2964 absolutely necessary. It allows for a filename of about 40 chars */
2965 if (space_remaining
< DIRLEN_GUESS
&& numentries
> 0) {
2966 out_of_space
= True
;
2969 finished
= !get_lanman2_dir_entry(ctx
,
2973 mask
,dirtype
,info_level
,
2974 requires_resume_key
,dont_descend
,
2977 space_remaining
, &out_of_space
,
2979 &last_entry_off
, ea_list
);
2982 if (finished
&& out_of_space
)
2985 if (!finished
&& !out_of_space
)
2989 * As an optimisation if we know we aren't looking
2990 * for a wildcard name (ie. the name matches the wildcard exactly)
2991 * then we can finish on any (first) match.
2992 * This speeds up large directory searches. JRA.
2998 space_remaining
= max_data_bytes
- PTR_DIFF(p
,pdata
);
3001 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
3002 smb_fn_name(req
->cmd
),
3003 mask
, directory
, dirtype
, numentries
) );
3005 /* Check if we can close the dirptr */
3006 if(close_after_request
|| (finished
&& close_if_end
)) {
3007 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num
));
3008 dptr_close(sconn
, &dptr_num
); /* This frees up the saved mask */
3015 /* Set up the return parameter block */
3016 SSVAL(params
,0,numentries
);
3017 SSVAL(params
,2,finished
);
3018 SSVAL(params
,4,0); /* Never an EA error */
3019 SSVAL(params
,6,last_entry_off
);
3021 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 8, pdata
, PTR_DIFF(p
,pdata
),
3027 unsigned char *create_volume_objectid(connection_struct
*conn
, unsigned char objid
[16])
3029 E_md4hash(lp_servicename(talloc_tos(), SNUM(conn
)),objid
);
3033 static void samba_extended_info_version(struct smb_extended_info
*extended_info
)
3035 SMB_ASSERT(extended_info
!= NULL
);
3037 extended_info
->samba_magic
= SAMBA_EXTENDED_INFO_MAGIC
;
3038 extended_info
->samba_version
= ((SAMBA_VERSION_MAJOR
& 0xff) << 24)
3039 | ((SAMBA_VERSION_MINOR
& 0xff) << 16)
3040 | ((SAMBA_VERSION_RELEASE
& 0xff) << 8);
3041 #ifdef SAMBA_VERSION_REVISION
3042 extended_info
->samba_version
|= (tolower(*SAMBA_VERSION_REVISION
) - 'a' + 1) & 0xff;
3044 extended_info
->samba_subversion
= 0;
3045 #ifdef SAMBA_VERSION_RC_RELEASE
3046 extended_info
->samba_subversion
|= (SAMBA_VERSION_RC_RELEASE
& 0xff) << 24;
3048 #ifdef SAMBA_VERSION_PRE_RELEASE
3049 extended_info
->samba_subversion
|= (SAMBA_VERSION_PRE_RELEASE
& 0xff) << 16;
3052 #ifdef SAMBA_VERSION_VENDOR_PATCH
3053 extended_info
->samba_subversion
|= (SAMBA_VERSION_VENDOR_PATCH
& 0xffff);
3055 extended_info
->samba_gitcommitdate
= 0;
3056 #ifdef SAMBA_VERSION_COMMIT_TIME
3057 unix_to_nt_time(&extended_info
->samba_gitcommitdate
, SAMBA_VERSION_COMMIT_TIME
);
3060 memset(extended_info
->samba_version_string
, 0,
3061 sizeof(extended_info
->samba_version_string
));
3063 snprintf (extended_info
->samba_version_string
,
3064 sizeof(extended_info
->samba_version_string
),
3065 "%s", samba_version_string());
3068 NTSTATUS
smbd_do_qfsinfo(struct smbXsrv_connection
*xconn
,
3069 connection_struct
*conn
,
3070 TALLOC_CTX
*mem_ctx
,
3071 uint16_t info_level
,
3073 unsigned int max_data_bytes
,
3074 size_t *fixed_portion
,
3075 struct smb_filename
*fname
,
3079 char *pdata
, *end_data
;
3080 int data_len
= 0, len
;
3081 const char *vname
= volume_label(talloc_tos(), SNUM(conn
));
3082 int snum
= SNUM(conn
);
3083 const char *fstype
= lp_fstype(SNUM(conn
));
3084 const char *filename
= NULL
;
3085 uint32 additional_flags
= 0;
3086 struct smb_filename smb_fname
;
3088 NTSTATUS status
= NT_STATUS_OK
;
3090 if (fname
== NULL
|| fname
->base_name
== NULL
) {
3093 filename
= fname
->base_name
;
3097 if (info_level
!= SMB_QUERY_CIFS_UNIX_INFO
) {
3098 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
3099 "info level (0x%x) on IPC$.\n",
3100 (unsigned int)info_level
));
3101 return NT_STATUS_ACCESS_DENIED
;
3105 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level
));
3107 ZERO_STRUCT(smb_fname
);
3108 smb_fname
.base_name
= discard_const_p(char, filename
);
3110 if(SMB_VFS_STAT(conn
, &smb_fname
) != 0) {
3111 DEBUG(2,("stat of . failed (%s)\n", strerror(errno
)));
3112 return map_nt_error_from_unix(errno
);
3117 if (max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
< max_data_bytes
) {
3118 return NT_STATUS_INVALID_PARAMETER
;
3121 *ppdata
= (char *)SMB_REALLOC(
3122 *ppdata
, max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
3123 if (*ppdata
== NULL
) {
3124 return NT_STATUS_NO_MEMORY
;
3128 memset((char *)pdata
,'\0',max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
);
3129 end_data
= pdata
+ max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
- 1;
3133 switch (info_level
) {
3134 case SMB_INFO_ALLOCATION
:
3136 uint64_t dfree
,dsize
,bsize
,block_size
,sectors_per_unit
,bytes_per_sector
;
3138 if (get_dfree_info(conn
,filename
,False
,&bsize
,&dfree
,&dsize
) == (uint64_t)-1) {
3139 return map_nt_error_from_unix(errno
);
3142 block_size
= lp_block_size(snum
);
3143 if (bsize
< block_size
) {
3144 uint64_t factor
= block_size
/bsize
;
3149 if (bsize
> block_size
) {
3150 uint64_t factor
= bsize
/block_size
;
3155 bytes_per_sector
= 512;
3156 sectors_per_unit
= bsize
/bytes_per_sector
;
3158 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
3159 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st
.st_ex_dev
, (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
3160 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
3162 SIVAL(pdata
,l1_idFileSystem
,st
.st_ex_dev
);
3163 SIVAL(pdata
,l1_cSectorUnit
,sectors_per_unit
);
3164 SIVAL(pdata
,l1_cUnit
,dsize
);
3165 SIVAL(pdata
,l1_cUnitAvail
,dfree
);
3166 SSVAL(pdata
,l1_cbSector
,bytes_per_sector
);
3170 case SMB_INFO_VOLUME
:
3171 /* Return volume name */
3173 * Add volume serial number - hash of a combination of
3174 * the called hostname and the service name.
3176 SIVAL(pdata
,0,str_checksum(lp_servicename(talloc_tos(), snum
)) ^ (str_checksum(get_local_machine_name())<<16) );
3178 * Win2k3 and previous mess this up by sending a name length
3179 * one byte short. I believe only older clients (OS/2 Win9x) use
3180 * this call so try fixing this by adding a terminating null to
3181 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
3185 pdata
+l2_vol_szVolLabel
, vname
,
3186 PTR_DIFF(end_data
, pdata
+l2_vol_szVolLabel
),
3187 STR_NOALIGN
|STR_TERMINATE
);
3188 SCVAL(pdata
,l2_vol_cch
,len
);
3189 data_len
= l2_vol_szVolLabel
+ len
;
3190 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %d, name = %s\n",
3191 (unsigned)convert_timespec_to_time_t(st
.st_ex_ctime
),
3195 case SMB_QUERY_FS_ATTRIBUTE_INFO
:
3196 case SMB_FS_ATTRIBUTE_INFORMATION
:
3198 additional_flags
= 0;
3199 #if defined(HAVE_SYS_QUOTAS)
3200 additional_flags
|= FILE_VOLUME_QUOTAS
;
3203 if(lp_nt_acl_support(SNUM(conn
))) {
3204 additional_flags
|= FILE_PERSISTENT_ACLS
;
3207 /* Capabilities are filled in at connection time through STATVFS call */
3208 additional_flags
|= conn
->fs_capabilities
;
3209 additional_flags
|= lp_parm_int(conn
->params
->service
,
3210 "share", "fake_fscaps",
3213 SIVAL(pdata
,0,FILE_CASE_PRESERVED_NAMES
|FILE_CASE_SENSITIVE_SEARCH
|
3214 FILE_SUPPORTS_OBJECT_IDS
|FILE_UNICODE_ON_DISK
|
3215 additional_flags
); /* FS ATTRIBUTES */
3217 SIVAL(pdata
,4,255); /* Max filename component length */
3218 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
3219 and will think we can't do long filenames */
3220 len
= srvstr_push(pdata
, flags2
, pdata
+12, fstype
,
3221 PTR_DIFF(end_data
, pdata
+12),
3224 data_len
= 12 + len
;
3225 if (max_data_bytes
>= 16 && data_len
> max_data_bytes
) {
3226 /* the client only requested a portion of the
3228 data_len
= max_data_bytes
;
3229 status
= STATUS_BUFFER_OVERFLOW
;
3231 *fixed_portion
= 16;
3234 case SMB_QUERY_FS_LABEL_INFO
:
3235 case SMB_FS_LABEL_INFORMATION
:
3236 len
= srvstr_push(pdata
, flags2
, pdata
+4, vname
,
3237 PTR_DIFF(end_data
, pdata
+4), 0);
3242 case SMB_QUERY_FS_VOLUME_INFO
:
3243 case SMB_FS_VOLUME_INFORMATION
:
3246 * Add volume serial number - hash of a combination of
3247 * the called hostname and the service name.
3249 SIVAL(pdata
,8,str_checksum(lp_servicename(talloc_tos(), snum
)) ^
3250 (str_checksum(get_local_machine_name())<<16));
3252 /* Max label len is 32 characters. */
3253 len
= srvstr_push(pdata
, flags2
, pdata
+18, vname
,
3254 PTR_DIFF(end_data
, pdata
+18),
3256 SIVAL(pdata
,12,len
);
3259 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3260 (int)strlen(vname
),vname
,
3261 lp_servicename(talloc_tos(), snum
)));
3262 if (max_data_bytes
>= 24 && data_len
> max_data_bytes
) {
3263 /* the client only requested a portion of the
3265 data_len
= max_data_bytes
;
3266 status
= STATUS_BUFFER_OVERFLOW
;
3268 *fixed_portion
= 24;
3271 case SMB_QUERY_FS_SIZE_INFO
:
3272 case SMB_FS_SIZE_INFORMATION
:
3274 uint64_t dfree
,dsize
,bsize
,block_size
,sectors_per_unit
,bytes_per_sector
;
3276 if (get_dfree_info(conn
,filename
,False
,&bsize
,&dfree
,&dsize
) == (uint64_t)-1) {
3277 return map_nt_error_from_unix(errno
);
3279 block_size
= lp_block_size(snum
);
3280 if (bsize
< block_size
) {
3281 uint64_t factor
= block_size
/bsize
;
3286 if (bsize
> block_size
) {
3287 uint64_t factor
= bsize
/block_size
;
3292 bytes_per_sector
= 512;
3293 sectors_per_unit
= bsize
/bytes_per_sector
;
3294 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3295 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
3296 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
3297 SBIG_UINT(pdata
,0,dsize
);
3298 SBIG_UINT(pdata
,8,dfree
);
3299 SIVAL(pdata
,16,sectors_per_unit
);
3300 SIVAL(pdata
,20,bytes_per_sector
);
3301 *fixed_portion
= 24;
3305 case SMB_FS_FULL_SIZE_INFORMATION
:
3307 uint64_t dfree
,dsize
,bsize
,block_size
,sectors_per_unit
,bytes_per_sector
;
3309 if (get_dfree_info(conn
,filename
,False
,&bsize
,&dfree
,&dsize
) == (uint64_t)-1) {
3310 return map_nt_error_from_unix(errno
);
3312 block_size
= lp_block_size(snum
);
3313 if (bsize
< block_size
) {
3314 uint64_t factor
= block_size
/bsize
;
3319 if (bsize
> block_size
) {
3320 uint64_t factor
= bsize
/block_size
;
3325 bytes_per_sector
= 512;
3326 sectors_per_unit
= bsize
/bytes_per_sector
;
3327 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3328 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize
, (unsigned int)sectors_per_unit
,
3329 (unsigned int)bytes_per_sector
, (unsigned int)dsize
, (unsigned int)dfree
));
3330 SBIG_UINT(pdata
,0,dsize
); /* Total Allocation units. */
3331 SBIG_UINT(pdata
,8,dfree
); /* Caller available allocation units. */
3332 SBIG_UINT(pdata
,16,dfree
); /* Actual available allocation units. */
3333 SIVAL(pdata
,24,sectors_per_unit
); /* Sectors per allocation unit. */
3334 SIVAL(pdata
,28,bytes_per_sector
); /* Bytes per sector. */
3335 *fixed_portion
= 32;
3339 case SMB_QUERY_FS_DEVICE_INFO
:
3340 case SMB_FS_DEVICE_INFORMATION
:
3342 uint32_t characteristics
= FILE_DEVICE_IS_MOUNTED
;
3344 if (!CAN_WRITE(conn
)) {
3345 characteristics
|= FILE_READ_ONLY_DEVICE
;
3348 SIVAL(pdata
,0,FILE_DEVICE_DISK
); /* dev type */
3349 SIVAL(pdata
,4,characteristics
);
3354 #ifdef HAVE_SYS_QUOTAS
3355 case SMB_FS_QUOTA_INFORMATION
:
3357 * what we have to send --metze:
3359 * Unknown1: 24 NULL bytes
3360 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3361 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3362 * Quota Flags: 2 byte :
3363 * Unknown3: 6 NULL bytes
3367 * details for Quota Flags:
3369 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3370 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3371 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3372 * 0x0001 Enable Quotas: enable quota for this fs
3376 /* we need to fake up a fsp here,
3377 * because its not send in this call
3380 SMB_NTQUOTA_STRUCT quotas
;
3383 ZERO_STRUCT(quotas
);
3386 fsp
.fnum
= FNUM_FIELD_INVALID
;
3389 if (get_current_uid(conn
) != 0) {
3390 DEBUG(0,("get_user_quota: access_denied "
3391 "service [%s] user [%s]\n",
3392 lp_servicename(talloc_tos(), SNUM(conn
)),
3393 conn
->session_info
->unix_info
->unix_name
));
3394 return NT_STATUS_ACCESS_DENIED
;
3397 if (vfs_get_ntquota(&fsp
, SMB_USER_FS_QUOTA_TYPE
, NULL
, "as
)!=0) {
3398 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn
))));
3399 return map_nt_error_from_unix(errno
);
3404 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3405 lp_servicename(talloc_tos(), SNUM(conn
))));
3407 /* Unknown1 24 NULL bytes*/
3408 SBIG_UINT(pdata
,0,(uint64_t)0);
3409 SBIG_UINT(pdata
,8,(uint64_t)0);
3410 SBIG_UINT(pdata
,16,(uint64_t)0);
3412 /* Default Soft Quota 8 bytes */
3413 SBIG_UINT(pdata
,24,quotas
.softlim
);
3415 /* Default Hard Quota 8 bytes */
3416 SBIG_UINT(pdata
,32,quotas
.hardlim
);
3418 /* Quota flag 2 bytes */
3419 SSVAL(pdata
,40,quotas
.qflags
);
3421 /* Unknown3 6 NULL bytes */
3427 #endif /* HAVE_SYS_QUOTAS */
3428 case SMB_FS_OBJECTID_INFORMATION
:
3430 unsigned char objid
[16];
3431 struct smb_extended_info extended_info
;
3432 memcpy(pdata
,create_volume_objectid(conn
, objid
),16);
3433 samba_extended_info_version (&extended_info
);
3434 SIVAL(pdata
,16,extended_info
.samba_magic
);
3435 SIVAL(pdata
,20,extended_info
.samba_version
);
3436 SIVAL(pdata
,24,extended_info
.samba_subversion
);
3437 SBIG_UINT(pdata
,28,extended_info
.samba_gitcommitdate
);
3438 memcpy(pdata
+36,extended_info
.samba_version_string
,28);
3444 * Query the version and capabilities of the CIFS UNIX extensions
3448 case SMB_QUERY_CIFS_UNIX_INFO
:
3450 bool large_write
= lp_min_receive_file_size() &&
3451 !srv_is_signing_active(xconn
);
3452 bool large_read
= !srv_is_signing_active(xconn
);
3453 int encrypt_caps
= 0;
3455 if (!lp_unix_extensions()) {
3456 return NT_STATUS_INVALID_LEVEL
;
3459 switch (conn
->encrypt_level
) {
3460 case SMB_SIGNING_OFF
:
3463 case SMB_SIGNING_IF_REQUIRED
:
3464 case SMB_SIGNING_DEFAULT
:
3465 encrypt_caps
= CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP
;
3467 case SMB_SIGNING_REQUIRED
:
3468 encrypt_caps
= CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP
|
3469 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP
;
3470 large_write
= false;
3476 SSVAL(pdata
,0,CIFS_UNIX_MAJOR_VERSION
);
3477 SSVAL(pdata
,2,CIFS_UNIX_MINOR_VERSION
);
3479 /* We have POSIX ACLs, pathname, encryption,
3480 * large read/write, and locking capability. */
3482 SBIG_UINT(pdata
,4,((uint64_t)(
3483 CIFS_UNIX_POSIX_ACLS_CAP
|
3484 CIFS_UNIX_POSIX_PATHNAMES_CAP
|
3485 CIFS_UNIX_FCNTL_LOCKS_CAP
|
3486 CIFS_UNIX_EXTATTR_CAP
|
3487 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP
|
3489 (large_read
? CIFS_UNIX_LARGE_READ_CAP
: 0) |
3491 CIFS_UNIX_LARGE_WRITE_CAP
: 0))));
3495 case SMB_QUERY_POSIX_FS_INFO
:
3498 vfs_statvfs_struct svfs
;
3500 if (!lp_unix_extensions()) {
3501 return NT_STATUS_INVALID_LEVEL
;
3504 rc
= SMB_VFS_STATVFS(conn
, filename
, &svfs
);
3508 SIVAL(pdata
,0,svfs
.OptimalTransferSize
);
3509 SIVAL(pdata
,4,svfs
.BlockSize
);
3510 SBIG_UINT(pdata
,8,svfs
.TotalBlocks
);
3511 SBIG_UINT(pdata
,16,svfs
.BlocksAvail
);
3512 SBIG_UINT(pdata
,24,svfs
.UserBlocksAvail
);
3513 SBIG_UINT(pdata
,32,svfs
.TotalFileNodes
);
3514 SBIG_UINT(pdata
,40,svfs
.FreeFileNodes
);
3515 SBIG_UINT(pdata
,48,svfs
.FsIdentifier
);
3516 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3518 } else if (rc
== EOPNOTSUPP
) {
3519 return NT_STATUS_INVALID_LEVEL
;
3520 #endif /* EOPNOTSUPP */
3522 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn
))));
3523 return NT_STATUS_DOS(ERRSRV
, ERRerror
);
3528 case SMB_QUERY_POSIX_WHOAMI
:
3534 if (!lp_unix_extensions()) {
3535 return NT_STATUS_INVALID_LEVEL
;
3538 if (max_data_bytes
< 40) {
3539 return NT_STATUS_BUFFER_TOO_SMALL
;
3542 if (security_session_user_level(conn
->session_info
, NULL
) < SECURITY_USER
) {
3543 flags
|= SMB_WHOAMI_GUEST
;
3546 /* NOTE: 8 bytes for UID/GID, irrespective of native
3547 * platform size. This matches
3548 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3550 data_len
= 4 /* flags */
3557 + 4 /* pad/reserved */
3558 + (conn
->session_info
->unix_token
->ngroups
* 8)
3560 + (conn
->session_info
->security_token
->num_sids
*
3564 SIVAL(pdata
, 0, flags
);
3565 SIVAL(pdata
, 4, SMB_WHOAMI_MASK
);
3567 (uint64_t)conn
->session_info
->unix_token
->uid
);
3568 SBIG_UINT(pdata
, 16,
3569 (uint64_t)conn
->session_info
->unix_token
->gid
);
3572 if (data_len
>= max_data_bytes
) {
3573 /* Potential overflow, skip the GIDs and SIDs. */
3575 SIVAL(pdata
, 24, 0); /* num_groups */
3576 SIVAL(pdata
, 28, 0); /* num_sids */
3577 SIVAL(pdata
, 32, 0); /* num_sid_bytes */
3578 SIVAL(pdata
, 36, 0); /* reserved */
3584 SIVAL(pdata
, 24, conn
->session_info
->unix_token
->ngroups
);
3585 SIVAL(pdata
, 28, conn
->session_info
->security_token
->num_sids
);
3587 /* We walk the SID list twice, but this call is fairly
3588 * infrequent, and I don't expect that it's performance
3589 * sensitive -- jpeach
3591 for (i
= 0, sid_bytes
= 0;
3592 i
< conn
->session_info
->security_token
->num_sids
; ++i
) {
3593 sid_bytes
+= ndr_size_dom_sid(
3594 &conn
->session_info
->security_token
->sids
[i
],
3598 /* SID list byte count */
3599 SIVAL(pdata
, 32, sid_bytes
);
3601 /* 4 bytes pad/reserved - must be zero */
3602 SIVAL(pdata
, 36, 0);
3606 for (i
= 0; i
< conn
->session_info
->unix_token
->ngroups
; ++i
) {
3607 SBIG_UINT(pdata
, data_len
,
3608 (uint64_t)conn
->session_info
->unix_token
->groups
[i
]);
3614 i
< conn
->session_info
->security_token
->num_sids
; ++i
) {
3615 int sid_len
= ndr_size_dom_sid(
3616 &conn
->session_info
->security_token
->sids
[i
],
3619 sid_linearize(pdata
+ data_len
, sid_len
,
3620 &conn
->session_info
->security_token
->sids
[i
]);
3621 data_len
+= sid_len
;
3627 case SMB_MAC_QUERY_FS_INFO
:
3629 * Thursby MAC extension... ONLY on NTFS filesystems
3630 * once we do streams then we don't need this
3632 if (strequal(lp_fstype(SNUM(conn
)),"NTFS")) {
3634 SIVAL(pdata
,84,0x100); /* Don't support mac... */
3639 return NT_STATUS_INVALID_LEVEL
;
3642 *ret_data_len
= data_len
;
3646 /****************************************************************************
3647 Reply to a TRANS2_QFSINFO (query filesystem info).
3648 ****************************************************************************/
3650 static void call_trans2qfsinfo(connection_struct
*conn
,
3651 struct smb_request
*req
,
3652 char **pparams
, int total_params
,
3653 char **ppdata
, int total_data
,
3654 unsigned int max_data_bytes
)
3656 char *params
= *pparams
;
3657 uint16_t info_level
;
3659 size_t fixed_portion
;
3662 if (total_params
< 2) {
3663 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3667 info_level
= SVAL(params
,0);
3669 if (ENCRYPTION_REQUIRED(conn
) && !req
->encrypted
) {
3670 if (info_level
!= SMB_QUERY_CIFS_UNIX_INFO
) {
3671 DEBUG(0,("call_trans2qfsinfo: encryption required "
3672 "and info level 0x%x sent.\n",
3673 (unsigned int)info_level
));
3674 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3679 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level
));
3681 status
= smbd_do_qfsinfo(req
->xconn
, conn
, req
,
3688 if (!NT_STATUS_IS_OK(status
)) {
3689 reply_nterror(req
, status
);
3693 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 0, *ppdata
, data_len
,
3696 DEBUG( 4, ( "%s info_level = %d\n",
3697 smb_fn_name(req
->cmd
), info_level
) );
3702 /****************************************************************************
3703 Reply to a TRANS2_SETFSINFO (set filesystem info).
3704 ****************************************************************************/
3706 static void call_trans2setfsinfo(connection_struct
*conn
,
3707 struct smb_request
*req
,
3708 char **pparams
, int total_params
,
3709 char **ppdata
, int total_data
,
3710 unsigned int max_data_bytes
)
3712 struct smbXsrv_connection
*xconn
= req
->xconn
;
3713 char *pdata
= *ppdata
;
3714 char *params
= *pparams
;
3717 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",
3718 lp_servicename(talloc_tos(), SNUM(conn
))));
3721 if (total_params
< 4) {
3722 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3724 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3728 info_level
= SVAL(params
,2);
3731 if (info_level
!= SMB_REQUEST_TRANSPORT_ENCRYPTION
&&
3732 info_level
!= SMB_SET_CIFS_UNIX_INFO
) {
3733 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3734 "info level (0x%x) on IPC$.\n",
3735 (unsigned int)info_level
));
3736 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3741 if (ENCRYPTION_REQUIRED(conn
) && !req
->encrypted
) {
3742 if (info_level
!= SMB_REQUEST_TRANSPORT_ENCRYPTION
) {
3743 DEBUG(0,("call_trans2setfsinfo: encryption required "
3744 "and info level 0x%x sent.\n",
3745 (unsigned int)info_level
));
3746 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3751 switch(info_level
) {
3752 case SMB_SET_CIFS_UNIX_INFO
:
3753 if (!lp_unix_extensions()) {
3754 DEBUG(2,("call_trans2setfsinfo: "
3755 "SMB_SET_CIFS_UNIX_INFO is invalid with "
3756 "unix extensions off\n"));
3758 NT_STATUS_INVALID_LEVEL
);
3762 /* There should be 12 bytes of capabilities set. */
3763 if (total_data
< 12) {
3766 NT_STATUS_INVALID_PARAMETER
);
3769 xconn
->smb1
.unix_info
.client_major
= SVAL(pdata
,0);
3770 xconn
->smb1
.unix_info
.client_minor
= SVAL(pdata
,2);
3771 xconn
->smb1
.unix_info
.client_cap_low
= IVAL(pdata
,4);
3772 xconn
->smb1
.unix_info
.client_cap_high
= IVAL(pdata
,8);
3773 /* Just print these values for now. */
3774 DEBUG(10, ("call_trans2setfsinfo: set unix_info info. "
3775 "major = %u, minor = %u cap_low = 0x%x, "
3777 (unsigned int)xconn
->
3778 smb1
.unix_info
.client_major
,
3779 (unsigned int)xconn
->
3780 smb1
.unix_info
.client_minor
,
3781 (unsigned int)xconn
->
3782 smb1
.unix_info
.client_cap_low
,
3783 (unsigned int)xconn
->
3784 smb1
.unix_info
.client_cap_high
));
3786 /* Here is where we must switch to posix pathname processing... */
3787 if (xconn
->smb1
.unix_info
.client_cap_low
& CIFS_UNIX_POSIX_PATHNAMES_CAP
) {
3788 lp_set_posix_pathnames();
3789 mangle_change_to_posix();
3792 if ((xconn
->smb1
.unix_info
.client_cap_low
& CIFS_UNIX_FCNTL_LOCKS_CAP
) &&
3793 !(xconn
->smb1
.unix_info
.client_cap_low
& CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP
)) {
3794 /* Client that knows how to do posix locks,
3795 * but not posix open/mkdir operations. Set a
3796 * default type for read/write checks. */
3798 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK
);
3803 case SMB_REQUEST_TRANSPORT_ENCRYPTION
:
3806 size_t param_len
= 0;
3807 size_t data_len
= total_data
;
3809 if (!lp_unix_extensions()) {
3812 NT_STATUS_INVALID_LEVEL
);
3816 if (lp_smb_encrypt(SNUM(conn
)) == SMB_SIGNING_OFF
) {
3819 NT_STATUS_NOT_SUPPORTED
);
3823 if (xconn
->smb1
.echo_handler
.trusted_fde
) {
3824 DEBUG( 2,("call_trans2setfsinfo: "
3825 "request transport encryption disabled"
3826 "with 'fork echo handler = yes'\n"));
3829 NT_STATUS_NOT_SUPPORTED
);
3833 DEBUG( 4,("call_trans2setfsinfo: "
3834 "request transport encryption.\n"));
3836 status
= srv_request_encryption_setup(conn
,
3837 (unsigned char **)ppdata
,
3839 (unsigned char **)pparams
,
3842 if (!NT_STATUS_EQUAL(status
, NT_STATUS_MORE_PROCESSING_REQUIRED
) &&
3843 !NT_STATUS_IS_OK(status
)) {
3844 reply_nterror(req
, status
);
3848 send_trans2_replies(conn
, req
,
3856 if (NT_STATUS_IS_OK(status
)) {
3857 /* Server-side transport
3858 * encryption is now *on*. */
3859 status
= srv_encryption_start(conn
);
3860 if (!NT_STATUS_IS_OK(status
)) {
3861 char *reason
= talloc_asprintf(talloc_tos(),
3862 "Failure in setting "
3863 "up encrypted transport: %s",
3865 exit_server_cleanly(reason
);
3871 case SMB_FS_QUOTA_INFORMATION
:
3873 files_struct
*fsp
= NULL
;
3874 SMB_NTQUOTA_STRUCT quotas
;
3876 ZERO_STRUCT(quotas
);
3879 if ((get_current_uid(conn
) != 0) || !CAN_WRITE(conn
)) {
3880 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3881 lp_servicename(talloc_tos(), SNUM(conn
)),
3882 conn
->session_info
->unix_info
->unix_name
));
3883 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3887 /* note: normaly there're 48 bytes,
3888 * but we didn't use the last 6 bytes for now
3891 fsp
= file_fsp(req
, SVAL(params
,0));
3893 if (!check_fsp_ntquota_handle(conn
, req
,
3895 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3897 req
, NT_STATUS_INVALID_HANDLE
);
3901 if (total_data
< 42) {
3902 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3906 NT_STATUS_INVALID_PARAMETER
);
3910 /* unknown_1 24 NULL bytes in pdata*/
3912 /* the soft quotas 8 bytes (uint64_t)*/
3913 quotas
.softlim
= BVAL(pdata
,24);
3915 /* the hard quotas 8 bytes (uint64_t)*/
3916 quotas
.hardlim
= BVAL(pdata
,32);
3918 /* quota_flags 2 bytes **/
3919 quotas
.qflags
= SVAL(pdata
,40);
3921 /* unknown_2 6 NULL bytes follow*/
3923 /* now set the quotas */
3924 if (vfs_set_ntquota(fsp
, SMB_USER_FS_QUOTA_TYPE
, NULL
, "as
)!=0) {
3925 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn
))));
3926 reply_nterror(req
, map_nt_error_from_unix(errno
));
3933 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3935 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
3941 * sending this reply works fine,
3942 * but I'm not sure it's the same
3943 * like windows do...
3946 reply_outbuf(req
, 10, 0);
3949 #if defined(HAVE_POSIX_ACLS)
3950 /****************************************************************************
3951 Utility function to count the number of entries in a POSIX acl.
3952 ****************************************************************************/
3954 static unsigned int count_acl_entries(connection_struct
*conn
, SMB_ACL_T posix_acl
)
3956 unsigned int ace_count
= 0;
3957 int entry_id
= SMB_ACL_FIRST_ENTRY
;
3958 SMB_ACL_ENTRY_T entry
;
3960 while ( posix_acl
&& (sys_acl_get_entry(posix_acl
, entry_id
, &entry
) == 1)) {
3962 if (entry_id
== SMB_ACL_FIRST_ENTRY
) {
3963 entry_id
= SMB_ACL_NEXT_ENTRY
;
3970 /****************************************************************************
3971 Utility function to marshall a POSIX acl into wire format.
3972 ****************************************************************************/
3974 static bool marshall_posix_acl(connection_struct
*conn
, char *pdata
, SMB_STRUCT_STAT
*pst
, SMB_ACL_T posix_acl
)
3976 int entry_id
= SMB_ACL_FIRST_ENTRY
;
3977 SMB_ACL_ENTRY_T entry
;
3979 while ( posix_acl
&& (sys_acl_get_entry(posix_acl
, entry_id
, &entry
) == 1)) {
3980 SMB_ACL_TAG_T tagtype
;
3981 SMB_ACL_PERMSET_T permset
;
3982 unsigned char perms
= 0;
3983 unsigned int own_grp
;
3986 if (entry_id
== SMB_ACL_FIRST_ENTRY
) {
3987 entry_id
= SMB_ACL_NEXT_ENTRY
;
3990 if (sys_acl_get_tag_type(entry
, &tagtype
) == -1) {
3991 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3995 if (sys_acl_get_permset(entry
, &permset
) == -1) {
3996 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
4000 perms
|= (sys_acl_get_perm(permset
, SMB_ACL_READ
) ? SMB_POSIX_ACL_READ
: 0);
4001 perms
|= (sys_acl_get_perm(permset
, SMB_ACL_WRITE
) ? SMB_POSIX_ACL_WRITE
: 0);
4002 perms
|= (sys_acl_get_perm(permset
, SMB_ACL_EXECUTE
) ? SMB_POSIX_ACL_EXECUTE
: 0);
4004 SCVAL(pdata
,1,perms
);
4007 case SMB_ACL_USER_OBJ
:
4008 SCVAL(pdata
,0,SMB_POSIX_ACL_USER_OBJ
);
4009 own_grp
= (unsigned int)pst
->st_ex_uid
;
4010 SIVAL(pdata
,2,own_grp
);
4015 uid_t
*puid
= (uid_t
*)sys_acl_get_qualifier(entry
);
4017 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
4020 own_grp
= (unsigned int)*puid
;
4021 SCVAL(pdata
,0,SMB_POSIX_ACL_USER
);
4022 SIVAL(pdata
,2,own_grp
);
4026 case SMB_ACL_GROUP_OBJ
:
4027 SCVAL(pdata
,0,SMB_POSIX_ACL_GROUP_OBJ
);
4028 own_grp
= (unsigned int)pst
->st_ex_gid
;
4029 SIVAL(pdata
,2,own_grp
);
4034 gid_t
*pgid
= (gid_t
*)sys_acl_get_qualifier(entry
);
4036 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
4039 own_grp
= (unsigned int)*pgid
;
4040 SCVAL(pdata
,0,SMB_POSIX_ACL_GROUP
);
4041 SIVAL(pdata
,2,own_grp
);
4046 SCVAL(pdata
,0,SMB_POSIX_ACL_MASK
);
4047 SIVAL(pdata
,2,0xFFFFFFFF);
4048 SIVAL(pdata
,6,0xFFFFFFFF);
4051 SCVAL(pdata
,0,SMB_POSIX_ACL_OTHER
);
4052 SIVAL(pdata
,2,0xFFFFFFFF);
4053 SIVAL(pdata
,6,0xFFFFFFFF);
4056 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
4059 pdata
+= SMB_POSIX_ACL_ENTRY_SIZE
;
4066 /****************************************************************************
4067 Store the FILE_UNIX_BASIC info.
4068 ****************************************************************************/
4070 static char *store_file_unix_basic(connection_struct
*conn
,
4073 const SMB_STRUCT_STAT
*psbuf
)
4075 uint64_t file_index
= get_FileIndex(conn
, psbuf
);
4078 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
4079 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf
->st_ex_mode
));
4081 SOFF_T(pdata
,0,get_file_size_stat(psbuf
)); /* File size 64 Bit */
4084 SOFF_T(pdata
,0,SMB_VFS_GET_ALLOC_SIZE(conn
,fsp
,psbuf
)); /* Number of bytes used on disk - 64 Bit */
4087 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER
, pdata
, psbuf
->st_ex_ctime
); /* Change Time 64 Bit */
4088 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER
,pdata
+8, psbuf
->st_ex_atime
); /* Last access time 64 Bit */
4089 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER
, pdata
+16, psbuf
->st_ex_mtime
); /* Last modification time 64 Bit */
4092 SIVAL(pdata
,0,psbuf
->st_ex_uid
); /* user id for the owner */
4096 SIVAL(pdata
,0,psbuf
->st_ex_gid
); /* group id of owner */
4100 SIVAL(pdata
,0,unix_filetype(psbuf
->st_ex_mode
));
4103 if (S_ISBLK(psbuf
->st_ex_mode
) || S_ISCHR(psbuf
->st_ex_mode
)) {
4104 devno
= psbuf
->st_ex_rdev
;
4106 devno
= psbuf
->st_ex_dev
;
4109 SIVAL(pdata
,0,unix_dev_major(devno
)); /* Major device number if type is device */
4113 SIVAL(pdata
,0,unix_dev_minor(devno
)); /* Minor device number if type is device */
4117 SINO_T_VAL(pdata
,0,(SMB_INO_T
)file_index
); /* inode number */
4120 SIVAL(pdata
,0, unix_perms_to_wire(psbuf
->st_ex_mode
)); /* Standard UNIX file permissions */
4124 SIVAL(pdata
,0,psbuf
->st_ex_nlink
); /* number of hard links */
4131 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
4132 * the chflags(2) (or equivalent) flags.
4134 * XXX: this really should be behind the VFS interface. To do this, we would
4135 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
4136 * Each VFS module could then implement its own mapping as appropriate for the
4137 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
4139 static const struct {unsigned stat_fflag
; unsigned smb_fflag
;}
4143 { UF_NODUMP
, EXT_DO_NOT_BACKUP
},
4147 { UF_IMMUTABLE
, EXT_IMMUTABLE
},
4151 { UF_APPEND
, EXT_OPEN_APPEND_ONLY
},
4155 { UF_HIDDEN
, EXT_HIDDEN
},
4158 /* Do not remove. We need to guarantee that this array has at least one
4159 * entry to build on HP-UX.
4165 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT
*psbuf
,
4166 uint32
*smb_fflags
, uint32
*smb_fmask
)
4170 for (i
= 0; i
< ARRAY_SIZE(info2_flags_map
); ++i
) {
4171 *smb_fmask
|= info2_flags_map
[i
].smb_fflag
;
4172 if (psbuf
->st_ex_flags
& info2_flags_map
[i
].stat_fflag
) {
4173 *smb_fflags
|= info2_flags_map
[i
].smb_fflag
;
4178 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT
*psbuf
,
4179 const uint32 smb_fflags
,
4180 const uint32 smb_fmask
,
4183 uint32 max_fmask
= 0;
4186 *stat_fflags
= psbuf
->st_ex_flags
;
4188 /* For each flags requested in smb_fmask, check the state of the
4189 * corresponding flag in smb_fflags and set or clear the matching
4193 for (i
= 0; i
< ARRAY_SIZE(info2_flags_map
); ++i
) {
4194 max_fmask
|= info2_flags_map
[i
].smb_fflag
;
4195 if (smb_fmask
& info2_flags_map
[i
].smb_fflag
) {
4196 if (smb_fflags
& info2_flags_map
[i
].smb_fflag
) {
4197 *stat_fflags
|= info2_flags_map
[i
].stat_fflag
;
4199 *stat_fflags
&= ~info2_flags_map
[i
].stat_fflag
;
4204 /* If smb_fmask is asking to set any bits that are not supported by
4205 * our flag mappings, we should fail.
4207 if ((smb_fmask
& max_fmask
) != smb_fmask
) {
4215 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
4216 * of file flags and birth (create) time.
4218 static char *store_file_unix_basic_info2(connection_struct
*conn
,
4221 const SMB_STRUCT_STAT
*psbuf
)
4223 uint32 file_flags
= 0;
4224 uint32 flags_mask
= 0;
4226 pdata
= store_file_unix_basic(conn
, pdata
, fsp
, psbuf
);
4228 /* Create (birth) time 64 bit */
4229 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER
,pdata
, psbuf
->st_ex_btime
);
4232 map_info2_flags_from_sbuf(psbuf
, &file_flags
, &flags_mask
);
4233 SIVAL(pdata
, 0, file_flags
); /* flags */
4234 SIVAL(pdata
, 4, flags_mask
); /* mask */
4240 static NTSTATUS
marshall_stream_info(unsigned int num_streams
,
4241 const struct stream_struct
*streams
,
4243 unsigned int max_data_bytes
,
4244 unsigned int *data_size
)
4247 unsigned int ofs
= 0;
4249 if (max_data_bytes
< 32) {
4250 return NT_STATUS_INFO_LENGTH_MISMATCH
;
4253 for (i
= 0; i
< num_streams
; i
++) {
4254 unsigned int next_offset
;
4256 smb_ucs2_t
*namebuf
;
4258 if (!push_ucs2_talloc(talloc_tos(), &namebuf
,
4259 streams
[i
].name
, &namelen
) ||
4262 return NT_STATUS_INVALID_PARAMETER
;
4266 * name_buf is now null-terminated, we need to marshall as not
4273 * We cannot overflow ...
4275 if ((ofs
+ 24 + namelen
) > max_data_bytes
) {
4276 DEBUG(10, ("refusing to overflow reply at stream %u\n",
4278 TALLOC_FREE(namebuf
);
4279 return STATUS_BUFFER_OVERFLOW
;
4282 SIVAL(data
, ofs
+4, namelen
);
4283 SOFF_T(data
, ofs
+8, streams
[i
].size
);
4284 SOFF_T(data
, ofs
+16, streams
[i
].alloc_size
);
4285 memcpy(data
+ofs
+24, namebuf
, namelen
);
4286 TALLOC_FREE(namebuf
);
4288 next_offset
= ofs
+ 24 + namelen
;
4290 if (i
== num_streams
-1) {
4291 SIVAL(data
, ofs
, 0);
4294 unsigned int align
= ndr_align_size(next_offset
, 8);
4296 if ((next_offset
+ align
) > max_data_bytes
) {
4297 DEBUG(10, ("refusing to overflow align "
4298 "reply at stream %u\n",
4300 TALLOC_FREE(namebuf
);
4301 return STATUS_BUFFER_OVERFLOW
;
4304 memset(data
+next_offset
, 0, align
);
4305 next_offset
+= align
;
4307 SIVAL(data
, ofs
, next_offset
- ofs
);
4314 DEBUG(10, ("max_data: %u, data_size: %u\n", max_data_bytes
, ofs
));
4318 return NT_STATUS_OK
;
4321 /****************************************************************************
4322 Reply to a TRANSACT2_QFILEINFO on a PIPE !
4323 ****************************************************************************/
4325 static void call_trans2qpipeinfo(connection_struct
*conn
,
4326 struct smb_request
*req
,
4327 unsigned int tran_call
,
4328 char **pparams
, int total_params
,
4329 char **ppdata
, int total_data
,
4330 unsigned int max_data_bytes
)
4332 char *params
= *pparams
;
4333 char *pdata
= *ppdata
;
4334 unsigned int data_size
= 0;
4335 unsigned int param_size
= 2;
4340 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4344 if (total_params
< 4) {
4345 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4349 fsp
= file_fsp(req
, SVAL(params
,0));
4350 if (!fsp_is_np(fsp
)) {
4351 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
4355 info_level
= SVAL(params
,2);
4357 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
4358 if (*pparams
== NULL
) {
4359 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
4364 if (max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
< max_data_bytes
) {
4365 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4368 data_size
= max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
;
4369 *ppdata
= (char *)SMB_REALLOC(*ppdata
, data_size
);
4370 if (*ppdata
== NULL
) {
4371 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
4376 switch (info_level
) {
4377 case SMB_FILE_STANDARD_INFORMATION
:
4379 SOFF_T(pdata
,0,4096LL);
4386 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
4390 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, param_size
, *ppdata
, data_size
,
4396 NTSTATUS
smbd_do_qfilepathinfo(connection_struct
*conn
,
4397 TALLOC_CTX
*mem_ctx
,
4398 uint16_t info_level
,
4400 struct smb_filename
*smb_fname
,
4401 bool delete_pending
,
4402 struct timespec write_time_ts
,
4403 struct ea_list
*ea_list
,
4404 int lock_data_count
,
4407 unsigned int max_data_bytes
,
4408 size_t *fixed_portion
,
4410 unsigned int *pdata_size
)
4412 char *pdata
= *ppdata
;
4413 char *dstart
, *dend
;
4414 unsigned int data_size
;
4415 struct timespec create_time_ts
, mtime_ts
, atime_ts
, ctime_ts
;
4416 time_t create_time
, mtime
, atime
, c_time
;
4417 SMB_STRUCT_STAT
*psbuf
= &smb_fname
->st
;
4424 uint64_t file_size
= 0;
4426 uint64_t allocation_size
= 0;
4427 uint64_t file_index
= 0;
4428 uint32_t access_mask
= 0;
4430 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
4431 return NT_STATUS_INVALID_LEVEL
;
4434 DEBUG(5,("smbd_do_qfilepathinfo: %s (%s) level=%d max_data=%u\n",
4435 smb_fname_str_dbg(smb_fname
),
4437 info_level
, max_data_bytes
));
4439 mode
= dos_mode(conn
, smb_fname
);
4440 nlink
= psbuf
->st_ex_nlink
;
4442 if (nlink
&& (mode
&FILE_ATTRIBUTE_DIRECTORY
)) {
4446 if ((nlink
> 0) && delete_pending
) {
4450 if (max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
< max_data_bytes
) {
4451 return NT_STATUS_INVALID_PARAMETER
;
4454 data_size
= max_data_bytes
+ DIR_ENTRY_SAFETY_MARGIN
;
4455 *ppdata
= (char *)SMB_REALLOC(*ppdata
, data_size
);
4456 if (*ppdata
== NULL
) {
4457 return NT_STATUS_NO_MEMORY
;
4461 dend
= dstart
+ data_size
- 1;
4463 if (!null_timespec(write_time_ts
) && !INFO_LEVEL_IS_UNIX(info_level
)) {
4464 update_stat_ex_mtime(psbuf
, write_time_ts
);
4467 create_time_ts
= get_create_timespec(conn
, fsp
, smb_fname
);
4468 mtime_ts
= psbuf
->st_ex_mtime
;
4469 atime_ts
= psbuf
->st_ex_atime
;
4470 ctime_ts
= get_change_timespec(conn
, fsp
, smb_fname
);
4472 if (lp_dos_filetime_resolution(SNUM(conn
))) {
4473 dos_filetime_timespec(&create_time_ts
);
4474 dos_filetime_timespec(&mtime_ts
);
4475 dos_filetime_timespec(&atime_ts
);
4476 dos_filetime_timespec(&ctime_ts
);
4479 create_time
= convert_timespec_to_time_t(create_time_ts
);
4480 mtime
= convert_timespec_to_time_t(mtime_ts
);
4481 atime
= convert_timespec_to_time_t(atime_ts
);
4482 c_time
= convert_timespec_to_time_t(ctime_ts
);
4484 p
= strrchr_m(smb_fname
->base_name
,'/');
4486 base_name
= smb_fname
->base_name
;
4490 /* NT expects the name to be in an exact form of the *full*
4491 filename. See the trans2 torture test */
4492 if (ISDOT(base_name
)) {
4493 dos_fname
= talloc_strdup(mem_ctx
, "\\");
4495 return NT_STATUS_NO_MEMORY
;
4498 dos_fname
= talloc_asprintf(mem_ctx
,
4500 smb_fname
->base_name
);
4502 return NT_STATUS_NO_MEMORY
;
4504 if (is_ntfs_stream_smb_fname(smb_fname
)) {
4505 dos_fname
= talloc_asprintf(dos_fname
, "%s",
4506 smb_fname
->stream_name
);
4508 return NT_STATUS_NO_MEMORY
;
4512 string_replace(dos_fname
, '/', '\\');
4515 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
, fsp
, psbuf
);
4518 /* Do we have this path open ? */
4520 struct file_id fileid
= vfs_file_id_from_sbuf(conn
, psbuf
);
4521 fsp1
= file_find_di_first(conn
->sconn
, fileid
);
4522 if (fsp1
&& fsp1
->initial_allocation_size
) {
4523 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
, fsp1
, psbuf
);
4527 if (!(mode
& FILE_ATTRIBUTE_DIRECTORY
)) {
4528 file_size
= get_file_size_stat(psbuf
);
4532 pos
= fsp
->fh
->position_information
;
4536 access_mask
= fsp
->access_mask
;
4538 /* GENERIC_EXECUTE mapping from Windows */
4539 access_mask
= 0x12019F;
4542 /* This should be an index number - looks like
4545 I think this causes us to fail the IFSKIT
4546 BasicFileInformationTest. -tpot */
4547 file_index
= get_FileIndex(conn
, psbuf
);
4551 switch (info_level
) {
4552 case SMB_INFO_STANDARD
:
4553 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4555 srv_put_dos_date2(pdata
,l1_fdateCreation
,create_time
);
4556 srv_put_dos_date2(pdata
,l1_fdateLastAccess
,atime
);
4557 srv_put_dos_date2(pdata
,l1_fdateLastWrite
,mtime
); /* write time */
4558 SIVAL(pdata
,l1_cbFile
,(uint32
)file_size
);
4559 SIVAL(pdata
,l1_cbFileAlloc
,(uint32
)allocation_size
);
4560 SSVAL(pdata
,l1_attrFile
,mode
);
4563 case SMB_INFO_QUERY_EA_SIZE
:
4565 unsigned int ea_size
=
4566 estimate_ea_size(conn
, fsp
,
4568 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4570 srv_put_dos_date2(pdata
,0,create_time
);
4571 srv_put_dos_date2(pdata
,4,atime
);
4572 srv_put_dos_date2(pdata
,8,mtime
); /* write time */
4573 SIVAL(pdata
,12,(uint32
)file_size
);
4574 SIVAL(pdata
,16,(uint32
)allocation_size
);
4575 SSVAL(pdata
,20,mode
);
4576 SIVAL(pdata
,22,ea_size
);
4580 case SMB_INFO_IS_NAME_VALID
:
4581 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4583 /* os/2 needs this ? really ?*/
4584 return NT_STATUS_DOS(ERRDOS
, ERRbadfunc
);
4586 /* This is only reached for qpathinfo */
4590 case SMB_INFO_QUERY_EAS_FROM_LIST
:
4592 size_t total_ea_len
= 0;
4593 struct ea_list
*ea_file_list
= NULL
;
4594 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4597 get_ea_list_from_file(mem_ctx
, conn
, fsp
,
4599 &total_ea_len
, &ea_file_list
);
4600 if (!NT_STATUS_IS_OK(status
)) {
4604 ea_list
= ea_list_union(ea_list
, ea_file_list
, &total_ea_len
);
4606 if (!ea_list
|| (total_ea_len
> data_size
)) {
4608 SIVAL(pdata
,0,4); /* EA List Length must be set to 4 if no EA's. */
4612 data_size
= fill_ea_buffer(mem_ctx
, pdata
, data_size
, conn
, ea_list
);
4616 case SMB_INFO_QUERY_ALL_EAS
:
4618 /* We have data_size bytes to put EA's into. */
4619 size_t total_ea_len
= 0;
4620 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4622 status
= get_ea_list_from_file(mem_ctx
, conn
, fsp
,
4624 &total_ea_len
, &ea_list
);
4625 if (!NT_STATUS_IS_OK(status
)) {
4629 if (!ea_list
|| (total_ea_len
> data_size
)) {
4631 SIVAL(pdata
,0,4); /* EA List Length must be set to 4 if no EA's. */
4635 data_size
= fill_ea_buffer(mem_ctx
, pdata
, data_size
, conn
, ea_list
);
4639 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
4641 /* This is FileFullEaInformation - 0xF which maps to
4642 * 1015 (decimal) in smbd_do_setfilepathinfo. */
4644 /* We have data_size bytes to put EA's into. */
4645 size_t total_ea_len
= 0;
4646 struct ea_list
*ea_file_list
= NULL
;
4648 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
4650 /*TODO: add filtering and index handling */
4653 get_ea_list_from_file(mem_ctx
, conn
, fsp
,
4655 &total_ea_len
, &ea_file_list
);
4656 if (!NT_STATUS_IS_OK(status
)) {
4659 if (!ea_file_list
) {
4660 return NT_STATUS_NO_EAS_ON_FILE
;
4663 status
= fill_ea_chained_buffer(mem_ctx
,
4667 conn
, ea_file_list
);
4668 if (!NT_STATUS_IS_OK(status
)) {
4674 case SMB_FILE_BASIC_INFORMATION
:
4675 case SMB_QUERY_FILE_BASIC_INFO
:
4677 if (info_level
== SMB_QUERY_FILE_BASIC_INFO
) {
4678 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4679 data_size
= 36; /* w95 returns 40 bytes not 36 - why ?. */
4681 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4685 put_long_date_timespec(conn
->ts_res
,pdata
,create_time_ts
);
4686 put_long_date_timespec(conn
->ts_res
,pdata
+8,atime_ts
);
4687 put_long_date_timespec(conn
->ts_res
,pdata
+16,mtime_ts
); /* write time */
4688 put_long_date_timespec(conn
->ts_res
,pdata
+24,ctime_ts
); /* change time */
4689 SIVAL(pdata
,32,mode
);
4691 DEBUG(5,("SMB_QFBI - "));
4692 DEBUG(5,("create: %s ", ctime(&create_time
)));
4693 DEBUG(5,("access: %s ", ctime(&atime
)));
4694 DEBUG(5,("write: %s ", ctime(&mtime
)));
4695 DEBUG(5,("change: %s ", ctime(&c_time
)));
4696 DEBUG(5,("mode: %x\n", mode
));
4697 *fixed_portion
= data_size
;
4700 case SMB_FILE_STANDARD_INFORMATION
:
4701 case SMB_QUERY_FILE_STANDARD_INFO
:
4703 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4705 SOFF_T(pdata
,0,allocation_size
);
4706 SOFF_T(pdata
,8,file_size
);
4707 SIVAL(pdata
,16,nlink
);
4708 SCVAL(pdata
,20,delete_pending
?1:0);
4709 SCVAL(pdata
,21,(mode
&FILE_ATTRIBUTE_DIRECTORY
)?1:0);
4710 SSVAL(pdata
,22,0); /* Padding. */
4711 *fixed_portion
= 24;
4714 case SMB_FILE_EA_INFORMATION
:
4715 case SMB_QUERY_FILE_EA_INFO
:
4717 unsigned int ea_size
=
4718 estimate_ea_size(conn
, fsp
, smb_fname
);
4719 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4722 SIVAL(pdata
,0,ea_size
);
4726 /* Get the 8.3 name - used if NT SMB was negotiated. */
4727 case SMB_QUERY_FILE_ALT_NAME_INFO
:
4728 case SMB_FILE_ALTERNATE_NAME_INFORMATION
:
4731 char mangled_name
[13];
4732 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4733 if (!name_to_8_3(base_name
,mangled_name
,
4734 True
,conn
->params
)) {
4735 return NT_STATUS_NO_MEMORY
;
4737 len
= srvstr_push(dstart
, flags2
,
4738 pdata
+4, mangled_name
,
4739 PTR_DIFF(dend
, pdata
+4),
4741 data_size
= 4 + len
;
4747 case SMB_QUERY_FILE_NAME_INFO
:
4751 this must be *exactly* right for ACLs on mapped drives to work
4753 len
= srvstr_push(dstart
, flags2
,
4755 PTR_DIFF(dend
, pdata
+4),
4757 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4758 data_size
= 4 + len
;
4763 case SMB_FILE_ALLOCATION_INFORMATION
:
4764 case SMB_QUERY_FILE_ALLOCATION_INFO
:
4765 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4767 SOFF_T(pdata
,0,allocation_size
);
4770 case SMB_FILE_END_OF_FILE_INFORMATION
:
4771 case SMB_QUERY_FILE_END_OF_FILEINFO
:
4772 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4774 SOFF_T(pdata
,0,file_size
);
4777 case SMB_QUERY_FILE_ALL_INFO
:
4778 case SMB_FILE_ALL_INFORMATION
:
4781 unsigned int ea_size
=
4782 estimate_ea_size(conn
, fsp
, smb_fname
);
4783 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4784 put_long_date_timespec(conn
->ts_res
,pdata
,create_time_ts
);
4785 put_long_date_timespec(conn
->ts_res
,pdata
+8,atime_ts
);
4786 put_long_date_timespec(conn
->ts_res
,pdata
+16,mtime_ts
); /* write time */
4787 put_long_date_timespec(conn
->ts_res
,pdata
+24,ctime_ts
); /* change time */
4788 SIVAL(pdata
,32,mode
);
4789 SIVAL(pdata
,36,0); /* padding. */
4791 SOFF_T(pdata
,0,allocation_size
);
4792 SOFF_T(pdata
,8,file_size
);
4793 SIVAL(pdata
,16,nlink
);
4794 SCVAL(pdata
,20,delete_pending
);
4795 SCVAL(pdata
,21,(mode
&FILE_ATTRIBUTE_DIRECTORY
)?1:0);
4798 SIVAL(pdata
,0,ea_size
);
4799 pdata
+= 4; /* EA info */
4800 len
= srvstr_push(dstart
, flags2
,
4802 PTR_DIFF(dend
, pdata
+4),
4806 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4807 *fixed_portion
= 10;
4811 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
4814 unsigned int ea_size
=
4815 estimate_ea_size(conn
, fsp
, smb_fname
);
4816 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
4817 put_long_date_timespec(conn
->ts_res
,pdata
+0x00,create_time_ts
);
4818 put_long_date_timespec(conn
->ts_res
,pdata
+0x08,atime_ts
);
4819 put_long_date_timespec(conn
->ts_res
,pdata
+0x10,mtime_ts
); /* write time */
4820 put_long_date_timespec(conn
->ts_res
,pdata
+0x18,ctime_ts
); /* change time */
4821 SIVAL(pdata
, 0x20, mode
);
4822 SIVAL(pdata
, 0x24, 0); /* padding. */
4823 SBVAL(pdata
, 0x28, allocation_size
);
4824 SBVAL(pdata
, 0x30, file_size
);
4825 SIVAL(pdata
, 0x38, nlink
);
4826 SCVAL(pdata
, 0x3C, delete_pending
);
4827 SCVAL(pdata
, 0x3D, (mode
&FILE_ATTRIBUTE_DIRECTORY
)?1:0);
4828 SSVAL(pdata
, 0x3E, 0); /* padding */
4829 SBVAL(pdata
, 0x40, file_index
);
4830 SIVAL(pdata
, 0x48, ea_size
);
4831 SIVAL(pdata
, 0x4C, access_mask
);
4832 SBVAL(pdata
, 0x50, pos
);
4833 SIVAL(pdata
, 0x58, mode
); /*TODO: mode != mode fix this!!! */
4834 SIVAL(pdata
, 0x5C, 0); /* No alignment needed. */
4838 len
= srvstr_push(dstart
, flags2
,
4840 PTR_DIFF(dend
, pdata
+4),
4844 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4845 *fixed_portion
= 104;
4848 case SMB_FILE_INTERNAL_INFORMATION
:
4850 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4851 SBVAL(pdata
, 0, file_index
);
4856 case SMB_FILE_ACCESS_INFORMATION
:
4857 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4858 SIVAL(pdata
, 0, access_mask
);
4863 case SMB_FILE_NAME_INFORMATION
:
4864 /* Pathname with leading '\'. */
4867 byte_len
= dos_PutUniCode(pdata
+4,dos_fname
,(size_t)max_data_bytes
,False
);
4868 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4869 SIVAL(pdata
,0,byte_len
);
4870 data_size
= 4 + byte_len
;
4874 case SMB_FILE_DISPOSITION_INFORMATION
:
4875 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4877 SCVAL(pdata
,0,delete_pending
);
4881 case SMB_FILE_POSITION_INFORMATION
:
4882 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4884 SOFF_T(pdata
,0,pos
);
4888 case SMB_FILE_MODE_INFORMATION
:
4889 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4890 SIVAL(pdata
,0,mode
);
4895 case SMB_FILE_ALIGNMENT_INFORMATION
:
4896 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4897 SIVAL(pdata
,0,0); /* No alignment needed. */
4903 * NT4 server just returns "invalid query" to this - if we try
4904 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4907 /* The first statement above is false - verified using Thursby
4908 * client against NT4 -- gcolley.
4910 case SMB_QUERY_FILE_STREAM_INFO
:
4911 case SMB_FILE_STREAM_INFORMATION
: {
4912 unsigned int num_streams
= 0;
4913 struct stream_struct
*streams
= NULL
;
4915 DEBUG(10,("smbd_do_qfilepathinfo: "
4916 "SMB_FILE_STREAM_INFORMATION\n"));
4918 if (is_ntfs_stream_smb_fname(smb_fname
)) {
4919 return NT_STATUS_INVALID_PARAMETER
;
4922 status
= vfs_streaminfo(conn
, fsp
, smb_fname
->base_name
,
4923 talloc_tos(), &num_streams
, &streams
);
4925 if (!NT_STATUS_IS_OK(status
)) {
4926 DEBUG(10, ("could not get stream info: %s\n",
4927 nt_errstr(status
)));
4931 status
= marshall_stream_info(num_streams
, streams
,
4932 pdata
, max_data_bytes
,
4935 if (!NT_STATUS_IS_OK(status
)) {
4936 DEBUG(10, ("marshall_stream_info failed: %s\n",
4937 nt_errstr(status
)));
4938 TALLOC_FREE(streams
);
4942 TALLOC_FREE(streams
);
4944 *fixed_portion
= 32;
4948 case SMB_QUERY_COMPRESSION_INFO
:
4949 case SMB_FILE_COMPRESSION_INFORMATION
:
4950 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4951 SOFF_T(pdata
,0,file_size
);
4952 SIVAL(pdata
,8,0); /* ??? */
4953 SIVAL(pdata
,12,0); /* ??? */
4955 *fixed_portion
= 16;
4958 case SMB_FILE_NETWORK_OPEN_INFORMATION
:
4959 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4960 put_long_date_timespec(conn
->ts_res
,pdata
,create_time_ts
);
4961 put_long_date_timespec(conn
->ts_res
,pdata
+8,atime_ts
);
4962 put_long_date_timespec(conn
->ts_res
,pdata
+16,mtime_ts
); /* write time */
4963 put_long_date_timespec(conn
->ts_res
,pdata
+24,ctime_ts
); /* change time */
4964 SOFF_T(pdata
,32,allocation_size
);
4965 SOFF_T(pdata
,40,file_size
);
4966 SIVAL(pdata
,48,mode
);
4967 SIVAL(pdata
,52,0); /* ??? */
4969 *fixed_portion
= 56;
4972 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION
:
4973 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4974 SIVAL(pdata
,0,mode
);
4981 * CIFS UNIX Extensions.
4984 case SMB_QUERY_FILE_UNIX_BASIC
:
4986 pdata
= store_file_unix_basic(conn
, pdata
, fsp
, psbuf
);
4987 data_size
= PTR_DIFF(pdata
,(*ppdata
));
4989 DEBUG(4,("smbd_do_qfilepathinfo: "
4990 "SMB_QUERY_FILE_UNIX_BASIC\n"));
4991 dump_data(4, (uint8_t *)(*ppdata
), data_size
);
4995 case SMB_QUERY_FILE_UNIX_INFO2
:
4997 pdata
= store_file_unix_basic_info2(conn
, pdata
, fsp
, psbuf
);
4998 data_size
= PTR_DIFF(pdata
,(*ppdata
));
5002 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
5004 for (i
=0; i
<100; i
++)
5005 DEBUG(4,("%d=%x, ",i
, (*ppdata
)[i
]));
5011 case SMB_QUERY_FILE_UNIX_LINK
:
5014 char *buffer
= talloc_array(mem_ctx
, char, PATH_MAX
+1);
5017 return NT_STATUS_NO_MEMORY
;
5020 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
5022 if(!S_ISLNK(psbuf
->st_ex_mode
)) {
5023 return NT_STATUS_DOS(ERRSRV
, ERRbadlink
);
5026 return NT_STATUS_DOS(ERRDOS
, ERRbadlink
);
5028 len
= SMB_VFS_READLINK(conn
,
5029 smb_fname
->base_name
,
5032 return map_nt_error_from_unix(errno
);
5035 len
= srvstr_push(dstart
, flags2
,
5037 PTR_DIFF(dend
, pdata
),
5040 data_size
= PTR_DIFF(pdata
,(*ppdata
));
5045 #if defined(HAVE_POSIX_ACLS)
5046 case SMB_QUERY_POSIX_ACL
:
5048 SMB_ACL_T file_acl
= NULL
;
5049 SMB_ACL_T def_acl
= NULL
;
5050 uint16 num_file_acls
= 0;
5051 uint16 num_def_acls
= 0;
5053 if (fsp
&& fsp
->fh
->fd
!= -1) {
5054 file_acl
= SMB_VFS_SYS_ACL_GET_FD(fsp
,
5058 SMB_VFS_SYS_ACL_GET_FILE(conn
,
5059 smb_fname
->base_name
,
5060 SMB_ACL_TYPE_ACCESS
,
5064 if (file_acl
== NULL
&& no_acl_syscall_error(errno
)) {
5065 DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
5066 "not implemented on "
5067 "filesystem containing %s\n",
5068 smb_fname
->base_name
));
5069 return NT_STATUS_NOT_IMPLEMENTED
;
5072 if (S_ISDIR(psbuf
->st_ex_mode
)) {
5073 if (fsp
&& fsp
->is_directory
) {
5075 SMB_VFS_SYS_ACL_GET_FILE(
5077 fsp
->fsp_name
->base_name
,
5078 SMB_ACL_TYPE_DEFAULT
,
5082 SMB_VFS_SYS_ACL_GET_FILE(
5084 smb_fname
->base_name
,
5085 SMB_ACL_TYPE_DEFAULT
,
5088 def_acl
= free_empty_sys_acl(conn
, def_acl
);
5091 num_file_acls
= count_acl_entries(conn
, file_acl
);
5092 num_def_acls
= count_acl_entries(conn
, def_acl
);
5094 if ( data_size
< (num_file_acls
+ num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
+ SMB_POSIX_ACL_HEADER_SIZE
) {
5095 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
5097 (unsigned int)((num_file_acls
+ num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
+
5098 SMB_POSIX_ACL_HEADER_SIZE
) ));
5100 TALLOC_FREE(file_acl
);
5103 TALLOC_FREE(def_acl
);
5105 return NT_STATUS_BUFFER_TOO_SMALL
;
5108 SSVAL(pdata
,0,SMB_POSIX_ACL_VERSION
);
5109 SSVAL(pdata
,2,num_file_acls
);
5110 SSVAL(pdata
,4,num_def_acls
);
5111 if (!marshall_posix_acl(conn
, pdata
+ SMB_POSIX_ACL_HEADER_SIZE
, psbuf
, file_acl
)) {
5113 TALLOC_FREE(file_acl
);
5116 TALLOC_FREE(def_acl
);
5118 return NT_STATUS_INTERNAL_ERROR
;
5120 if (!marshall_posix_acl(conn
, pdata
+ SMB_POSIX_ACL_HEADER_SIZE
+ (num_file_acls
*SMB_POSIX_ACL_ENTRY_SIZE
), psbuf
, def_acl
)) {
5122 TALLOC_FREE(file_acl
);
5125 TALLOC_FREE(def_acl
);
5127 return NT_STATUS_INTERNAL_ERROR
;
5131 TALLOC_FREE(file_acl
);
5134 TALLOC_FREE(def_acl
);
5136 data_size
= (num_file_acls
+ num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
+ SMB_POSIX_ACL_HEADER_SIZE
;
5142 case SMB_QUERY_POSIX_LOCK
:
5147 enum brl_type lock_type
;
5149 /* We need an open file with a real fd for this. */
5150 if (!fsp
|| fsp
->fh
->fd
== -1) {
5151 return NT_STATUS_INVALID_LEVEL
;
5154 if (lock_data_count
!= POSIX_LOCK_DATA_SIZE
) {
5155 return NT_STATUS_INVALID_PARAMETER
;
5158 switch (SVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
)) {
5159 case POSIX_LOCK_TYPE_READ
:
5160 lock_type
= READ_LOCK
;
5162 case POSIX_LOCK_TYPE_WRITE
:
5163 lock_type
= WRITE_LOCK
;
5165 case POSIX_LOCK_TYPE_UNLOCK
:
5167 /* There's no point in asking for an unlock... */
5168 return NT_STATUS_INVALID_PARAMETER
;
5171 smblctx
= (uint64_t)IVAL(pdata
, POSIX_LOCK_PID_OFFSET
);
5172 offset
= BVAL(pdata
,POSIX_LOCK_START_OFFSET
);
5173 count
= BVAL(pdata
,POSIX_LOCK_LEN_OFFSET
);
5175 status
= query_lock(fsp
,
5182 if (ERROR_WAS_LOCK_DENIED(status
)) {
5183 /* Here we need to report who has it locked... */
5184 data_size
= POSIX_LOCK_DATA_SIZE
;
5186 SSVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
, lock_type
);
5187 SSVAL(pdata
, POSIX_LOCK_FLAGS_OFFSET
, 0);
5188 SIVAL(pdata
, POSIX_LOCK_PID_OFFSET
, (uint32_t)smblctx
);
5189 SBVAL(pdata
, POSIX_LOCK_START_OFFSET
, offset
);
5190 SBVAL(pdata
, POSIX_LOCK_LEN_OFFSET
, count
);
5192 } else if (NT_STATUS_IS_OK(status
)) {
5193 /* For success we just return a copy of what we sent
5194 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
5195 data_size
= POSIX_LOCK_DATA_SIZE
;
5196 memcpy(pdata
, lock_data
, POSIX_LOCK_DATA_SIZE
);
5197 SSVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
, POSIX_LOCK_TYPE_UNLOCK
);
5205 return NT_STATUS_INVALID_LEVEL
;
5208 *pdata_size
= data_size
;
5209 return NT_STATUS_OK
;
5212 /****************************************************************************
5213 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
5214 file name or file id).
5215 ****************************************************************************/
5217 static void call_trans2qfilepathinfo(connection_struct
*conn
,
5218 struct smb_request
*req
,
5219 unsigned int tran_call
,
5220 char **pparams
, int total_params
,
5221 char **ppdata
, int total_data
,
5222 unsigned int max_data_bytes
)
5224 char *params
= *pparams
;
5225 char *pdata
= *ppdata
;
5227 unsigned int data_size
= 0;
5228 unsigned int param_size
= 2;
5229 struct smb_filename
*smb_fname
= NULL
;
5230 bool delete_pending
= False
;
5231 struct timespec write_time_ts
;
5232 files_struct
*fsp
= NULL
;
5233 struct file_id fileid
;
5234 struct ea_list
*ea_list
= NULL
;
5235 int lock_data_count
= 0;
5236 char *lock_data
= NULL
;
5237 size_t fixed_portion
;
5238 NTSTATUS status
= NT_STATUS_OK
;
5241 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5245 ZERO_STRUCT(write_time_ts
);
5247 if (tran_call
== TRANSACT2_QFILEINFO
) {
5248 if (total_params
< 4) {
5249 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5254 call_trans2qpipeinfo(conn
, req
, tran_call
,
5255 pparams
, total_params
,
5261 fsp
= file_fsp(req
, SVAL(params
,0));
5262 info_level
= SVAL(params
,2);
5264 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level
));
5266 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
5267 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
5271 /* Initial check for valid fsp ptr. */
5272 if (!check_fsp_open(conn
, req
, fsp
)) {
5276 smb_fname
= cp_smb_filename(talloc_tos(), fsp
->fsp_name
);
5277 if (smb_fname
== NULL
) {
5278 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5282 if(fsp
->fake_file_handle
) {
5284 * This is actually for the QUOTA_FAKE_FILE --metze
5287 /* We know this name is ok, it's already passed the checks. */
5289 } else if(fsp
->fh
->fd
== -1) {
5291 * This is actually a QFILEINFO on a directory
5292 * handle (returned from an NT SMB). NT5.0 seems
5293 * to do this call. JRA.
5296 if (INFO_LEVEL_IS_UNIX(info_level
)) {
5297 /* Always do lstat for UNIX calls. */
5298 if (SMB_VFS_LSTAT(conn
, smb_fname
)) {
5299 DEBUG(3,("call_trans2qfilepathinfo: "
5300 "SMB_VFS_LSTAT of %s failed "
5302 smb_fname_str_dbg(smb_fname
),
5305 map_nt_error_from_unix(errno
));
5308 } else if (SMB_VFS_STAT(conn
, smb_fname
)) {
5309 DEBUG(3,("call_trans2qfilepathinfo: "
5310 "SMB_VFS_STAT of %s failed (%s)\n",
5311 smb_fname_str_dbg(smb_fname
),
5314 map_nt_error_from_unix(errno
));
5318 fileid
= vfs_file_id_from_sbuf(conn
, &smb_fname
->st
);
5319 get_file_infos(fileid
, fsp
->name_hash
, &delete_pending
, &write_time_ts
);
5322 * Original code - this is an open file.
5324 if (SMB_VFS_FSTAT(fsp
, &smb_fname
->st
) != 0) {
5325 DEBUG(3, ("fstat of %s failed (%s)\n",
5326 fsp_fnum_dbg(fsp
), strerror(errno
)));
5328 map_nt_error_from_unix(errno
));
5331 fileid
= vfs_file_id_from_sbuf(conn
, &smb_fname
->st
);
5332 get_file_infos(fileid
, fsp
->name_hash
, &delete_pending
, &write_time_ts
);
5338 uint32_t ucf_flags
= 0;
5341 if (total_params
< 7) {
5342 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5346 info_level
= SVAL(params
,0);
5348 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level
));
5350 if (INFO_LEVEL_IS_UNIX(info_level
)) {
5351 if (!lp_unix_extensions()) {
5352 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
5355 if (info_level
== SMB_QUERY_FILE_UNIX_BASIC
||
5356 info_level
== SMB_QUERY_FILE_UNIX_INFO2
||
5357 info_level
== SMB_QUERY_FILE_UNIX_LINK
) {
5358 ucf_flags
|= UCF_UNIX_NAME_LOOKUP
;
5362 srvstr_get_path(req
, params
, req
->flags2
, &fname
, ¶ms
[6],
5364 STR_TERMINATE
, &status
);
5365 if (!NT_STATUS_IS_OK(status
)) {
5366 reply_nterror(req
, status
);
5370 status
= filename_convert(req
,
5372 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
5377 if (!NT_STATUS_IS_OK(status
)) {
5378 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
5379 reply_botherror(req
,
5380 NT_STATUS_PATH_NOT_COVERED
,
5381 ERRSRV
, ERRbadpath
);
5384 reply_nterror(req
, status
);
5388 /* If this is a stream, check if there is a delete_pending. */
5389 if ((conn
->fs_capabilities
& FILE_NAMED_STREAMS
)
5390 && is_ntfs_stream_smb_fname(smb_fname
)) {
5391 struct smb_filename
*smb_fname_base
;
5393 /* Create an smb_filename with stream_name == NULL. */
5394 smb_fname_base
= synthetic_smb_fname(
5395 talloc_tos(), smb_fname
->base_name
,
5397 if (smb_fname_base
== NULL
) {
5398 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5402 if (INFO_LEVEL_IS_UNIX(info_level
)) {
5403 /* Always do lstat for UNIX calls. */
5404 if (SMB_VFS_LSTAT(conn
, smb_fname_base
) != 0) {
5405 DEBUG(3,("call_trans2qfilepathinfo: "
5406 "SMB_VFS_LSTAT of %s failed "
5408 smb_fname_str_dbg(smb_fname_base
),
5410 TALLOC_FREE(smb_fname_base
);
5412 map_nt_error_from_unix(errno
));
5416 if (SMB_VFS_STAT(conn
, smb_fname_base
) != 0) {
5417 DEBUG(3,("call_trans2qfilepathinfo: "
5418 "fileinfo of %s failed "
5420 smb_fname_str_dbg(smb_fname_base
),
5422 TALLOC_FREE(smb_fname_base
);
5424 map_nt_error_from_unix(errno
));
5429 status
= file_name_hash(conn
,
5430 smb_fname_str_dbg(smb_fname_base
),
5432 if (!NT_STATUS_IS_OK(status
)) {
5433 TALLOC_FREE(smb_fname_base
);
5434 reply_nterror(req
, status
);
5438 fileid
= vfs_file_id_from_sbuf(conn
,
5439 &smb_fname_base
->st
);
5440 TALLOC_FREE(smb_fname_base
);
5441 get_file_infos(fileid
, name_hash
, &delete_pending
, NULL
);
5442 if (delete_pending
) {
5443 reply_nterror(req
, NT_STATUS_DELETE_PENDING
);
5448 if (INFO_LEVEL_IS_UNIX(info_level
)) {
5449 /* Always do lstat for UNIX calls. */
5450 if (SMB_VFS_LSTAT(conn
, smb_fname
)) {
5451 DEBUG(3,("call_trans2qfilepathinfo: "
5452 "SMB_VFS_LSTAT of %s failed (%s)\n",
5453 smb_fname_str_dbg(smb_fname
),
5456 map_nt_error_from_unix(errno
));
5461 if (SMB_VFS_STAT(conn
, smb_fname
) != 0) {
5462 DEBUG(3,("call_trans2qfilepathinfo: "
5463 "SMB_VFS_STAT of %s failed (%s)\n",
5464 smb_fname_str_dbg(smb_fname
),
5467 map_nt_error_from_unix(errno
));
5472 status
= file_name_hash(conn
,
5473 smb_fname_str_dbg(smb_fname
),
5475 if (!NT_STATUS_IS_OK(status
)) {
5476 reply_nterror(req
, status
);
5480 fileid
= vfs_file_id_from_sbuf(conn
, &smb_fname
->st
);
5481 get_file_infos(fileid
, name_hash
, &delete_pending
, &write_time_ts
);
5482 if (delete_pending
) {
5483 reply_nterror(req
, NT_STATUS_DELETE_PENDING
);
5488 DEBUG(3,("call_trans2qfilepathinfo %s (%s) level=%d call=%d "
5489 "total_data=%d\n", smb_fname_str_dbg(smb_fname
),
5491 info_level
,tran_call
,total_data
));
5493 /* Pull out any data sent here before we realloc. */
5494 switch (info_level
) {
5495 case SMB_INFO_QUERY_EAS_FROM_LIST
:
5497 /* Pull any EA list from the data portion. */
5500 if (total_data
< 4) {
5502 req
, NT_STATUS_INVALID_PARAMETER
);
5505 ea_size
= IVAL(pdata
,0);
5507 if (total_data
> 0 && ea_size
!= total_data
) {
5508 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5509 total_data=%u (should be %u)\n", (unsigned int)total_data
, (unsigned int)IVAL(pdata
,0) ));
5511 req
, NT_STATUS_INVALID_PARAMETER
);
5515 if (!lp_ea_support(SNUM(conn
))) {
5516 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
5520 /* Pull out the list of names. */
5521 ea_list
= read_ea_name_list(req
, pdata
+ 4, ea_size
- 4);
5524 req
, NT_STATUS_INVALID_PARAMETER
);
5530 case SMB_QUERY_POSIX_LOCK
:
5532 if (fsp
== NULL
|| fsp
->fh
->fd
== -1) {
5533 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
5537 if (total_data
!= POSIX_LOCK_DATA_SIZE
) {
5539 req
, NT_STATUS_INVALID_PARAMETER
);
5543 /* Copy the lock range data. */
5544 lock_data
= (char *)talloc_memdup(
5545 req
, pdata
, total_data
);
5547 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5550 lock_data_count
= total_data
;
5556 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
5557 if (*pparams
== NULL
) {
5558 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5565 * draft-leach-cifs-v1-spec-02.txt
5566 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
5569 * The requested information is placed in the Data portion of the
5570 * transaction response. For the information levels greater than 0x100,
5571 * the transaction response has 1 parameter word which should be
5572 * ignored by the client.
5574 * However Windows only follows this rule for the IS_NAME_VALID call.
5576 switch (info_level
) {
5577 case SMB_INFO_IS_NAME_VALID
:
5582 if ((info_level
& 0xFF00) == 0xFF00) {
5584 * We use levels that start with 0xFF00
5585 * internally to represent SMB2 specific levels
5587 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
5591 status
= smbd_do_qfilepathinfo(conn
, req
, info_level
,
5593 delete_pending
, write_time_ts
,
5595 lock_data_count
, lock_data
,
5596 req
->flags2
, max_data_bytes
,
5598 ppdata
, &data_size
);
5599 if (!NT_STATUS_IS_OK(status
)) {
5600 reply_nterror(req
, status
);
5603 if (fixed_portion
> max_data_bytes
) {
5604 reply_nterror(req
, NT_STATUS_INFO_LENGTH_MISMATCH
);
5608 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, param_size
, *ppdata
, data_size
,
5614 /****************************************************************************
5615 Set a hard link (called by UNIX extensions and by NT rename with HARD link
5617 ****************************************************************************/
5619 NTSTATUS
hardlink_internals(TALLOC_CTX
*ctx
,
5620 connection_struct
*conn
,
5621 struct smb_request
*req
,
5622 bool overwrite_if_exists
,
5623 const struct smb_filename
*smb_fname_old
,
5624 struct smb_filename
*smb_fname_new
)
5626 NTSTATUS status
= NT_STATUS_OK
;
5628 /* source must already exist. */
5629 if (!VALID_STAT(smb_fname_old
->st
)) {
5630 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5633 if (VALID_STAT(smb_fname_new
->st
)) {
5634 if (overwrite_if_exists
) {
5635 if (S_ISDIR(smb_fname_new
->st
.st_ex_mode
)) {
5636 return NT_STATUS_FILE_IS_A_DIRECTORY
;
5638 status
= unlink_internals(conn
,
5640 FILE_ATTRIBUTE_NORMAL
,
5643 if (!NT_STATUS_IS_OK(status
)) {
5647 /* Disallow if newname already exists. */
5648 return NT_STATUS_OBJECT_NAME_COLLISION
;
5652 /* No links from a directory. */
5653 if (S_ISDIR(smb_fname_old
->st
.st_ex_mode
)) {
5654 return NT_STATUS_FILE_IS_A_DIRECTORY
;
5657 /* Setting a hardlink to/from a stream isn't currently supported. */
5658 if (is_ntfs_stream_smb_fname(smb_fname_old
) ||
5659 is_ntfs_stream_smb_fname(smb_fname_new
)) {
5660 return NT_STATUS_INVALID_PARAMETER
;
5663 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
5664 smb_fname_old
->base_name
, smb_fname_new
->base_name
));
5666 if (SMB_VFS_LINK(conn
, smb_fname_old
->base_name
,
5667 smb_fname_new
->base_name
) != 0) {
5668 status
= map_nt_error_from_unix(errno
);
5669 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
5670 nt_errstr(status
), smb_fname_old
->base_name
,
5671 smb_fname_new
->base_name
));
5676 /****************************************************************************
5677 Deal with setting the time from any of the setfilepathinfo functions.
5678 NOTE !!!! The check for FILE_WRITE_ATTRIBUTES access must be done *before*
5679 calling this function.
5680 ****************************************************************************/
5682 NTSTATUS
smb_set_file_time(connection_struct
*conn
,
5684 const struct smb_filename
*smb_fname
,
5685 struct smb_file_time
*ft
,
5686 bool setting_write_time
)
5688 struct smb_filename smb_fname_base
;
5690 FILE_NOTIFY_CHANGE_LAST_ACCESS
5691 |FILE_NOTIFY_CHANGE_LAST_WRITE
5692 |FILE_NOTIFY_CHANGE_CREATION
;
5694 if (!VALID_STAT(smb_fname
->st
)) {
5695 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5698 /* get some defaults (no modifications) if any info is zero or -1. */
5699 if (null_timespec(ft
->create_time
)) {
5700 action
&= ~FILE_NOTIFY_CHANGE_CREATION
;
5703 if (null_timespec(ft
->atime
)) {
5704 action
&= ~FILE_NOTIFY_CHANGE_LAST_ACCESS
;
5707 if (null_timespec(ft
->mtime
)) {
5708 action
&= ~FILE_NOTIFY_CHANGE_LAST_WRITE
;
5711 if (!setting_write_time
) {
5712 /* ft->mtime comes from change time, not write time. */
5713 action
&= ~FILE_NOTIFY_CHANGE_LAST_WRITE
;
5716 /* Ensure the resolution is the correct for
5717 * what we can store on this filesystem. */
5719 round_timespec(conn
->ts_res
, &ft
->create_time
);
5720 round_timespec(conn
->ts_res
, &ft
->ctime
);
5721 round_timespec(conn
->ts_res
, &ft
->atime
);
5722 round_timespec(conn
->ts_res
, &ft
->mtime
);
5724 DEBUG(5,("smb_set_filetime: actime: %s\n ",
5725 time_to_asc(convert_timespec_to_time_t(ft
->atime
))));
5726 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
5727 time_to_asc(convert_timespec_to_time_t(ft
->mtime
))));
5728 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
5729 time_to_asc(convert_timespec_to_time_t(ft
->ctime
))));
5730 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
5731 time_to_asc(convert_timespec_to_time_t(ft
->create_time
))));
5733 if (setting_write_time
) {
5735 * This was a Windows setfileinfo on an open file.
5736 * NT does this a lot. We also need to
5737 * set the time here, as it can be read by
5738 * FindFirst/FindNext and with the patch for bug #2045
5739 * in smbd/fileio.c it ensures that this timestamp is
5740 * kept sticky even after a write. We save the request
5741 * away and will set it on file close and after a write. JRA.
5744 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
5745 time_to_asc(convert_timespec_to_time_t(ft
->mtime
))));
5748 if (fsp
->base_fsp
) {
5749 set_sticky_write_time_fsp(fsp
->base_fsp
,
5752 set_sticky_write_time_fsp(fsp
, ft
->mtime
);
5755 set_sticky_write_time_path(
5756 vfs_file_id_from_sbuf(conn
, &smb_fname
->st
),
5761 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5763 /* Always call ntimes on the base, even if a stream was passed in. */
5764 smb_fname_base
= *smb_fname
;
5765 smb_fname_base
.stream_name
= NULL
;
5767 if(file_ntimes(conn
, &smb_fname_base
, ft
)!=0) {
5768 return map_nt_error_from_unix(errno
);
5771 notify_fname(conn
, NOTIFY_ACTION_MODIFIED
, action
,
5772 smb_fname
->base_name
);
5773 return NT_STATUS_OK
;
5776 /****************************************************************************
5777 Deal with setting the dosmode from any of the setfilepathinfo functions.
5778 NB. The check for FILE_WRITE_ATTRIBUTES access on this path must have been
5779 done before calling this function.
5780 ****************************************************************************/
5782 static NTSTATUS
smb_set_file_dosmode(connection_struct
*conn
,
5783 const struct smb_filename
*smb_fname
,
5786 struct smb_filename
*smb_fname_base
;
5789 if (!VALID_STAT(smb_fname
->st
)) {
5790 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5793 /* Always operate on the base_name, even if a stream was passed in. */
5794 smb_fname_base
= synthetic_smb_fname(
5795 talloc_tos(), smb_fname
->base_name
, NULL
, &smb_fname
->st
);
5796 if (smb_fname_base
== NULL
) {
5797 return NT_STATUS_NO_MEMORY
;
5801 if (S_ISDIR(smb_fname_base
->st
.st_ex_mode
)) {
5802 dosmode
|= FILE_ATTRIBUTE_DIRECTORY
;
5804 dosmode
&= ~FILE_ATTRIBUTE_DIRECTORY
;
5808 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode
));
5810 /* check the mode isn't different, before changing it */
5811 if ((dosmode
!= 0) && (dosmode
!= dos_mode(conn
, smb_fname_base
))) {
5812 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
5813 "0x%x\n", smb_fname_str_dbg(smb_fname_base
),
5814 (unsigned int)dosmode
));
5816 if(file_set_dosmode(conn
, smb_fname_base
, dosmode
, NULL
,
5818 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
5820 smb_fname_str_dbg(smb_fname_base
),
5822 status
= map_nt_error_from_unix(errno
);
5826 status
= NT_STATUS_OK
;
5828 TALLOC_FREE(smb_fname_base
);
5832 /****************************************************************************
5833 Deal with setting the size from any of the setfilepathinfo functions.
5834 ****************************************************************************/
5836 static NTSTATUS
smb_set_file_size(connection_struct
*conn
,
5837 struct smb_request
*req
,
5839 const struct smb_filename
*smb_fname
,
5840 const SMB_STRUCT_STAT
*psbuf
,
5842 bool fail_after_createfile
)
5844 NTSTATUS status
= NT_STATUS_OK
;
5845 struct smb_filename
*smb_fname_tmp
= NULL
;
5846 files_struct
*new_fsp
= NULL
;
5848 if (!VALID_STAT(*psbuf
)) {
5849 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
5852 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size
));
5854 if (size
== get_file_size_stat(psbuf
)) {
5855 return NT_STATUS_OK
;
5858 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5859 smb_fname_str_dbg(smb_fname
), (double)size
));
5861 if (fsp
&& fsp
->fh
->fd
!= -1) {
5862 /* Handle based call. */
5863 if (!(fsp
->access_mask
& FILE_WRITE_DATA
)) {
5864 return NT_STATUS_ACCESS_DENIED
;
5867 if (vfs_set_filelen(fsp
, size
) == -1) {
5868 return map_nt_error_from_unix(errno
);
5870 trigger_write_time_update_immediate(fsp
);
5871 return NT_STATUS_OK
;
5874 smb_fname_tmp
= cp_smb_filename(talloc_tos(), smb_fname
);
5875 if (smb_fname_tmp
== NULL
) {
5876 return NT_STATUS_NO_MEMORY
;
5879 smb_fname_tmp
->st
= *psbuf
;
5881 status
= SMB_VFS_CREATE_FILE(
5884 0, /* root_dir_fid */
5885 smb_fname_tmp
, /* fname */
5886 FILE_WRITE_DATA
, /* access_mask */
5887 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
5889 FILE_OPEN
, /* create_disposition*/
5890 0, /* create_options */
5891 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
5892 0, /* oplock_request */
5894 0, /* allocation_size */
5895 0, /* private_flags */
5898 &new_fsp
, /* result */
5901 TALLOC_FREE(smb_fname_tmp
);
5903 if (!NT_STATUS_IS_OK(status
)) {
5904 /* NB. We check for open_was_deferred in the caller. */
5908 /* See RAW-SFILEINFO-END-OF-FILE */
5909 if (fail_after_createfile
) {
5910 close_file(req
, new_fsp
,NORMAL_CLOSE
);
5911 return NT_STATUS_INVALID_LEVEL
;
5914 if (vfs_set_filelen(new_fsp
, size
) == -1) {
5915 status
= map_nt_error_from_unix(errno
);
5916 close_file(req
, new_fsp
,NORMAL_CLOSE
);
5920 trigger_write_time_update_immediate(new_fsp
);
5921 close_file(req
, new_fsp
,NORMAL_CLOSE
);
5922 return NT_STATUS_OK
;
5925 /****************************************************************************
5926 Deal with SMB_INFO_SET_EA.
5927 ****************************************************************************/
5929 static NTSTATUS
smb_info_set_ea(connection_struct
*conn
,
5933 const struct smb_filename
*smb_fname
)
5935 struct ea_list
*ea_list
= NULL
;
5936 TALLOC_CTX
*ctx
= NULL
;
5937 NTSTATUS status
= NT_STATUS_OK
;
5939 if (total_data
< 10) {
5941 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5942 length. They seem to have no effect. Bug #3212. JRA */
5944 if ((total_data
== 4) && (IVAL(pdata
,0) == 4)) {
5945 /* We're done. We only get EA info in this call. */
5946 return NT_STATUS_OK
;
5949 return NT_STATUS_INVALID_PARAMETER
;
5952 if (IVAL(pdata
,0) > total_data
) {
5953 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5954 IVAL(pdata
,0), (unsigned int)total_data
));
5955 return NT_STATUS_INVALID_PARAMETER
;
5959 ea_list
= read_ea_list(ctx
, pdata
+ 4, total_data
- 4);
5961 return NT_STATUS_INVALID_PARAMETER
;
5964 status
= set_ea(conn
, fsp
, smb_fname
, ea_list
);
5969 /****************************************************************************
5970 Deal with SMB_FILE_FULL_EA_INFORMATION set.
5971 ****************************************************************************/
5973 static NTSTATUS
smb_set_file_full_ea_info(connection_struct
*conn
,
5978 struct ea_list
*ea_list
= NULL
;
5982 return NT_STATUS_INVALID_HANDLE
;
5985 if (!lp_ea_support(SNUM(conn
))) {
5986 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
5987 "EA's not supported.\n",
5988 (unsigned int)total_data
));
5989 return NT_STATUS_EAS_NOT_SUPPORTED
;
5992 if (total_data
< 10) {
5993 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
5995 (unsigned int)total_data
));
5996 return NT_STATUS_INVALID_PARAMETER
;
5999 ea_list
= read_nttrans_ea_list(talloc_tos(),
6004 return NT_STATUS_INVALID_PARAMETER
;
6007 status
= set_ea(conn
, fsp
, fsp
->fsp_name
, ea_list
);
6009 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
6010 smb_fname_str_dbg(fsp
->fsp_name
),
6011 nt_errstr(status
) ));
6017 /****************************************************************************
6018 Deal with SMB_SET_FILE_DISPOSITION_INFO.
6019 ****************************************************************************/
6021 static NTSTATUS
smb_set_file_disposition_info(connection_struct
*conn
,
6025 struct smb_filename
*smb_fname
)
6027 NTSTATUS status
= NT_STATUS_OK
;
6028 bool delete_on_close
;
6031 if (total_data
< 1) {
6032 return NT_STATUS_INVALID_PARAMETER
;
6036 return NT_STATUS_INVALID_HANDLE
;
6039 delete_on_close
= (CVAL(pdata
,0) ? True
: False
);
6040 dosmode
= dos_mode(conn
, smb_fname
);
6042 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
6043 "delete_on_close = %u\n",
6044 smb_fname_str_dbg(smb_fname
),
6045 (unsigned int)dosmode
,
6046 (unsigned int)delete_on_close
));
6048 if (delete_on_close
) {
6049 status
= can_set_delete_on_close(fsp
, dosmode
);
6050 if (!NT_STATUS_IS_OK(status
)) {
6055 /* The set is across all open files on this dev/inode pair. */
6056 if (!set_delete_on_close(fsp
, delete_on_close
,
6057 conn
->session_info
->security_token
,
6058 conn
->session_info
->unix_token
)) {
6059 return NT_STATUS_ACCESS_DENIED
;
6061 return NT_STATUS_OK
;
6064 /****************************************************************************
6065 Deal with SMB_FILE_POSITION_INFORMATION.
6066 ****************************************************************************/
6068 static NTSTATUS
smb_file_position_information(connection_struct
*conn
,
6073 uint64_t position_information
;
6075 if (total_data
< 8) {
6076 return NT_STATUS_INVALID_PARAMETER
;
6080 /* Ignore on pathname based set. */
6081 return NT_STATUS_OK
;
6084 position_information
= (uint64_t)IVAL(pdata
,0);
6085 position_information
|= (((uint64_t)IVAL(pdata
,4)) << 32);
6087 DEBUG(10,("smb_file_position_information: Set file position "
6088 "information for file %s to %.0f\n", fsp_str_dbg(fsp
),
6089 (double)position_information
));
6090 fsp
->fh
->position_information
= position_information
;
6091 return NT_STATUS_OK
;
6094 /****************************************************************************
6095 Deal with SMB_FILE_MODE_INFORMATION.
6096 ****************************************************************************/
6098 static NTSTATUS
smb_file_mode_information(connection_struct
*conn
,
6104 if (total_data
< 4) {
6105 return NT_STATUS_INVALID_PARAMETER
;
6107 mode
= IVAL(pdata
,0);
6108 if (mode
!= 0 && mode
!= 2 && mode
!= 4 && mode
!= 6) {
6109 return NT_STATUS_INVALID_PARAMETER
;
6111 return NT_STATUS_OK
;
6114 /****************************************************************************
6115 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
6116 ****************************************************************************/
6118 static NTSTATUS
smb_set_file_unix_link(connection_struct
*conn
,
6119 struct smb_request
*req
,
6122 const struct smb_filename
*smb_fname
)
6124 char *link_target
= NULL
;
6125 const char *newname
= smb_fname
->base_name
;
6126 TALLOC_CTX
*ctx
= talloc_tos();
6128 /* Set a symbolic link. */
6129 /* Don't allow this if follow links is false. */
6131 if (total_data
== 0) {
6132 return NT_STATUS_INVALID_PARAMETER
;
6135 if (!lp_follow_symlinks(SNUM(conn
))) {
6136 return NT_STATUS_ACCESS_DENIED
;
6139 srvstr_pull_talloc(ctx
, pdata
, req
->flags2
, &link_target
, pdata
,
6140 total_data
, STR_TERMINATE
);
6143 return NT_STATUS_INVALID_PARAMETER
;
6146 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
6147 newname
, link_target
));
6149 if (SMB_VFS_SYMLINK(conn
,link_target
,newname
) != 0) {
6150 return map_nt_error_from_unix(errno
);
6153 return NT_STATUS_OK
;
6156 /****************************************************************************
6157 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
6158 ****************************************************************************/
6160 static NTSTATUS
smb_set_file_unix_hlink(connection_struct
*conn
,
6161 struct smb_request
*req
,
6162 const char *pdata
, int total_data
,
6163 struct smb_filename
*smb_fname_new
)
6165 char *oldname
= NULL
;
6166 struct smb_filename
*smb_fname_old
= NULL
;
6167 TALLOC_CTX
*ctx
= talloc_tos();
6168 NTSTATUS status
= NT_STATUS_OK
;
6170 /* Set a hard link. */
6171 if (total_data
== 0) {
6172 return NT_STATUS_INVALID_PARAMETER
;
6175 srvstr_get_path(ctx
, pdata
, req
->flags2
, &oldname
, pdata
,
6176 total_data
, STR_TERMINATE
, &status
);
6177 if (!NT_STATUS_IS_OK(status
)) {
6181 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
6182 smb_fname_str_dbg(smb_fname_new
), oldname
));
6184 status
= filename_convert(ctx
,
6186 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6191 if (!NT_STATUS_IS_OK(status
)) {
6195 return hardlink_internals(ctx
, conn
, req
, false,
6196 smb_fname_old
, smb_fname_new
);
6199 /****************************************************************************
6200 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
6201 ****************************************************************************/
6203 static NTSTATUS
smb2_file_rename_information(connection_struct
*conn
,
6204 struct smb_request
*req
,
6208 struct smb_filename
*smb_fname_src
)
6212 char *newname
= NULL
;
6213 struct smb_filename
*smb_fname_dst
= NULL
;
6214 NTSTATUS status
= NT_STATUS_OK
;
6215 TALLOC_CTX
*ctx
= talloc_tos();
6218 return NT_STATUS_INVALID_HANDLE
;
6221 if (total_data
< 20) {
6222 return NT_STATUS_INVALID_PARAMETER
;
6225 overwrite
= (CVAL(pdata
,0) ? True
: False
);
6226 len
= IVAL(pdata
,16);
6228 if (len
> (total_data
- 20) || (len
== 0)) {
6229 return NT_STATUS_INVALID_PARAMETER
;
6232 srvstr_get_path(ctx
, pdata
, req
->flags2
, &newname
,
6233 &pdata
[20], len
, STR_TERMINATE
,
6235 if (!NT_STATUS_IS_OK(status
)) {
6239 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
6242 status
= filename_convert(ctx
,
6244 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6249 if (!NT_STATUS_IS_OK(status
)) {
6253 if (fsp
->base_fsp
) {
6254 /* newname must be a stream name. */
6255 if (newname
[0] != ':') {
6256 return NT_STATUS_NOT_SUPPORTED
;
6259 /* Create an smb_fname to call rename_internals_fsp() with. */
6260 smb_fname_dst
= synthetic_smb_fname(
6261 talloc_tos(), fsp
->base_fsp
->fsp_name
->base_name
,
6263 if (smb_fname_dst
== NULL
) {
6264 status
= NT_STATUS_NO_MEMORY
;
6269 * Set the original last component, since
6270 * rename_internals_fsp() requires it.
6272 smb_fname_dst
->original_lcomp
= talloc_strdup(smb_fname_dst
,
6274 if (smb_fname_dst
->original_lcomp
== NULL
) {
6275 status
= NT_STATUS_NO_MEMORY
;
6281 DEBUG(10,("smb2_file_rename_information: "
6282 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
6283 fsp_fnum_dbg(fsp
), fsp_str_dbg(fsp
),
6284 smb_fname_str_dbg(smb_fname_dst
)));
6285 status
= rename_internals_fsp(conn
, fsp
, smb_fname_dst
,
6286 (FILE_ATTRIBUTE_HIDDEN
|FILE_ATTRIBUTE_SYSTEM
),
6290 TALLOC_FREE(smb_fname_dst
);
6294 static NTSTATUS
smb_file_link_information(connection_struct
*conn
,
6295 struct smb_request
*req
,
6299 struct smb_filename
*smb_fname_src
)
6303 char *newname
= NULL
;
6304 struct smb_filename
*smb_fname_dst
= NULL
;
6305 NTSTATUS status
= NT_STATUS_OK
;
6306 TALLOC_CTX
*ctx
= talloc_tos();
6309 return NT_STATUS_INVALID_HANDLE
;
6312 if (total_data
< 20) {
6313 return NT_STATUS_INVALID_PARAMETER
;
6316 overwrite
= (CVAL(pdata
,0) ? true : false);
6317 len
= IVAL(pdata
,16);
6319 if (len
> (total_data
- 20) || (len
== 0)) {
6320 return NT_STATUS_INVALID_PARAMETER
;
6323 srvstr_get_path(ctx
, pdata
, req
->flags2
, &newname
,
6324 &pdata
[20], len
, STR_TERMINATE
,
6326 if (!NT_STATUS_IS_OK(status
)) {
6330 DEBUG(10,("smb_file_link_information: got name |%s|\n",
6333 status
= filename_convert(ctx
,
6335 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6340 if (!NT_STATUS_IS_OK(status
)) {
6344 if (fsp
->base_fsp
) {
6345 /* No stream names. */
6346 return NT_STATUS_NOT_SUPPORTED
;
6349 DEBUG(10,("smb_file_link_information: "
6350 "SMB_FILE_LINK_INFORMATION (%s) %s -> %s\n",
6351 fsp_fnum_dbg(fsp
), fsp_str_dbg(fsp
),
6352 smb_fname_str_dbg(smb_fname_dst
)));
6353 status
= hardlink_internals(ctx
,
6360 TALLOC_FREE(smb_fname_dst
);
6364 /****************************************************************************
6365 Deal with SMB_FILE_RENAME_INFORMATION.
6366 ****************************************************************************/
6368 static NTSTATUS
smb_file_rename_information(connection_struct
*conn
,
6369 struct smb_request
*req
,
6373 struct smb_filename
*smb_fname_src
)
6378 char *newname
= NULL
;
6379 struct smb_filename
*smb_fname_dst
= NULL
;
6380 bool dest_has_wcard
= False
;
6381 NTSTATUS status
= NT_STATUS_OK
;
6383 TALLOC_CTX
*ctx
= talloc_tos();
6385 if (total_data
< 13) {
6386 return NT_STATUS_INVALID_PARAMETER
;
6389 overwrite
= (CVAL(pdata
,0) ? True
: False
);
6390 root_fid
= IVAL(pdata
,4);
6391 len
= IVAL(pdata
,8);
6393 if (len
> (total_data
- 12) || (len
== 0) || (root_fid
!= 0)) {
6394 return NT_STATUS_INVALID_PARAMETER
;
6397 srvstr_get_path_wcard(ctx
, pdata
, req
->flags2
, &newname
, &pdata
[12],
6400 if (!NT_STATUS_IS_OK(status
)) {
6404 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
6407 status
= resolve_dfspath_wcard(ctx
, conn
,
6408 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6411 !conn
->sconn
->using_smb2
,
6414 if (!NT_STATUS_IS_OK(status
)) {
6418 /* Check the new name has no '/' characters. */
6419 if (strchr_m(newname
, '/')) {
6420 return NT_STATUS_NOT_SUPPORTED
;
6423 if (fsp
&& fsp
->base_fsp
) {
6424 /* newname must be a stream name. */
6425 if (newname
[0] != ':') {
6426 return NT_STATUS_NOT_SUPPORTED
;
6429 /* Create an smb_fname to call rename_internals_fsp() with. */
6430 smb_fname_dst
= synthetic_smb_fname(
6431 talloc_tos(), fsp
->base_fsp
->fsp_name
->base_name
,
6433 if (smb_fname_dst
== NULL
) {
6434 status
= NT_STATUS_NO_MEMORY
;
6439 * Set the original last component, since
6440 * rename_internals_fsp() requires it.
6442 smb_fname_dst
->original_lcomp
= talloc_strdup(smb_fname_dst
,
6444 if (smb_fname_dst
->original_lcomp
== NULL
) {
6445 status
= NT_STATUS_NO_MEMORY
;
6451 * Build up an smb_fname_dst based on the filename passed in.
6452 * We basically just strip off the last component, and put on
6453 * the newname instead.
6455 char *base_name
= NULL
;
6457 /* newname must *not* be a stream name. */
6458 if (newname
[0] == ':') {
6459 return NT_STATUS_NOT_SUPPORTED
;
6463 * Strip off the last component (filename) of the path passed
6466 base_name
= talloc_strdup(ctx
, smb_fname_src
->base_name
);
6468 return NT_STATUS_NO_MEMORY
;
6470 p
= strrchr_m(base_name
, '/');
6474 base_name
= talloc_strdup(ctx
, "");
6476 return NT_STATUS_NO_MEMORY
;
6479 /* Append the new name. */
6480 base_name
= talloc_asprintf_append(base_name
,
6484 return NT_STATUS_NO_MEMORY
;
6487 status
= unix_convert(ctx
, conn
, base_name
, &smb_fname_dst
,
6490 UCF_ALWAYS_ALLOW_WCARD_LCOMP
:
6493 /* If an error we expect this to be
6494 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
6496 if (!NT_STATUS_IS_OK(status
)) {
6497 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND
,
6501 /* Create an smb_fname to call rename_internals_fsp() */
6502 smb_fname_dst
= synthetic_smb_fname(
6503 ctx
, base_name
, NULL
, NULL
);
6504 if (smb_fname_dst
== NULL
) {
6505 status
= NT_STATUS_NO_MEMORY
;
6512 DEBUG(10,("smb_file_rename_information: "
6513 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
6514 fsp_fnum_dbg(fsp
), fsp_str_dbg(fsp
),
6515 smb_fname_str_dbg(smb_fname_dst
)));
6516 status
= rename_internals_fsp(conn
, fsp
, smb_fname_dst
, 0,
6519 DEBUG(10,("smb_file_rename_information: "
6520 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
6521 smb_fname_str_dbg(smb_fname_src
),
6522 smb_fname_str_dbg(smb_fname_dst
)));
6523 status
= rename_internals(ctx
, conn
, req
, smb_fname_src
,
6524 smb_fname_dst
, 0, overwrite
, false,
6526 FILE_WRITE_ATTRIBUTES
);
6529 TALLOC_FREE(smb_fname_dst
);
6533 /****************************************************************************
6534 Deal with SMB_SET_POSIX_ACL.
6535 ****************************************************************************/
6537 #if defined(HAVE_POSIX_ACLS)
6538 static NTSTATUS
smb_set_posix_acl(connection_struct
*conn
,
6542 const struct smb_filename
*smb_fname
)
6544 uint16 posix_acl_version
;
6545 uint16 num_file_acls
;
6546 uint16 num_def_acls
;
6547 bool valid_file_acls
= True
;
6548 bool valid_def_acls
= True
;
6550 if (total_data
< SMB_POSIX_ACL_HEADER_SIZE
) {
6551 return NT_STATUS_INVALID_PARAMETER
;
6553 posix_acl_version
= SVAL(pdata
,0);
6554 num_file_acls
= SVAL(pdata
,2);
6555 num_def_acls
= SVAL(pdata
,4);
6557 if (num_file_acls
== SMB_POSIX_IGNORE_ACE_ENTRIES
) {
6558 valid_file_acls
= False
;
6562 if (num_def_acls
== SMB_POSIX_IGNORE_ACE_ENTRIES
) {
6563 valid_def_acls
= False
;
6567 if (posix_acl_version
!= SMB_POSIX_ACL_VERSION
) {
6568 return NT_STATUS_INVALID_PARAMETER
;
6571 if (total_data
< SMB_POSIX_ACL_HEADER_SIZE
+
6572 (num_file_acls
+num_def_acls
)*SMB_POSIX_ACL_ENTRY_SIZE
) {
6573 return NT_STATUS_INVALID_PARAMETER
;
6576 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
6577 smb_fname
? smb_fname_str_dbg(smb_fname
) : fsp_str_dbg(fsp
),
6578 (unsigned int)num_file_acls
,
6579 (unsigned int)num_def_acls
));
6581 if (valid_file_acls
&& !set_unix_posix_acl(conn
, fsp
,
6582 smb_fname
->base_name
, num_file_acls
,
6583 pdata
+ SMB_POSIX_ACL_HEADER_SIZE
)) {
6584 return map_nt_error_from_unix(errno
);
6587 if (valid_def_acls
&& !set_unix_posix_default_acl(conn
,
6588 smb_fname
->base_name
, &smb_fname
->st
, num_def_acls
,
6589 pdata
+ SMB_POSIX_ACL_HEADER_SIZE
+
6590 (num_file_acls
*SMB_POSIX_ACL_ENTRY_SIZE
))) {
6591 return map_nt_error_from_unix(errno
);
6593 return NT_STATUS_OK
;
6597 /****************************************************************************
6598 Deal with SMB_SET_POSIX_LOCK.
6599 ****************************************************************************/
6601 static NTSTATUS
smb_set_posix_lock(connection_struct
*conn
,
6602 struct smb_request
*req
,
6610 bool blocking_lock
= False
;
6611 enum brl_type lock_type
;
6613 NTSTATUS status
= NT_STATUS_OK
;
6615 if (fsp
== NULL
|| fsp
->fh
->fd
== -1) {
6616 return NT_STATUS_INVALID_HANDLE
;
6619 if (total_data
!= POSIX_LOCK_DATA_SIZE
) {
6620 return NT_STATUS_INVALID_PARAMETER
;
6623 switch (SVAL(pdata
, POSIX_LOCK_TYPE_OFFSET
)) {
6624 case POSIX_LOCK_TYPE_READ
:
6625 lock_type
= READ_LOCK
;
6627 case POSIX_LOCK_TYPE_WRITE
:
6628 /* Return the right POSIX-mappable error code for files opened read-only. */
6629 if (!fsp
->can_write
) {
6630 return NT_STATUS_INVALID_HANDLE
;
6632 lock_type
= WRITE_LOCK
;
6634 case POSIX_LOCK_TYPE_UNLOCK
:
6635 lock_type
= UNLOCK_LOCK
;
6638 return NT_STATUS_INVALID_PARAMETER
;
6641 if (SVAL(pdata
,POSIX_LOCK_FLAGS_OFFSET
) == POSIX_LOCK_FLAG_NOWAIT
) {
6642 blocking_lock
= False
;
6643 } else if (SVAL(pdata
,POSIX_LOCK_FLAGS_OFFSET
) == POSIX_LOCK_FLAG_WAIT
) {
6644 blocking_lock
= True
;
6646 return NT_STATUS_INVALID_PARAMETER
;
6649 if (!lp_blocking_locks(SNUM(conn
))) {
6650 blocking_lock
= False
;
6653 smblctx
= (uint64_t)IVAL(pdata
, POSIX_LOCK_PID_OFFSET
);
6654 offset
= (((uint64_t) IVAL(pdata
,(POSIX_LOCK_START_OFFSET
+4))) << 32) |
6655 ((uint64_t) IVAL(pdata
,POSIX_LOCK_START_OFFSET
));
6656 count
= (((uint64_t) IVAL(pdata
,(POSIX_LOCK_LEN_OFFSET
+4))) << 32) |
6657 ((uint64_t) IVAL(pdata
,POSIX_LOCK_LEN_OFFSET
));
6659 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
6660 "smblctx = %llu, count = %.0f, offset = %.0f\n",
6662 (unsigned int)lock_type
,
6663 (unsigned long long)smblctx
,
6667 if (lock_type
== UNLOCK_LOCK
) {
6668 status
= do_unlock(req
->sconn
->msg_ctx
,
6675 uint64_t block_smblctx
;
6677 struct byte_range_lock
*br_lck
= do_lock(req
->sconn
->msg_ctx
,
6688 if (br_lck
&& blocking_lock
&& ERROR_WAS_LOCK_DENIED(status
)) {
6690 * A blocking lock was requested. Package up
6691 * this smb into a queued request and push it
6692 * onto the blocking lock queue.
6694 if(push_blocking_lock_request(br_lck
,
6697 -1, /* infinite timeout. */
6705 TALLOC_FREE(br_lck
);
6709 TALLOC_FREE(br_lck
);
6715 /****************************************************************************
6716 Deal with SMB_SET_FILE_BASIC_INFO.
6717 ****************************************************************************/
6719 static NTSTATUS
smb_set_file_basic_info(connection_struct
*conn
,
6723 const struct smb_filename
*smb_fname
)
6725 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
6726 struct smb_file_time ft
;
6728 NTSTATUS status
= NT_STATUS_OK
;
6732 if (total_data
< 36) {
6733 return NT_STATUS_INVALID_PARAMETER
;
6736 status
= check_access(conn
, fsp
, smb_fname
, FILE_WRITE_ATTRIBUTES
);
6737 if (!NT_STATUS_IS_OK(status
)) {
6741 /* Set the attributes */
6742 dosmode
= IVAL(pdata
,32);
6743 status
= smb_set_file_dosmode(conn
, smb_fname
, dosmode
);
6744 if (!NT_STATUS_IS_OK(status
)) {
6749 ft
.create_time
= interpret_long_date(pdata
);
6752 ft
.atime
= interpret_long_date(pdata
+8);
6755 ft
.mtime
= interpret_long_date(pdata
+16);
6758 ft
.ctime
= interpret_long_date(pdata
+24);
6760 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
6761 smb_fname_str_dbg(smb_fname
)));
6763 return smb_set_file_time(conn
, fsp
, smb_fname
, &ft
,
6767 /****************************************************************************
6768 Deal with SMB_INFO_STANDARD.
6769 ****************************************************************************/
6771 static NTSTATUS
smb_set_info_standard(connection_struct
*conn
,
6775 const struct smb_filename
*smb_fname
)
6778 struct smb_file_time ft
;
6782 if (total_data
< 12) {
6783 return NT_STATUS_INVALID_PARAMETER
;
6787 ft
.create_time
= convert_time_t_to_timespec(srv_make_unix_date2(pdata
));
6789 ft
.atime
= convert_time_t_to_timespec(srv_make_unix_date2(pdata
+4));
6791 ft
.mtime
= convert_time_t_to_timespec(srv_make_unix_date2(pdata
+8));
6793 DEBUG(10,("smb_set_info_standard: file %s\n",
6794 smb_fname_str_dbg(smb_fname
)));
6796 status
= check_access(conn
, fsp
, smb_fname
, FILE_WRITE_ATTRIBUTES
);
6797 if (!NT_STATUS_IS_OK(status
)) {
6801 return smb_set_file_time(conn
,
6808 /****************************************************************************
6809 Deal with SMB_SET_FILE_ALLOCATION_INFO.
6810 ****************************************************************************/
6812 static NTSTATUS
smb_set_file_allocation_info(connection_struct
*conn
,
6813 struct smb_request
*req
,
6817 struct smb_filename
*smb_fname
)
6819 uint64_t allocation_size
= 0;
6820 NTSTATUS status
= NT_STATUS_OK
;
6821 files_struct
*new_fsp
= NULL
;
6823 if (!VALID_STAT(smb_fname
->st
)) {
6824 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
6827 if (total_data
< 8) {
6828 return NT_STATUS_INVALID_PARAMETER
;
6831 allocation_size
= (uint64_t)IVAL(pdata
,0);
6832 allocation_size
|= (((uint64_t)IVAL(pdata
,4)) << 32);
6833 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
6834 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname
),
6835 (double)allocation_size
));
6837 if (allocation_size
) {
6838 allocation_size
= smb_roundup(conn
, allocation_size
);
6841 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
6842 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname
),
6843 (double)allocation_size
));
6845 if (fsp
&& fsp
->fh
->fd
!= -1) {
6846 /* Open file handle. */
6847 if (!(fsp
->access_mask
& FILE_WRITE_DATA
)) {
6848 return NT_STATUS_ACCESS_DENIED
;
6851 /* Only change if needed. */
6852 if (allocation_size
!= get_file_size_stat(&smb_fname
->st
)) {
6853 if (vfs_allocate_file_space(fsp
, allocation_size
) == -1) {
6854 return map_nt_error_from_unix(errno
);
6857 /* But always update the time. */
6859 * This is equivalent to a write. Ensure it's seen immediately
6860 * if there are no pending writes.
6862 trigger_write_time_update_immediate(fsp
);
6863 return NT_STATUS_OK
;
6866 /* Pathname or stat or directory file. */
6867 status
= SMB_VFS_CREATE_FILE(
6870 0, /* root_dir_fid */
6871 smb_fname
, /* fname */
6872 FILE_WRITE_DATA
, /* access_mask */
6873 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
6875 FILE_OPEN
, /* create_disposition*/
6876 0, /* create_options */
6877 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
6878 0, /* oplock_request */
6880 0, /* allocation_size */
6881 0, /* private_flags */
6884 &new_fsp
, /* result */
6887 if (!NT_STATUS_IS_OK(status
)) {
6888 /* NB. We check for open_was_deferred in the caller. */
6892 /* Only change if needed. */
6893 if (allocation_size
!= get_file_size_stat(&smb_fname
->st
)) {
6894 if (vfs_allocate_file_space(new_fsp
, allocation_size
) == -1) {
6895 status
= map_nt_error_from_unix(errno
);
6896 close_file(req
, new_fsp
, NORMAL_CLOSE
);
6901 /* Changing the allocation size should set the last mod time. */
6903 * This is equivalent to a write. Ensure it's seen immediately
6904 * if there are no pending writes.
6906 trigger_write_time_update_immediate(new_fsp
);
6907 close_file(req
, new_fsp
, NORMAL_CLOSE
);
6908 return NT_STATUS_OK
;
6911 /****************************************************************************
6912 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
6913 ****************************************************************************/
6915 static NTSTATUS
smb_set_file_end_of_file_info(connection_struct
*conn
,
6916 struct smb_request
*req
,
6920 const struct smb_filename
*smb_fname
,
6921 bool fail_after_createfile
)
6925 if (total_data
< 8) {
6926 return NT_STATUS_INVALID_PARAMETER
;
6929 size
= IVAL(pdata
,0);
6930 size
|= (((off_t
)IVAL(pdata
,4)) << 32);
6931 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
6932 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname
),
6935 return smb_set_file_size(conn
, req
,
6940 fail_after_createfile
);
6943 /****************************************************************************
6944 Allow a UNIX info mknod.
6945 ****************************************************************************/
6947 static NTSTATUS
smb_unix_mknod(connection_struct
*conn
,
6950 const struct smb_filename
*smb_fname
)
6952 uint32 file_type
= IVAL(pdata
,56);
6953 #if defined(HAVE_MAKEDEV)
6954 uint32 dev_major
= IVAL(pdata
,60);
6955 uint32 dev_minor
= IVAL(pdata
,68);
6957 SMB_DEV_T dev
= (SMB_DEV_T
)0;
6958 uint32 raw_unixmode
= IVAL(pdata
,84);
6962 if (total_data
< 100) {
6963 return NT_STATUS_INVALID_PARAMETER
;
6966 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
6967 PERM_NEW_FILE
, &unixmode
);
6968 if (!NT_STATUS_IS_OK(status
)) {
6972 #if defined(HAVE_MAKEDEV)
6973 dev
= makedev(dev_major
, dev_minor
);
6976 switch (file_type
) {
6977 #if defined(S_IFIFO)
6978 case UNIX_TYPE_FIFO
:
6979 unixmode
|= S_IFIFO
;
6982 #if defined(S_IFSOCK)
6983 case UNIX_TYPE_SOCKET
:
6984 unixmode
|= S_IFSOCK
;
6987 #if defined(S_IFCHR)
6988 case UNIX_TYPE_CHARDEV
:
6989 unixmode
|= S_IFCHR
;
6992 #if defined(S_IFBLK)
6993 case UNIX_TYPE_BLKDEV
:
6994 unixmode
|= S_IFBLK
;
6998 return NT_STATUS_INVALID_PARAMETER
;
7001 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
7002 "%.0f mode 0%o for file %s\n", (double)dev
,
7003 (unsigned int)unixmode
, smb_fname_str_dbg(smb_fname
)));
7005 /* Ok - do the mknod. */
7006 if (SMB_VFS_MKNOD(conn
, smb_fname
->base_name
, unixmode
, dev
) != 0) {
7007 return map_nt_error_from_unix(errno
);
7010 /* If any of the other "set" calls fail we
7011 * don't want to end up with a half-constructed mknod.
7014 if (lp_inherit_permissions(SNUM(conn
))) {
7016 if (!parent_dirname(talloc_tos(), smb_fname
->base_name
,
7018 return NT_STATUS_NO_MEMORY
;
7020 inherit_access_posix_acl(conn
, parent
, smb_fname
->base_name
,
7022 TALLOC_FREE(parent
);
7025 return NT_STATUS_OK
;
7028 /****************************************************************************
7029 Deal with SMB_SET_FILE_UNIX_BASIC.
7030 ****************************************************************************/
7032 static NTSTATUS
smb_set_file_unix_basic(connection_struct
*conn
,
7033 struct smb_request
*req
,
7037 const struct smb_filename
*smb_fname
)
7039 struct smb_file_time ft
;
7040 uint32 raw_unixmode
;
7043 uid_t set_owner
= (uid_t
)SMB_UID_NO_CHANGE
;
7044 gid_t set_grp
= (uid_t
)SMB_GID_NO_CHANGE
;
7045 NTSTATUS status
= NT_STATUS_OK
;
7046 bool delete_on_fail
= False
;
7047 enum perm_type ptype
;
7048 files_struct
*all_fsps
= NULL
;
7049 bool modify_mtime
= true;
7051 struct smb_filename
*smb_fname_tmp
= NULL
;
7052 SMB_STRUCT_STAT sbuf
;
7056 if (total_data
< 100) {
7057 return NT_STATUS_INVALID_PARAMETER
;
7060 if(IVAL(pdata
, 0) != SMB_SIZE_NO_CHANGE_LO
&&
7061 IVAL(pdata
, 4) != SMB_SIZE_NO_CHANGE_HI
) {
7062 size
=IVAL(pdata
,0); /* first 8 Bytes are size */
7063 size
|= (((off_t
)IVAL(pdata
,4)) << 32);
7066 ft
.atime
= interpret_long_date(pdata
+24); /* access_time */
7067 ft
.mtime
= interpret_long_date(pdata
+32); /* modification_time */
7068 set_owner
= (uid_t
)IVAL(pdata
,40);
7069 set_grp
= (gid_t
)IVAL(pdata
,48);
7070 raw_unixmode
= IVAL(pdata
,84);
7072 if (VALID_STAT(smb_fname
->st
)) {
7073 if (S_ISDIR(smb_fname
->st
.st_ex_mode
)) {
7074 ptype
= PERM_EXISTING_DIR
;
7076 ptype
= PERM_EXISTING_FILE
;
7079 ptype
= PERM_NEW_FILE
;
7082 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
7084 if (!NT_STATUS_IS_OK(status
)) {
7088 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
7089 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
7090 smb_fname_str_dbg(smb_fname
), (double)size
,
7091 (unsigned int)set_owner
, (unsigned int)set_grp
,
7092 (int)raw_unixmode
));
7094 sbuf
= smb_fname
->st
;
7096 if (!VALID_STAT(sbuf
)) {
7098 * The only valid use of this is to create character and block
7099 * devices, and named pipes. This is deprecated (IMHO) and
7100 * a new info level should be used for mknod. JRA.
7103 status
= smb_unix_mknod(conn
,
7107 if (!NT_STATUS_IS_OK(status
)) {
7111 smb_fname_tmp
= cp_smb_filename(talloc_tos(), smb_fname
);
7112 if (smb_fname_tmp
== NULL
) {
7113 return NT_STATUS_NO_MEMORY
;
7116 if (SMB_VFS_STAT(conn
, smb_fname_tmp
) != 0) {
7117 status
= map_nt_error_from_unix(errno
);
7118 TALLOC_FREE(smb_fname_tmp
);
7119 SMB_VFS_UNLINK(conn
, smb_fname
);
7123 sbuf
= smb_fname_tmp
->st
;
7124 smb_fname
= smb_fname_tmp
;
7126 /* Ensure we don't try and change anything else. */
7127 raw_unixmode
= SMB_MODE_NO_CHANGE
;
7128 size
= get_file_size_stat(&sbuf
);
7129 ft
.atime
= sbuf
.st_ex_atime
;
7130 ft
.mtime
= sbuf
.st_ex_mtime
;
7132 * We continue here as we might want to change the
7135 delete_on_fail
= True
;
7139 /* Horrible backwards compatibility hack as an old server bug
7140 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
7144 size
= get_file_size_stat(&sbuf
);
7149 * Deal with the UNIX specific mode set.
7152 if (raw_unixmode
!= SMB_MODE_NO_CHANGE
) {
7155 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7156 "setting mode 0%o for file %s\n",
7157 (unsigned int)unixmode
,
7158 smb_fname_str_dbg(smb_fname
)));
7159 if (fsp
&& fsp
->fh
->fd
!= -1) {
7160 ret
= SMB_VFS_FCHMOD(fsp
, unixmode
);
7162 ret
= SMB_VFS_CHMOD(conn
, smb_fname
->base_name
, unixmode
);
7165 return map_nt_error_from_unix(errno
);
7170 * Deal with the UNIX specific uid set.
7173 if ((set_owner
!= (uid_t
)SMB_UID_NO_CHANGE
) &&
7174 (sbuf
.st_ex_uid
!= set_owner
)) {
7177 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7178 "changing owner %u for path %s\n",
7179 (unsigned int)set_owner
,
7180 smb_fname_str_dbg(smb_fname
)));
7182 if (fsp
&& fsp
->fh
->fd
!= -1) {
7183 ret
= SMB_VFS_FCHOWN(fsp
, set_owner
, (gid_t
)-1);
7186 * UNIX extensions calls must always operate
7189 ret
= SMB_VFS_LCHOWN(conn
, smb_fname
->base_name
,
7190 set_owner
, (gid_t
)-1);
7194 status
= map_nt_error_from_unix(errno
);
7195 if (delete_on_fail
) {
7196 SMB_VFS_UNLINK(conn
, smb_fname
);
7203 * Deal with the UNIX specific gid set.
7206 if ((set_grp
!= (uid_t
)SMB_GID_NO_CHANGE
) &&
7207 (sbuf
.st_ex_gid
!= set_grp
)) {
7210 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7211 "changing group %u for file %s\n",
7212 (unsigned int)set_owner
,
7213 smb_fname_str_dbg(smb_fname
)));
7214 if (fsp
&& fsp
->fh
->fd
!= -1) {
7215 ret
= SMB_VFS_FCHOWN(fsp
, set_owner
, (gid_t
)-1);
7218 * UNIX extensions calls must always operate
7221 ret
= SMB_VFS_LCHOWN(conn
, smb_fname
->base_name
, (uid_t
)-1,
7225 status
= map_nt_error_from_unix(errno
);
7226 if (delete_on_fail
) {
7227 SMB_VFS_UNLINK(conn
, smb_fname
);
7233 /* Deal with any size changes. */
7235 status
= smb_set_file_size(conn
, req
,
7241 if (!NT_STATUS_IS_OK(status
)) {
7245 /* Deal with any time changes. */
7246 if (null_timespec(ft
.mtime
) && null_timespec(ft
.atime
)) {
7247 /* No change, don't cancel anything. */
7251 id
= vfs_file_id_from_sbuf(conn
, &sbuf
);
7252 for(all_fsps
= file_find_di_first(conn
->sconn
, id
); all_fsps
;
7253 all_fsps
= file_find_di_next(all_fsps
)) {
7255 * We're setting the time explicitly for UNIX.
7256 * Cancel any pending changes over all handles.
7258 all_fsps
->update_write_time_on_close
= false;
7259 TALLOC_FREE(all_fsps
->update_write_time_event
);
7263 * Override the "setting_write_time"
7264 * parameter here as it almost does what
7265 * we need. Just remember if we modified
7266 * mtime and send the notify ourselves.
7268 if (null_timespec(ft
.mtime
)) {
7269 modify_mtime
= false;
7272 status
= smb_set_file_time(conn
,
7278 notify_fname(conn
, NOTIFY_ACTION_MODIFIED
,
7279 FILE_NOTIFY_CHANGE_LAST_WRITE
, smb_fname
->base_name
);
7284 /****************************************************************************
7285 Deal with SMB_SET_FILE_UNIX_INFO2.
7286 ****************************************************************************/
7288 static NTSTATUS
smb_set_file_unix_info2(connection_struct
*conn
,
7289 struct smb_request
*req
,
7293 const struct smb_filename
*smb_fname
)
7299 if (total_data
< 116) {
7300 return NT_STATUS_INVALID_PARAMETER
;
7303 /* Start by setting all the fields that are common between UNIX_BASIC
7306 status
= smb_set_file_unix_basic(conn
, req
, pdata
, total_data
,
7308 if (!NT_STATUS_IS_OK(status
)) {
7312 smb_fflags
= IVAL(pdata
, 108);
7313 smb_fmask
= IVAL(pdata
, 112);
7315 /* NB: We should only attempt to alter the file flags if the client
7316 * sends a non-zero mask.
7318 if (smb_fmask
!= 0) {
7319 int stat_fflags
= 0;
7321 if (!map_info2_flags_to_sbuf(&smb_fname
->st
, smb_fflags
,
7322 smb_fmask
, &stat_fflags
)) {
7323 /* Client asked to alter a flag we don't understand. */
7324 return NT_STATUS_INVALID_PARAMETER
;
7327 if (fsp
&& fsp
->fh
->fd
!= -1) {
7328 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
7329 return NT_STATUS_NOT_SUPPORTED
;
7331 if (SMB_VFS_CHFLAGS(conn
, smb_fname
->base_name
,
7332 stat_fflags
) != 0) {
7333 return map_nt_error_from_unix(errno
);
7338 /* XXX: need to add support for changing the create_time here. You
7339 * can do this for paths on Darwin with setattrlist(2). The right way
7340 * to hook this up is probably by extending the VFS utimes interface.
7343 return NT_STATUS_OK
;
7346 /****************************************************************************
7347 Create a directory with POSIX semantics.
7348 ****************************************************************************/
7350 static NTSTATUS
smb_posix_mkdir(connection_struct
*conn
,
7351 struct smb_request
*req
,
7354 struct smb_filename
*smb_fname
,
7355 int *pdata_return_size
)
7357 NTSTATUS status
= NT_STATUS_OK
;
7358 uint32 raw_unixmode
= 0;
7359 uint32 mod_unixmode
= 0;
7360 mode_t unixmode
= (mode_t
)0;
7361 files_struct
*fsp
= NULL
;
7362 uint16 info_level_return
= 0;
7364 char *pdata
= *ppdata
;
7366 if (total_data
< 18) {
7367 return NT_STATUS_INVALID_PARAMETER
;
7370 raw_unixmode
= IVAL(pdata
,8);
7371 /* Next 4 bytes are not yet defined. */
7373 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
7374 PERM_NEW_DIR
, &unixmode
);
7375 if (!NT_STATUS_IS_OK(status
)) {
7379 mod_unixmode
= (uint32
)unixmode
| FILE_FLAG_POSIX_SEMANTICS
;
7381 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
7382 smb_fname_str_dbg(smb_fname
), (unsigned int)unixmode
));
7384 status
= SMB_VFS_CREATE_FILE(
7387 0, /* root_dir_fid */
7388 smb_fname
, /* fname */
7389 FILE_READ_ATTRIBUTES
, /* access_mask */
7390 FILE_SHARE_NONE
, /* share_access */
7391 FILE_CREATE
, /* create_disposition*/
7392 FILE_DIRECTORY_FILE
, /* create_options */
7393 mod_unixmode
, /* file_attributes */
7394 0, /* oplock_request */
7396 0, /* allocation_size */
7397 0, /* private_flags */
7403 if (NT_STATUS_IS_OK(status
)) {
7404 close_file(req
, fsp
, NORMAL_CLOSE
);
7407 info_level_return
= SVAL(pdata
,16);
7409 if (info_level_return
== SMB_QUERY_FILE_UNIX_BASIC
) {
7410 *pdata_return_size
= 12 + SMB_FILE_UNIX_BASIC_SIZE
;
7411 } else if (info_level_return
== SMB_QUERY_FILE_UNIX_INFO2
) {
7412 *pdata_return_size
= 12 + SMB_FILE_UNIX_INFO2_SIZE
;
7414 *pdata_return_size
= 12;
7417 /* Realloc the data size */
7418 *ppdata
= (char *)SMB_REALLOC(*ppdata
,*pdata_return_size
);
7419 if (*ppdata
== NULL
) {
7420 *pdata_return_size
= 0;
7421 return NT_STATUS_NO_MEMORY
;
7425 SSVAL(pdata
,0,NO_OPLOCK_RETURN
);
7426 SSVAL(pdata
,2,0); /* No fnum. */
7427 SIVAL(pdata
,4,info
); /* Was directory created. */
7429 switch (info_level_return
) {
7430 case SMB_QUERY_FILE_UNIX_BASIC
:
7431 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_BASIC
);
7432 SSVAL(pdata
,10,0); /* Padding. */
7433 store_file_unix_basic(conn
, pdata
+ 12, fsp
,
7436 case SMB_QUERY_FILE_UNIX_INFO2
:
7437 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_INFO2
);
7438 SSVAL(pdata
,10,0); /* Padding. */
7439 store_file_unix_basic_info2(conn
, pdata
+ 12, fsp
,
7443 SSVAL(pdata
,8,SMB_NO_INFO_LEVEL_RETURNED
);
7444 SSVAL(pdata
,10,0); /* Padding. */
7451 /****************************************************************************
7452 Open/Create a file with POSIX semantics.
7453 ****************************************************************************/
7455 #define SMB_O_RDONLY_MAPPING (FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA)
7456 #define SMB_O_WRONLY_MAPPING (FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA)
7458 static NTSTATUS
smb_posix_open(connection_struct
*conn
,
7459 struct smb_request
*req
,
7462 struct smb_filename
*smb_fname
,
7463 int *pdata_return_size
)
7465 bool extended_oplock_granted
= False
;
7466 char *pdata
= *ppdata
;
7468 uint32 wire_open_mode
= 0;
7469 uint32 raw_unixmode
= 0;
7470 uint32 mod_unixmode
= 0;
7471 uint32 create_disp
= 0;
7472 uint32 access_mask
= 0;
7473 uint32 create_options
= FILE_NON_DIRECTORY_FILE
;
7474 NTSTATUS status
= NT_STATUS_OK
;
7475 mode_t unixmode
= (mode_t
)0;
7476 files_struct
*fsp
= NULL
;
7477 int oplock_request
= 0;
7479 uint16 info_level_return
= 0;
7481 if (total_data
< 18) {
7482 return NT_STATUS_INVALID_PARAMETER
;
7485 flags
= IVAL(pdata
,0);
7486 oplock_request
= (flags
& REQUEST_OPLOCK
) ? EXCLUSIVE_OPLOCK
: 0;
7487 if (oplock_request
) {
7488 oplock_request
|= (flags
& REQUEST_BATCH_OPLOCK
) ? BATCH_OPLOCK
: 0;
7491 wire_open_mode
= IVAL(pdata
,4);
7493 if (wire_open_mode
== (SMB_O_CREAT
|SMB_O_DIRECTORY
)) {
7494 return smb_posix_mkdir(conn
, req
,
7501 switch (wire_open_mode
& SMB_ACCMODE
) {
7503 access_mask
= SMB_O_RDONLY_MAPPING
;
7506 access_mask
= SMB_O_WRONLY_MAPPING
;
7509 access_mask
= (SMB_O_RDONLY_MAPPING
|
7510 SMB_O_WRONLY_MAPPING
);
7513 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
7514 (unsigned int)wire_open_mode
));
7515 return NT_STATUS_INVALID_PARAMETER
;
7518 wire_open_mode
&= ~SMB_ACCMODE
;
7520 /* First take care of O_CREAT|O_EXCL interactions. */
7521 switch (wire_open_mode
& (SMB_O_CREAT
| SMB_O_EXCL
)) {
7522 case (SMB_O_CREAT
| SMB_O_EXCL
):
7523 /* File exists fail. File not exist create. */
7524 create_disp
= FILE_CREATE
;
7527 /* File exists open. File not exist create. */
7528 create_disp
= FILE_OPEN_IF
;
7531 /* O_EXCL on its own without O_CREAT is undefined.
7532 We deliberately ignore it as some versions of
7533 Linux CIFSFS can send a bare O_EXCL on the
7534 wire which other filesystems in the kernel
7535 ignore. See bug 9519 for details. */
7540 /* File exists open. File not exist fail. */
7541 create_disp
= FILE_OPEN
;
7544 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
7545 (unsigned int)wire_open_mode
));
7546 return NT_STATUS_INVALID_PARAMETER
;
7549 /* Next factor in the effects of O_TRUNC. */
7550 wire_open_mode
&= ~(SMB_O_CREAT
| SMB_O_EXCL
);
7552 if (wire_open_mode
& SMB_O_TRUNC
) {
7553 switch (create_disp
) {
7555 /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
7556 /* Leave create_disp alone as
7557 (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
7559 /* File exists fail. File not exist create. */
7562 /* SMB_O_CREAT | SMB_O_TRUNC */
7563 /* File exists overwrite. File not exist create. */
7564 create_disp
= FILE_OVERWRITE_IF
;
7568 /* File exists overwrite. File not exist fail. */
7569 create_disp
= FILE_OVERWRITE
;
7572 /* Cannot get here. */
7573 smb_panic("smb_posix_open: logic error");
7574 return NT_STATUS_INVALID_PARAMETER
;
7578 raw_unixmode
= IVAL(pdata
,8);
7579 /* Next 4 bytes are not yet defined. */
7581 status
= unix_perms_from_wire(conn
, &smb_fname
->st
, raw_unixmode
,
7582 (VALID_STAT(smb_fname
->st
) ?
7583 PERM_EXISTING_FILE
: PERM_NEW_FILE
),
7586 if (!NT_STATUS_IS_OK(status
)) {
7590 mod_unixmode
= (uint32
)unixmode
| FILE_FLAG_POSIX_SEMANTICS
;
7592 if (wire_open_mode
& SMB_O_SYNC
) {
7593 create_options
|= FILE_WRITE_THROUGH
;
7595 if (wire_open_mode
& SMB_O_APPEND
) {
7596 access_mask
|= FILE_APPEND_DATA
;
7598 if (wire_open_mode
& SMB_O_DIRECT
) {
7599 mod_unixmode
|= FILE_FLAG_NO_BUFFERING
;
7602 if ((wire_open_mode
& SMB_O_DIRECTORY
) ||
7603 VALID_STAT_OF_DIR(smb_fname
->st
)) {
7604 if (access_mask
!= SMB_O_RDONLY_MAPPING
) {
7605 return NT_STATUS_FILE_IS_A_DIRECTORY
;
7607 create_options
&= ~FILE_NON_DIRECTORY_FILE
;
7608 create_options
|= FILE_DIRECTORY_FILE
;
7611 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
7612 smb_fname_str_dbg(smb_fname
),
7613 (unsigned int)wire_open_mode
,
7614 (unsigned int)unixmode
));
7616 status
= SMB_VFS_CREATE_FILE(
7619 0, /* root_dir_fid */
7620 smb_fname
, /* fname */
7621 access_mask
, /* access_mask */
7622 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
7624 create_disp
, /* create_disposition*/
7625 create_options
, /* create_options */
7626 mod_unixmode
, /* file_attributes */
7627 oplock_request
, /* oplock_request */
7629 0, /* allocation_size */
7630 0, /* private_flags */
7636 if (!NT_STATUS_IS_OK(status
)) {
7640 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
7641 extended_oplock_granted
= True
;
7644 if(oplock_request
&& EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
7645 extended_oplock_granted
= True
;
7648 info_level_return
= SVAL(pdata
,16);
7650 /* Allocate the correct return size. */
7652 if (info_level_return
== SMB_QUERY_FILE_UNIX_BASIC
) {
7653 *pdata_return_size
= 12 + SMB_FILE_UNIX_BASIC_SIZE
;
7654 } else if (info_level_return
== SMB_QUERY_FILE_UNIX_INFO2
) {
7655 *pdata_return_size
= 12 + SMB_FILE_UNIX_INFO2_SIZE
;
7657 *pdata_return_size
= 12;
7660 /* Realloc the data size */
7661 *ppdata
= (char *)SMB_REALLOC(*ppdata
,*pdata_return_size
);
7662 if (*ppdata
== NULL
) {
7663 close_file(req
, fsp
, ERROR_CLOSE
);
7664 *pdata_return_size
= 0;
7665 return NT_STATUS_NO_MEMORY
;
7669 if (extended_oplock_granted
) {
7670 if (flags
& REQUEST_BATCH_OPLOCK
) {
7671 SSVAL(pdata
,0, BATCH_OPLOCK_RETURN
);
7673 SSVAL(pdata
,0, EXCLUSIVE_OPLOCK_RETURN
);
7675 } else if (fsp
->oplock_type
== LEVEL_II_OPLOCK
) {
7676 SSVAL(pdata
,0, LEVEL_II_OPLOCK_RETURN
);
7678 SSVAL(pdata
,0,NO_OPLOCK_RETURN
);
7681 SSVAL(pdata
,2,fsp
->fnum
);
7682 SIVAL(pdata
,4,info
); /* Was file created etc. */
7684 switch (info_level_return
) {
7685 case SMB_QUERY_FILE_UNIX_BASIC
:
7686 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_BASIC
);
7687 SSVAL(pdata
,10,0); /* padding. */
7688 store_file_unix_basic(conn
, pdata
+ 12, fsp
,
7691 case SMB_QUERY_FILE_UNIX_INFO2
:
7692 SSVAL(pdata
,8,SMB_QUERY_FILE_UNIX_INFO2
);
7693 SSVAL(pdata
,10,0); /* padding. */
7694 store_file_unix_basic_info2(conn
, pdata
+ 12, fsp
,
7698 SSVAL(pdata
,8,SMB_NO_INFO_LEVEL_RETURNED
);
7699 SSVAL(pdata
,10,0); /* padding. */
7702 return NT_STATUS_OK
;
7705 /****************************************************************************
7706 Delete a file with POSIX semantics.
7707 ****************************************************************************/
7709 static NTSTATUS
smb_posix_unlink(connection_struct
*conn
,
7710 struct smb_request
*req
,
7713 struct smb_filename
*smb_fname
)
7715 NTSTATUS status
= NT_STATUS_OK
;
7716 files_struct
*fsp
= NULL
;
7720 int create_options
= 0;
7722 struct share_mode_lock
*lck
= NULL
;
7724 if (total_data
< 2) {
7725 return NT_STATUS_INVALID_PARAMETER
;
7728 flags
= SVAL(pdata
,0);
7730 if (!VALID_STAT(smb_fname
->st
)) {
7731 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
7734 if ((flags
== SMB_POSIX_UNLINK_DIRECTORY_TARGET
) &&
7735 !VALID_STAT_OF_DIR(smb_fname
->st
)) {
7736 return NT_STATUS_NOT_A_DIRECTORY
;
7739 DEBUG(10,("smb_posix_unlink: %s %s\n",
7740 (flags
== SMB_POSIX_UNLINK_DIRECTORY_TARGET
) ? "directory" : "file",
7741 smb_fname_str_dbg(smb_fname
)));
7743 if (VALID_STAT_OF_DIR(smb_fname
->st
)) {
7744 create_options
|= FILE_DIRECTORY_FILE
;
7747 status
= SMB_VFS_CREATE_FILE(
7750 0, /* root_dir_fid */
7751 smb_fname
, /* fname */
7752 DELETE_ACCESS
, /* access_mask */
7753 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
7755 FILE_OPEN
, /* create_disposition*/
7756 create_options
, /* create_options */
7757 FILE_FLAG_POSIX_SEMANTICS
|0777, /* file_attributes */
7758 0, /* oplock_request */
7760 0, /* allocation_size */
7761 0, /* private_flags */
7767 if (!NT_STATUS_IS_OK(status
)) {
7772 * Don't lie to client. If we can't really delete due to
7773 * non-POSIX opens return SHARING_VIOLATION.
7776 lck
= get_existing_share_mode_lock(talloc_tos(), fsp
->file_id
);
7778 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
7779 "lock for file %s\n", fsp_str_dbg(fsp
)));
7780 close_file(req
, fsp
, NORMAL_CLOSE
);
7781 return NT_STATUS_INVALID_PARAMETER
;
7785 * See if others still have the file open. If this is the case, then
7786 * don't delete. If all opens are POSIX delete we can set the delete
7787 * on close disposition.
7789 for (i
=0; i
<lck
->data
->num_share_modes
; i
++) {
7790 struct share_mode_entry
*e
= &lck
->data
->share_modes
[i
];
7791 if (is_valid_share_mode_entry(e
)) {
7792 if (e
->flags
& SHARE_MODE_FLAG_POSIX_OPEN
) {
7795 if (share_mode_stale_pid(lck
->data
, i
)) {
7798 /* Fail with sharing violation. */
7800 close_file(req
, fsp
, NORMAL_CLOSE
);
7801 return NT_STATUS_SHARING_VIOLATION
;
7806 * Set the delete on close.
7808 status
= smb_set_file_disposition_info(conn
,
7816 if (!NT_STATUS_IS_OK(status
)) {
7817 close_file(req
, fsp
, NORMAL_CLOSE
);
7820 return close_file(req
, fsp
, NORMAL_CLOSE
);
7823 NTSTATUS
smbd_do_setfilepathinfo(connection_struct
*conn
,
7824 struct smb_request
*req
,
7825 TALLOC_CTX
*mem_ctx
,
7826 uint16_t info_level
,
7828 struct smb_filename
*smb_fname
,
7829 char **ppdata
, int total_data
,
7832 char *pdata
= *ppdata
;
7833 NTSTATUS status
= NT_STATUS_OK
;
7834 int data_return_size
= 0;
7838 if (INFO_LEVEL_IS_UNIX(info_level
) && !lp_unix_extensions()) {
7839 return NT_STATUS_INVALID_LEVEL
;
7842 if (!CAN_WRITE(conn
)) {
7843 /* Allow POSIX opens. The open path will deny
7844 * any non-readonly opens. */
7845 if (info_level
!= SMB_POSIX_PATH_OPEN
) {
7846 return NT_STATUS_DOS(ERRSRV
, ERRaccess
);
7850 DEBUG(3,("smbd_do_setfilepathinfo: %s (%s) info_level=%d "
7851 "totdata=%d\n", smb_fname_str_dbg(smb_fname
),
7853 info_level
, total_data
));
7855 switch (info_level
) {
7857 case SMB_INFO_STANDARD
:
7859 status
= smb_set_info_standard(conn
,
7867 case SMB_INFO_SET_EA
:
7869 status
= smb_info_set_ea(conn
,
7877 case SMB_SET_FILE_BASIC_INFO
:
7878 case SMB_FILE_BASIC_INFORMATION
:
7880 status
= smb_set_file_basic_info(conn
,
7888 case SMB_FILE_ALLOCATION_INFORMATION
:
7889 case SMB_SET_FILE_ALLOCATION_INFO
:
7891 status
= smb_set_file_allocation_info(conn
, req
,
7899 case SMB_FILE_END_OF_FILE_INFORMATION
:
7900 case SMB_SET_FILE_END_OF_FILE_INFO
:
7903 * XP/Win7 both fail after the createfile with
7904 * SMB_SET_FILE_END_OF_FILE_INFO but not
7905 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
7906 * The level is known here, so pass it down
7910 (info_level
== SMB_SET_FILE_END_OF_FILE_INFO
);
7912 status
= smb_set_file_end_of_file_info(conn
, req
,
7921 case SMB_FILE_DISPOSITION_INFORMATION
:
7922 case SMB_SET_FILE_DISPOSITION_INFO
: /* Set delete on close for open file. */
7925 /* JRA - We used to just ignore this on a path ?
7926 * Shouldn't this be invalid level on a pathname
7929 if (tran_call
!= TRANSACT2_SETFILEINFO
) {
7930 return ERROR_NT(NT_STATUS_INVALID_LEVEL
);
7933 status
= smb_set_file_disposition_info(conn
,
7941 case SMB_FILE_POSITION_INFORMATION
:
7943 status
= smb_file_position_information(conn
,
7950 case SMB_FILE_FULL_EA_INFORMATION
:
7952 status
= smb_set_file_full_ea_info(conn
,
7959 /* From tridge Samba4 :
7960 * MODE_INFORMATION in setfileinfo (I have no
7961 * idea what "mode information" on a file is - it takes a value of 0,
7962 * 2, 4 or 6. What could it be?).
7965 case SMB_FILE_MODE_INFORMATION
:
7967 status
= smb_file_mode_information(conn
,
7974 * CIFS UNIX extensions.
7977 case SMB_SET_FILE_UNIX_BASIC
:
7979 status
= smb_set_file_unix_basic(conn
, req
,
7987 case SMB_SET_FILE_UNIX_INFO2
:
7989 status
= smb_set_file_unix_info2(conn
, req
,
7997 case SMB_SET_FILE_UNIX_LINK
:
8000 /* We must have a pathname for this. */
8001 return NT_STATUS_INVALID_LEVEL
;
8003 status
= smb_set_file_unix_link(conn
, req
, pdata
,
8004 total_data
, smb_fname
);
8008 case SMB_SET_FILE_UNIX_HLINK
:
8011 /* We must have a pathname for this. */
8012 return NT_STATUS_INVALID_LEVEL
;
8014 status
= smb_set_file_unix_hlink(conn
, req
,
8020 case SMB_FILE_RENAME_INFORMATION
:
8022 status
= smb_file_rename_information(conn
, req
,
8028 case SMB2_FILE_RENAME_INFORMATION_INTERNAL
:
8030 /* SMB2 rename information. */
8031 status
= smb2_file_rename_information(conn
, req
,
8037 case SMB_FILE_LINK_INFORMATION
:
8039 status
= smb_file_link_information(conn
, req
,
8045 #if defined(HAVE_POSIX_ACLS)
8046 case SMB_SET_POSIX_ACL
:
8048 status
= smb_set_posix_acl(conn
,
8057 case SMB_SET_POSIX_LOCK
:
8060 return NT_STATUS_INVALID_LEVEL
;
8062 status
= smb_set_posix_lock(conn
, req
,
8063 pdata
, total_data
, fsp
);
8067 case SMB_POSIX_PATH_OPEN
:
8070 /* We must have a pathname for this. */
8071 return NT_STATUS_INVALID_LEVEL
;
8074 status
= smb_posix_open(conn
, req
,
8082 case SMB_POSIX_PATH_UNLINK
:
8085 /* We must have a pathname for this. */
8086 return NT_STATUS_INVALID_LEVEL
;
8089 status
= smb_posix_unlink(conn
, req
,
8097 return NT_STATUS_INVALID_LEVEL
;
8100 if (!NT_STATUS_IS_OK(status
)) {
8104 *ret_data_size
= data_return_size
;
8105 return NT_STATUS_OK
;
8108 /****************************************************************************
8109 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
8110 ****************************************************************************/
8112 static void call_trans2setfilepathinfo(connection_struct
*conn
,
8113 struct smb_request
*req
,
8114 unsigned int tran_call
,
8115 char **pparams
, int total_params
,
8116 char **ppdata
, int total_data
,
8117 unsigned int max_data_bytes
)
8119 char *params
= *pparams
;
8120 char *pdata
= *ppdata
;
8122 struct smb_filename
*smb_fname
= NULL
;
8123 files_struct
*fsp
= NULL
;
8124 NTSTATUS status
= NT_STATUS_OK
;
8125 int data_return_size
= 0;
8128 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8132 if (tran_call
== TRANSACT2_SETFILEINFO
) {
8133 if (total_params
< 4) {
8134 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8138 fsp
= file_fsp(req
, SVAL(params
,0));
8139 /* Basic check for non-null fsp. */
8140 if (!check_fsp_open(conn
, req
, fsp
)) {
8143 info_level
= SVAL(params
,2);
8145 smb_fname
= cp_smb_filename(talloc_tos(), fsp
->fsp_name
);
8146 if (smb_fname
== NULL
) {
8147 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8151 if(fsp
->fh
->fd
== -1) {
8153 * This is actually a SETFILEINFO on a directory
8154 * handle (returned from an NT SMB). NT5.0 seems
8155 * to do this call. JRA.
8157 if (INFO_LEVEL_IS_UNIX(info_level
)) {
8158 /* Always do lstat for UNIX calls. */
8159 if (SMB_VFS_LSTAT(conn
, smb_fname
)) {
8160 DEBUG(3,("call_trans2setfilepathinfo: "
8161 "SMB_VFS_LSTAT of %s failed "
8163 smb_fname_str_dbg(smb_fname
),
8165 reply_nterror(req
, map_nt_error_from_unix(errno
));
8169 if (SMB_VFS_STAT(conn
, smb_fname
) != 0) {
8170 DEBUG(3,("call_trans2setfilepathinfo: "
8171 "fileinfo of %s failed (%s)\n",
8172 smb_fname_str_dbg(smb_fname
),
8174 reply_nterror(req
, map_nt_error_from_unix(errno
));
8178 } else if (fsp
->print_file
) {
8180 * Doing a DELETE_ON_CLOSE should cancel a print job.
8182 if ((info_level
== SMB_SET_FILE_DISPOSITION_INFO
) && CVAL(pdata
,0)) {
8183 fsp
->fh
->private_options
|= NTCREATEX_OPTIONS_PRIVATE_DELETE_ON_CLOSE
;
8185 DEBUG(3,("call_trans2setfilepathinfo: "
8186 "Cancelling print job (%s)\n",
8190 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 2,
8196 NT_STATUS_OBJECT_PATH_NOT_FOUND
);
8201 * Original code - this is an open file.
8203 if (SMB_VFS_FSTAT(fsp
, &smb_fname
->st
) != 0) {
8204 DEBUG(3,("call_trans2setfilepathinfo: fstat "
8205 "of %s failed (%s)\n", fsp_fnum_dbg(fsp
),
8207 reply_nterror(req
, map_nt_error_from_unix(errno
));
8213 uint32_t ucf_flags
= 0;
8216 if (total_params
< 7) {
8217 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8221 info_level
= SVAL(params
,0);
8222 srvstr_get_path(req
, params
, req
->flags2
, &fname
, ¶ms
[6],
8223 total_params
- 6, STR_TERMINATE
,
8225 if (!NT_STATUS_IS_OK(status
)) {
8226 reply_nterror(req
, status
);
8230 if (info_level
== SMB_SET_FILE_UNIX_BASIC
||
8231 info_level
== SMB_SET_FILE_UNIX_INFO2
||
8232 info_level
== SMB_FILE_RENAME_INFORMATION
||
8233 info_level
== SMB_POSIX_PATH_UNLINK
) {
8234 ucf_flags
|= UCF_UNIX_NAME_LOOKUP
;
8237 status
= filename_convert(req
, conn
,
8238 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
8243 if (!NT_STATUS_IS_OK(status
)) {
8244 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
8245 reply_botherror(req
,
8246 NT_STATUS_PATH_NOT_COVERED
,
8247 ERRSRV
, ERRbadpath
);
8250 reply_nterror(req
, status
);
8254 if (INFO_LEVEL_IS_UNIX(info_level
)) {
8256 * For CIFS UNIX extensions the target name may not exist.
8259 /* Always do lstat for UNIX calls. */
8260 SMB_VFS_LSTAT(conn
, smb_fname
);
8262 } else if (!VALID_STAT(smb_fname
->st
) &&
8263 SMB_VFS_STAT(conn
, smb_fname
)) {
8264 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
8266 smb_fname_str_dbg(smb_fname
),
8268 reply_nterror(req
, map_nt_error_from_unix(errno
));
8273 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (%s) info_level=%d "
8274 "totdata=%d\n", tran_call
, smb_fname_str_dbg(smb_fname
),
8276 info_level
,total_data
));
8278 /* Realloc the parameter size */
8279 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
8280 if (*pparams
== NULL
) {
8281 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8288 status
= smbd_do_setfilepathinfo(conn
, req
, req
,
8294 if (!NT_STATUS_IS_OK(status
)) {
8295 if (open_was_deferred(req
->sconn
, req
->mid
)) {
8296 /* We have re-scheduled this call. */
8299 if (blocking_lock_was_deferred_smb1(req
->sconn
, req
->mid
)) {
8300 /* We have re-scheduled this call. */
8303 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
8304 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
8305 ERRSRV
, ERRbadpath
);
8308 if (info_level
== SMB_POSIX_PATH_OPEN
) {
8309 reply_openerror(req
, status
);
8314 * Invalid EA name needs to return 2 param bytes,
8315 * not a zero-length error packet.
8317 if (NT_STATUS_EQUAL(status
, STATUS_INVALID_EA_NAME
)) {
8318 send_trans2_replies(conn
, req
, status
, params
, 2, NULL
, 0,
8321 reply_nterror(req
, status
);
8326 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 2, *ppdata
, data_return_size
,
8332 /****************************************************************************
8333 Reply to a TRANS2_MKDIR (make directory with extended attributes).
8334 ****************************************************************************/
8336 static void call_trans2mkdir(connection_struct
*conn
, struct smb_request
*req
,
8337 char **pparams
, int total_params
,
8338 char **ppdata
, int total_data
,
8339 unsigned int max_data_bytes
)
8341 struct smb_filename
*smb_dname
= NULL
;
8342 char *params
= *pparams
;
8343 char *pdata
= *ppdata
;
8344 char *directory
= NULL
;
8345 NTSTATUS status
= NT_STATUS_OK
;
8346 struct ea_list
*ea_list
= NULL
;
8347 TALLOC_CTX
*ctx
= talloc_tos();
8349 if (!CAN_WRITE(conn
)) {
8350 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
8354 if (total_params
< 5) {
8355 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8359 srvstr_get_path(ctx
, params
, req
->flags2
, &directory
, ¶ms
[4],
8360 total_params
- 4, STR_TERMINATE
,
8362 if (!NT_STATUS_IS_OK(status
)) {
8363 reply_nterror(req
, status
);
8367 DEBUG(3,("call_trans2mkdir : name = %s\n", directory
));
8369 status
= filename_convert(ctx
,
8371 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
8377 if (!NT_STATUS_IS_OK(status
)) {
8378 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
8379 reply_botherror(req
,
8380 NT_STATUS_PATH_NOT_COVERED
,
8381 ERRSRV
, ERRbadpath
);
8384 reply_nterror(req
, status
);
8389 * OS/2 workplace shell seems to send SET_EA requests of "null"
8390 * length (4 bytes containing IVAL 4).
8391 * They seem to have no effect. Bug #3212. JRA.
8394 if (total_data
&& (total_data
!= 4)) {
8395 /* Any data in this call is an EA list. */
8396 if (total_data
< 10) {
8397 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8401 if (IVAL(pdata
,0) > total_data
) {
8402 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
8403 IVAL(pdata
,0), (unsigned int)total_data
));
8404 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8408 ea_list
= read_ea_list(talloc_tos(), pdata
+ 4,
8411 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8415 if (!lp_ea_support(SNUM(conn
))) {
8416 reply_nterror(req
, NT_STATUS_EAS_NOT_SUPPORTED
);
8420 /* If total_data == 4 Windows doesn't care what values
8421 * are placed in that field, it just ignores them.
8422 * The System i QNTC IBM SMB client puts bad values here,
8423 * so ignore them. */
8425 status
= create_directory(conn
, req
, smb_dname
);
8427 if (!NT_STATUS_IS_OK(status
)) {
8428 reply_nterror(req
, status
);
8432 /* Try and set any given EA. */
8434 status
= set_ea(conn
, NULL
, smb_dname
, ea_list
);
8435 if (!NT_STATUS_IS_OK(status
)) {
8436 reply_nterror(req
, status
);
8441 /* Realloc the parameter and data sizes */
8442 *pparams
= (char *)SMB_REALLOC(*pparams
,2);
8443 if(*pparams
== NULL
) {
8444 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8451 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 2, *ppdata
, 0, max_data_bytes
);
8454 TALLOC_FREE(smb_dname
);
8458 /****************************************************************************
8459 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
8460 We don't actually do this - we just send a null response.
8461 ****************************************************************************/
8463 static void call_trans2findnotifyfirst(connection_struct
*conn
,
8464 struct smb_request
*req
,
8465 char **pparams
, int total_params
,
8466 char **ppdata
, int total_data
,
8467 unsigned int max_data_bytes
)
8469 char *params
= *pparams
;
8472 if (total_params
< 6) {
8473 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8477 info_level
= SVAL(params
,4);
8478 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level
));
8480 switch (info_level
) {
8485 reply_nterror(req
, NT_STATUS_INVALID_LEVEL
);
8489 /* Realloc the parameter and data sizes */
8490 *pparams
= (char *)SMB_REALLOC(*pparams
,6);
8491 if (*pparams
== NULL
) {
8492 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8497 SSVAL(params
,0,fnf_handle
);
8498 SSVAL(params
,2,0); /* No changes */
8499 SSVAL(params
,4,0); /* No EA errors */
8506 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 6, *ppdata
, 0, max_data_bytes
);
8511 /****************************************************************************
8512 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
8513 changes). Currently this does nothing.
8514 ****************************************************************************/
8516 static void call_trans2findnotifynext(connection_struct
*conn
,
8517 struct smb_request
*req
,
8518 char **pparams
, int total_params
,
8519 char **ppdata
, int total_data
,
8520 unsigned int max_data_bytes
)
8522 char *params
= *pparams
;
8524 DEBUG(3,("call_trans2findnotifynext\n"));
8526 /* Realloc the parameter and data sizes */
8527 *pparams
= (char *)SMB_REALLOC(*pparams
,4);
8528 if (*pparams
== NULL
) {
8529 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8534 SSVAL(params
,0,0); /* No changes */
8535 SSVAL(params
,2,0); /* No EA errors */
8537 send_trans2_replies(conn
, req
, NT_STATUS_OK
, params
, 4, *ppdata
, 0, max_data_bytes
);
8542 /****************************************************************************
8543 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
8544 ****************************************************************************/
8546 static void call_trans2getdfsreferral(connection_struct
*conn
,
8547 struct smb_request
*req
,
8548 char **pparams
, int total_params
,
8549 char **ppdata
, int total_data
,
8550 unsigned int max_data_bytes
)
8552 char *params
= *pparams
;
8553 char *pathname
= NULL
;
8555 int max_referral_level
;
8556 NTSTATUS status
= NT_STATUS_OK
;
8557 TALLOC_CTX
*ctx
= talloc_tos();
8559 DEBUG(10,("call_trans2getdfsreferral\n"));
8561 if (total_params
< 3) {
8562 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8566 max_referral_level
= SVAL(params
,0);
8568 if(!lp_host_msdfs()) {
8569 reply_nterror(req
, NT_STATUS_NOT_IMPLEMENTED
);
8573 srvstr_pull_talloc(ctx
, params
, req
->flags2
, &pathname
, ¶ms
[2],
8574 total_params
- 2, STR_TERMINATE
);
8576 reply_nterror(req
, NT_STATUS_NOT_FOUND
);
8579 if((reply_size
= setup_dfs_referral(conn
, pathname
, max_referral_level
,
8580 ppdata
,&status
)) < 0) {
8581 reply_nterror(req
, status
);
8585 SSVAL((discard_const_p(uint8_t, req
->inbuf
)), smb_flg2
,
8586 SVAL(req
->inbuf
,smb_flg2
) | FLAGS2_DFS_PATHNAMES
);
8587 send_trans2_replies(conn
, req
, NT_STATUS_OK
, 0,0,*ppdata
,reply_size
, max_data_bytes
);
8592 #define LMCAT_SPL 0x53
8593 #define LMFUNC_GETJOBID 0x60
8595 /****************************************************************************
8596 Reply to a TRANS2_IOCTL - used for OS/2 printing.
8597 ****************************************************************************/
8599 static void call_trans2ioctl(connection_struct
*conn
,
8600 struct smb_request
*req
,
8601 char **pparams
, int total_params
,
8602 char **ppdata
, int total_data
,
8603 unsigned int max_data_bytes
)
8605 char *pdata
= *ppdata
;
8606 files_struct
*fsp
= file_fsp(req
, SVAL(req
->vwv
+15, 0));
8608 /* check for an invalid fid before proceeding */
8611 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
8615 if ((SVAL(req
->vwv
+16, 0) == LMCAT_SPL
)
8616 && (SVAL(req
->vwv
+17, 0) == LMFUNC_GETJOBID
)) {
8617 *ppdata
= (char *)SMB_REALLOC(*ppdata
, 32);
8618 if (*ppdata
== NULL
) {
8619 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8624 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
8625 CAN ACCEPT THIS IN UNICODE. JRA. */
8628 SSVAL(pdata
, 0, print_spool_rap_jobid(fsp
->print_file
));
8630 srvstr_push(pdata
, req
->flags2
, pdata
+ 2,
8631 lp_netbios_name(), 15,
8632 STR_ASCII
|STR_TERMINATE
); /* Our NetBIOS name */
8633 srvstr_push(pdata
, req
->flags2
, pdata
+18,
8634 lp_servicename(talloc_tos(), SNUM(conn
)), 13,
8635 STR_ASCII
|STR_TERMINATE
); /* Service name */
8636 send_trans2_replies(conn
, req
, NT_STATUS_OK
, *pparams
, 0, *ppdata
, 32,
8641 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
8642 reply_nterror(req
, NT_STATUS_NOT_IMPLEMENTED
);
8645 /****************************************************************************
8646 Reply to a SMBfindclose (stop trans2 directory search).
8647 ****************************************************************************/
8649 void reply_findclose(struct smb_request
*req
)
8652 struct smbd_server_connection
*sconn
= req
->sconn
;
8654 START_PROFILE(SMBfindclose
);
8657 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8658 END_PROFILE(SMBfindclose
);
8662 dptr_num
= SVALS(req
->vwv
+0, 0);
8664 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num
));
8666 dptr_close(sconn
, &dptr_num
);
8668 reply_outbuf(req
, 0, 0);
8670 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num
));
8672 END_PROFILE(SMBfindclose
);
8676 /****************************************************************************
8677 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
8678 ****************************************************************************/
8680 void reply_findnclose(struct smb_request
*req
)
8684 START_PROFILE(SMBfindnclose
);
8687 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8688 END_PROFILE(SMBfindnclose
);
8692 dptr_num
= SVAL(req
->vwv
+0, 0);
8694 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num
));
8696 /* We never give out valid handles for a
8697 findnotifyfirst - so any dptr_num is ok here.
8700 reply_outbuf(req
, 0, 0);
8702 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num
));
8704 END_PROFILE(SMBfindnclose
);
8708 static void handle_trans2(connection_struct
*conn
, struct smb_request
*req
,
8709 struct trans_state
*state
)
8711 if (get_Protocol() >= PROTOCOL_NT1
) {
8712 req
->flags2
|= 0x40; /* IS_LONG_NAME */
8713 SSVAL((discard_const_p(uint8_t, req
->inbuf
)),smb_flg2
,req
->flags2
);
8716 if (ENCRYPTION_REQUIRED(conn
) && !req
->encrypted
) {
8717 if (state
->call
!= TRANSACT2_QFSINFO
&&
8718 state
->call
!= TRANSACT2_SETFSINFO
) {
8719 DEBUG(0,("handle_trans2: encryption required "
8721 (unsigned int)state
->call
));
8722 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
8727 SMB_PERFCOUNT_SET_SUBOP(&req
->pcd
, state
->call
);
8729 /* Now we must call the relevant TRANS2 function */
8730 switch(state
->call
) {
8731 case TRANSACT2_OPEN
:
8733 START_PROFILE(Trans2_open
);
8734 call_trans2open(conn
, req
,
8735 &state
->param
, state
->total_param
,
8736 &state
->data
, state
->total_data
,
8737 state
->max_data_return
);
8738 END_PROFILE(Trans2_open
);
8742 case TRANSACT2_FINDFIRST
:
8744 START_PROFILE(Trans2_findfirst
);
8745 call_trans2findfirst(conn
, req
,
8746 &state
->param
, state
->total_param
,
8747 &state
->data
, state
->total_data
,
8748 state
->max_data_return
);
8749 END_PROFILE(Trans2_findfirst
);
8753 case TRANSACT2_FINDNEXT
:
8755 START_PROFILE(Trans2_findnext
);
8756 call_trans2findnext(conn
, req
,
8757 &state
->param
, state
->total_param
,
8758 &state
->data
, state
->total_data
,
8759 state
->max_data_return
);
8760 END_PROFILE(Trans2_findnext
);
8764 case TRANSACT2_QFSINFO
:
8766 START_PROFILE(Trans2_qfsinfo
);
8767 call_trans2qfsinfo(conn
, req
,
8768 &state
->param
, state
->total_param
,
8769 &state
->data
, state
->total_data
,
8770 state
->max_data_return
);
8771 END_PROFILE(Trans2_qfsinfo
);
8775 case TRANSACT2_SETFSINFO
:
8777 START_PROFILE(Trans2_setfsinfo
);
8778 call_trans2setfsinfo(conn
, req
,
8779 &state
->param
, state
->total_param
,
8780 &state
->data
, state
->total_data
,
8781 state
->max_data_return
);
8782 END_PROFILE(Trans2_setfsinfo
);
8786 case TRANSACT2_QPATHINFO
:
8787 case TRANSACT2_QFILEINFO
:
8789 START_PROFILE(Trans2_qpathinfo
);
8790 call_trans2qfilepathinfo(conn
, req
, state
->call
,
8791 &state
->param
, state
->total_param
,
8792 &state
->data
, state
->total_data
,
8793 state
->max_data_return
);
8794 END_PROFILE(Trans2_qpathinfo
);
8798 case TRANSACT2_SETPATHINFO
:
8799 case TRANSACT2_SETFILEINFO
:
8801 START_PROFILE(Trans2_setpathinfo
);
8802 call_trans2setfilepathinfo(conn
, req
, state
->call
,
8803 &state
->param
, state
->total_param
,
8804 &state
->data
, state
->total_data
,
8805 state
->max_data_return
);
8806 END_PROFILE(Trans2_setpathinfo
);
8810 case TRANSACT2_FINDNOTIFYFIRST
:
8812 START_PROFILE(Trans2_findnotifyfirst
);
8813 call_trans2findnotifyfirst(conn
, req
,
8814 &state
->param
, state
->total_param
,
8815 &state
->data
, state
->total_data
,
8816 state
->max_data_return
);
8817 END_PROFILE(Trans2_findnotifyfirst
);
8821 case TRANSACT2_FINDNOTIFYNEXT
:
8823 START_PROFILE(Trans2_findnotifynext
);
8824 call_trans2findnotifynext(conn
, req
,
8825 &state
->param
, state
->total_param
,
8826 &state
->data
, state
->total_data
,
8827 state
->max_data_return
);
8828 END_PROFILE(Trans2_findnotifynext
);
8832 case TRANSACT2_MKDIR
:
8834 START_PROFILE(Trans2_mkdir
);
8835 call_trans2mkdir(conn
, req
,
8836 &state
->param
, state
->total_param
,
8837 &state
->data
, state
->total_data
,
8838 state
->max_data_return
);
8839 END_PROFILE(Trans2_mkdir
);
8843 case TRANSACT2_GET_DFS_REFERRAL
:
8845 START_PROFILE(Trans2_get_dfs_referral
);
8846 call_trans2getdfsreferral(conn
, req
,
8847 &state
->param
, state
->total_param
,
8848 &state
->data
, state
->total_data
,
8849 state
->max_data_return
);
8850 END_PROFILE(Trans2_get_dfs_referral
);
8854 case TRANSACT2_IOCTL
:
8856 START_PROFILE(Trans2_ioctl
);
8857 call_trans2ioctl(conn
, req
,
8858 &state
->param
, state
->total_param
,
8859 &state
->data
, state
->total_data
,
8860 state
->max_data_return
);
8861 END_PROFILE(Trans2_ioctl
);
8866 /* Error in request */
8867 DEBUG(2,("Unknown request %d in trans2 call\n", state
->call
));
8868 reply_nterror(req
, NT_STATUS_NOT_IMPLEMENTED
);
8872 /****************************************************************************
8873 Reply to a SMBtrans2.
8874 ****************************************************************************/
8876 void reply_trans2(struct smb_request
*req
)
8878 connection_struct
*conn
= req
->conn
;
8883 unsigned int tran_call
;
8884 struct trans_state
*state
;
8887 START_PROFILE(SMBtrans2
);
8889 if (req
->wct
< 14) {
8890 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8891 END_PROFILE(SMBtrans2
);
8895 dsoff
= SVAL(req
->vwv
+12, 0);
8896 dscnt
= SVAL(req
->vwv
+11, 0);
8897 psoff
= SVAL(req
->vwv
+10, 0);
8898 pscnt
= SVAL(req
->vwv
+9, 0);
8899 tran_call
= SVAL(req
->vwv
+14, 0);
8901 result
= allow_new_trans(conn
->pending_trans
, req
->mid
);
8902 if (!NT_STATUS_IS_OK(result
)) {
8903 DEBUG(2, ("Got invalid trans2 request: %s\n",
8904 nt_errstr(result
)));
8905 reply_nterror(req
, result
);
8906 END_PROFILE(SMBtrans2
);
8911 switch (tran_call
) {
8912 /* List the allowed trans2 calls on IPC$ */
8913 case TRANSACT2_OPEN
:
8914 case TRANSACT2_GET_DFS_REFERRAL
:
8915 case TRANSACT2_QFILEINFO
:
8916 case TRANSACT2_QFSINFO
:
8917 case TRANSACT2_SETFSINFO
:
8920 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
8921 END_PROFILE(SMBtrans2
);
8926 if ((state
= talloc(conn
, struct trans_state
)) == NULL
) {
8927 DEBUG(0, ("talloc failed\n"));
8928 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8929 END_PROFILE(SMBtrans2
);
8933 state
->cmd
= SMBtrans2
;
8935 state
->mid
= req
->mid
;
8936 state
->vuid
= req
->vuid
;
8937 state
->setup_count
= SVAL(req
->vwv
+13, 0);
8938 state
->setup
= NULL
;
8939 state
->total_param
= SVAL(req
->vwv
+0, 0);
8940 state
->param
= NULL
;
8941 state
->total_data
= SVAL(req
->vwv
+1, 0);
8943 state
->max_param_return
= SVAL(req
->vwv
+2, 0);
8944 state
->max_data_return
= SVAL(req
->vwv
+3, 0);
8945 state
->max_setup_return
= SVAL(req
->vwv
+4, 0);
8946 state
->close_on_completion
= BITSETW(req
->vwv
+5, 0);
8947 state
->one_way
= BITSETW(req
->vwv
+5, 1);
8949 state
->call
= tran_call
;
8951 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
8952 is so as a sanity check */
8953 if (state
->setup_count
!= 1) {
8955 * Need to have rc=0 for ioctl to get job id for OS/2.
8956 * Network printing will fail if function is not successful.
8957 * Similar function in reply.c will be used if protocol
8958 * is LANMAN1.0 instead of LM1.2X002.
8959 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
8960 * outbuf doesn't have to be set(only job id is used).
8962 if ( (state
->setup_count
== 4)
8963 && (tran_call
== TRANSACT2_IOCTL
)
8964 && (SVAL(req
->vwv
+16, 0) == LMCAT_SPL
)
8965 && (SVAL(req
->vwv
+17, 0) == LMFUNC_GETJOBID
)) {
8966 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
8968 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state
->setup_count
));
8969 DEBUG(2,("Transaction is %d\n",tran_call
));
8971 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
8972 END_PROFILE(SMBtrans2
);
8977 if ((dscnt
> state
->total_data
) || (pscnt
> state
->total_param
))
8980 if (state
->total_data
) {
8982 if (trans_oob(state
->total_data
, 0, dscnt
)
8983 || trans_oob(smb_len(req
->inbuf
), dsoff
, dscnt
)) {
8987 /* Can't use talloc here, the core routines do realloc on the
8988 * params and data. */
8989 state
->data
= (char *)SMB_MALLOC(state
->total_data
);
8990 if (state
->data
== NULL
) {
8991 DEBUG(0,("reply_trans2: data malloc fail for %u "
8992 "bytes !\n", (unsigned int)state
->total_data
));
8994 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
8995 END_PROFILE(SMBtrans2
);
8999 memcpy(state
->data
,smb_base(req
->inbuf
)+dsoff
,dscnt
);
9002 if (state
->total_param
) {
9004 if (trans_oob(state
->total_param
, 0, pscnt
)
9005 || trans_oob(smb_len(req
->inbuf
), psoff
, pscnt
)) {
9009 /* Can't use talloc here, the core routines do realloc on the
9010 * params and data. */
9011 state
->param
= (char *)SMB_MALLOC(state
->total_param
);
9012 if (state
->param
== NULL
) {
9013 DEBUG(0,("reply_trans: param malloc fail for %u "
9014 "bytes !\n", (unsigned int)state
->total_param
));
9015 SAFE_FREE(state
->data
);
9017 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
9018 END_PROFILE(SMBtrans2
);
9022 memcpy(state
->param
,smb_base(req
->inbuf
)+psoff
,pscnt
);
9025 state
->received_data
= dscnt
;
9026 state
->received_param
= pscnt
;
9028 if ((state
->received_param
== state
->total_param
) &&
9029 (state
->received_data
== state
->total_data
)) {
9031 handle_trans2(conn
, req
, state
);
9033 SAFE_FREE(state
->data
);
9034 SAFE_FREE(state
->param
);
9036 END_PROFILE(SMBtrans2
);
9040 DLIST_ADD(conn
->pending_trans
, state
);
9042 /* We need to send an interim response then receive the rest
9043 of the parameter/data bytes */
9044 reply_outbuf(req
, 0, 0);
9045 show_msg((char *)req
->outbuf
);
9046 END_PROFILE(SMBtrans2
);
9051 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
9052 SAFE_FREE(state
->data
);
9053 SAFE_FREE(state
->param
);
9055 END_PROFILE(SMBtrans2
);
9056 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
9060 /****************************************************************************
9061 Reply to a SMBtranss2
9062 ****************************************************************************/
9064 void reply_transs2(struct smb_request
*req
)
9066 connection_struct
*conn
= req
->conn
;
9067 unsigned int pcnt
,poff
,dcnt
,doff
,pdisp
,ddisp
;
9068 struct trans_state
*state
;
9070 START_PROFILE(SMBtranss2
);
9072 show_msg((const char *)req
->inbuf
);
9074 /* Windows clients expect all replies to
9075 a transact secondary (SMBtranss2 0x33)
9076 to have a command code of transact
9077 (SMBtrans2 0x32). See bug #8989
9078 and also [MS-CIFS] section 2.2.4.47.2
9081 req
->cmd
= SMBtrans2
;
9084 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
9085 END_PROFILE(SMBtranss2
);
9089 for (state
= conn
->pending_trans
; state
!= NULL
;
9090 state
= state
->next
) {
9091 if (state
->mid
== req
->mid
) {
9096 if ((state
== NULL
) || (state
->cmd
!= SMBtrans2
)) {
9097 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
9098 END_PROFILE(SMBtranss2
);
9102 /* Revise state->total_param and state->total_data in case they have
9103 changed downwards */
9105 if (SVAL(req
->vwv
+0, 0) < state
->total_param
)
9106 state
->total_param
= SVAL(req
->vwv
+0, 0);
9107 if (SVAL(req
->vwv
+1, 0) < state
->total_data
)
9108 state
->total_data
= SVAL(req
->vwv
+1, 0);
9110 pcnt
= SVAL(req
->vwv
+2, 0);
9111 poff
= SVAL(req
->vwv
+3, 0);
9112 pdisp
= SVAL(req
->vwv
+4, 0);
9114 dcnt
= SVAL(req
->vwv
+5, 0);
9115 doff
= SVAL(req
->vwv
+6, 0);
9116 ddisp
= SVAL(req
->vwv
+7, 0);
9118 state
->received_param
+= pcnt
;
9119 state
->received_data
+= dcnt
;
9121 if ((state
->received_data
> state
->total_data
) ||
9122 (state
->received_param
> state
->total_param
))
9126 if (trans_oob(state
->total_param
, pdisp
, pcnt
)
9127 || trans_oob(smb_len(req
->inbuf
), poff
, pcnt
)) {
9130 memcpy(state
->param
+pdisp
,smb_base(req
->inbuf
)+poff
,pcnt
);
9134 if (trans_oob(state
->total_data
, ddisp
, dcnt
)
9135 || trans_oob(smb_len(req
->inbuf
), doff
, dcnt
)) {
9138 memcpy(state
->data
+ddisp
, smb_base(req
->inbuf
)+doff
,dcnt
);
9141 if ((state
->received_param
< state
->total_param
) ||
9142 (state
->received_data
< state
->total_data
)) {
9143 END_PROFILE(SMBtranss2
);
9147 handle_trans2(conn
, req
, state
);
9149 DLIST_REMOVE(conn
->pending_trans
, state
);
9150 SAFE_FREE(state
->data
);
9151 SAFE_FREE(state
->param
);
9154 END_PROFILE(SMBtranss2
);
9159 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
9160 DLIST_REMOVE(conn
->pending_trans
, state
);
9161 SAFE_FREE(state
->data
);
9162 SAFE_FREE(state
->param
);
9164 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
9165 END_PROFILE(SMBtranss2
);